From c4dbfc0480ec0aad66f3f0cc8609005ca161110b Mon Sep 17 00:00:00 2001 From: Annwan Date: Sun, 31 May 2026 18:29:38 +0200 Subject: [PATCH] asm: Instruction encoding and decoding --- include/ain48.h | 60 ++++++++++++++- include/common.h | 1 + src/ain48.c | 191 +++++++++++++++++++++++++++++++++++++++++++++++ src/asm.c | 1 + src/main.c | 7 +- 5 files changed, 254 insertions(+), 6 deletions(-) create mode 100644 src/ain48.c diff --git a/include/ain48.h b/include/ain48.h index aacd45c..5570242 100644 --- a/include/ain48.h +++ b/include/ain48.h @@ -4,8 +4,64 @@ #include #include +enum instruction_format { + AMAL, + IML, + IPL, + AMLS, + ASSS, + ASLI, + ASLR, + ASRD, +}; -// #ifdef AIN49__IMPL +enum amal_ac : u8 { + ADD = 000, + STR = 001, + MPL = 002, + DVD = 004, + RSD = 005, + DEM = 006, + ET = 010, + VEL = 011, + AUT = 012, + NAM = 014, + NEC = 015, +}; + +enum asss_ac : u8 { + RV = 00, + IRRV = 04, + NCIVC = 03, + NCRV = 02, +}; + +// clang-format off +struct instruction { + enum instruction_format format; + union { + struct { + bool s, i1, i2; enum amal_ac ac; u4 rf; + union { + u8 imm; i8 simm; + struct { + union { u4 r2; u4 imm2; i4 simm2; }; + union { u4 r1; u4 imm1; u4 simm1; }; + }; + } data; + } AMAL; + struct { u4 r; u48 imm; } IML; + struct { bool s; u4 r; union { u12 imm; i12 simm; }; } IPL; + struct { bool s; u4 rd; u4 rl; i12 imm; } AMLS; + enum asss_ac ASSS_ac; + struct { bool I, E, N, U, R; u48 imm; } ASLI; + struct { bool I, E, N, U, R; u4 rl; } ASLR; + struct { bool I, E, N, U, R; u4 rl; i12 imm; } ASRD; + }; +}; +// clang-format on + +u12 *ain48_read_instr(u12 *code, struct instruction *i); +u12 *ain48_write_instr(u12 *code, struct instruction *i); -// #endif // def AIN48__IMPL #endif // AIN48__H diff --git a/include/common.h b/include/common.h index 18d4987..6763445 100644 --- a/include/common.h +++ b/include/common.h @@ -9,6 +9,7 @@ #include // # NUMBER TYPES +typedef unsigned _BitInt(4) u4; typedef uint8_t u8; typedef unsigned _BitInt(12) u12; typedef uint16_t u16; diff --git a/src/ain48.c b/src/ain48.c new file mode 100644 index 0000000..88961e1 --- /dev/null +++ b/src/ain48.c @@ -0,0 +1,191 @@ +#include +#include + +u12 *ain48_write_instruction(u12 *code, struct instruction *i) { + u4 u4tmp; + u8 u8tmp; + switch (i->format) { + case AMAL: + *code++ = i->AMAL.ac | (i->AMAL.s ? 1 << 4 : 0) | + (i->AMAL.i1 ? 1 << 5 : 0) | (i->AMAL.i2 ? 1 << 6 : 0); + *code = ((u12)i->AMAL.rf) << 8; + if (!i->AMAL.i1) + *code |= ((u12)i->AMAL.data.r1) << 4; + if (!i->AMAL.i2) + *code |= ((u12)i->AMAL.data.r2); + if (i->AMAL.i1 && i->AMAL.i2) { + if (i->AMAL.s) + memcpy(&u8tmp, &i->AMAL.data.simm, sizeof(u8)); + else + u8tmp = i->AMAL.data.imm; + *code |= u8tmp; + } else if (i->AMAL.i1) { + if (i->AMAL.s) + memcpy(&u4tmp, &i->AMAL.data.simm1, sizeof(u4)); + else + u4tmp = i->AMAL.data.imm1; + *code |= u4tmp; + } else if (i->AMAL.i2) { + if (i->AMAL.s) + memcpy(&u4tmp, &i->AMAL.data.simm2, sizeof(u4)); + else + u4tmp = i->AMAL.data.imm2; + *code |= ((u12)u4tmp) << 4; + } + return ++code; + case IML: + *code++ = 00400 | i->IML.r; + *code++ = i->IML.imm & 07777; + *code++ = (i->IML.imm >> 12) & 07777; + *code++ = (i->IML.imm >> 24) & 07777; + *code++ = (i->IML.imm >> 36) & 07777; + return code; + case IPL: + *code++ = 00500 | (i->IPL.s ? (1 << 4) : 0) | i->IPL.r; + if (i->IPL.s) { + memcpy(code++, &i->IPL.simm, sizeof(u12)); + } else { + *code++ = i->IPL.imm; + } + return code; + case AMLS: + *code++ = 01000 | (i->AMLS.s ? 1 << 8 : 0) | (((u12)i->AMLS.rd) << 4) | + i->AMLS.rl; + memcpy(code++, &i->AMLS.imm, sizeof(u12)); + return code; + case ASSS: + *code++ = 07770 | i->ASSS_ac; + return code; + case ASLI: + *code++ = 04000 | (i->ASLI.R ? 1 << 0 : 0) | (i->ASLI.U ? 1 << 1 : 0) | + (i->ASLI.N ? 1 << 2 : 0) | (i->ASLI.E ? 1 << 3 : 0) | + (i->ASLI.I ? 1 << 4 : 0); + *code++ = i->ASLI.imm & 07777; + *code++ = (i->ASLI.imm >> 12) & 07777; + *code++ = (i->ASLI.imm >> 24) & 07777; + *code++ = (i->ASLI.imm >> 36) & 07777; + return code; + case ASLR: + *code++ = 05000 | (i->ASLR.R ? 1 << 0 : 0) | (i->ASLR.U ? 1 << 1 : 0) | + (i->ASLR.N ? 1 << 2 : 0) | (i->ASLR.E ? 1 << 3 : 0) | + (i->ASLR.I ? 1 << 4 : 0) | (((u12)i->ASLR.rl) << 5); + return code; + case ASRD: + *code++ = 05000 | (i->ASRD.R ? 1 << 0 : 0) | (i->ASRD.U ? 1 << 1 : 0) | + (i->ASRD.N ? 1 << 2 : 0) | (i->ASRD.E ? 1 << 3 : 0) | + (i->ASLR.I ? 1 << 4 : 0) | (((u12)i->ASRD.rl) << 5); + memcpy(code++, &i->ASRD.imm, sizeof(u12)); + return code; + default: + return nullptr; + } +} + +u12 *ain48_read_instr(u12 *code, struct instruction *i) { + u12 byte = *code++; + if ((byte & 07600) == 0) { // AMAL + i->format = AMAL; + i->AMAL.i1 = (byte & 00040) > 0; + i->AMAL.i2 = (byte & 00100) > 0; + i->AMAL.s = (byte & 00020) > 0; + i->AMAL.ac = (enum amal_ac) (byte & 00017); + byte = *code++; + i->AMAL.rf = (byte >> 8) & 017; + if (!i->AMAL.i1) + i->AMAL.data.r1 = (byte >> 4) & 017; + if (!i->AMAL.i2) + i->AMAL.data.r2 = byte & 017; + if (i->AMAL.i1 && i->AMAL.i2) { + if (i->AMAL.s) { + u8 tmp = byte & 0377; + memcpy(&i->AMAL.data.simm, &tmp, sizeof(i8)); + } else + i->AMAL.data.imm = byte & 0337; + } else if (i->AMAL.i1) { + if (i->AMAL.s) { + u4 tmp = byte & 017; + memcpy(&i->AMAL.data.simm1, &tmp, sizeof(i4)); + } + else + i->AMAL.data.imm1 = byte & 017; + } else if (i->AMAL.i2) { + if (i->AMAL.s) { + u4 tmp = (byte >> 4) & 017; + memcpy(&i->AMAL.data.simm2, &tmp, sizeof(i4)); + } + else + i->AMAL.data.imm2 = (byte >> 4) & 017; + } + return code; + } else if ((byte & 07600) == 00400) { // IML + i->format = IML; + i->IML.r = byte & 017; + byte = *code++; + i->IML.imm = (u48)byte; + byte = *code++; + i->IML.imm |= ((u48)byte << 12); + byte = *code++; + i->IML.imm |= ((u48)byte << 24); + byte = *code++; + i->IML.imm |= ((u48)byte << 36); + return code; + } else if ((byte & 07600) == 00600) { // IPL + i->format = IPL; + i->IPL.r = byte & 017; + i->IPL.s = (byte & 00020) > 0; + byte = *code++; + if (i->IPL.s) { + memcpy(&i->IPL.simm, &byte, sizeof(i12)); + } else { + i->IPL.imm = byte; + } + return code; + } else if ((byte & 07000) == 01000) { // AMLS + i->format = AMLS; + i->AMLS.s = (byte & 00400) > 0; + i->AMLS.rd = (byte >> 4) & 017; + i->AMLS.rl = byte & 017; + memcpy(&i->AMLS.imm, code++, sizeof(i12)); + return code; + } else if ((byte & 07770) == 07770) { // ASSS + i->format = ASSS; + i->ASSS_ac = byte & 00007; + return code; + } else if ((byte & 07000) == 04000) { // ASLI + i->format = ASLI; + i->ASLI.R = (byte & 0b1) > 0; + i->ASLI.U = (byte & 0b10) > 0; + i->ASLI.N = (byte & 0b100) > 0; + i->ASLI.E = (byte & 0b1000) > 0; + i->ASLI.I = (byte & 0b10000) > 0; + byte = *code++; + i->ASLI.imm = (u48)byte; + byte = *code++; + i->ASLI.imm |= ((u48)byte << 12); + byte = *code++; + i->ASLI.imm |= ((u48)byte << 24); + byte = *code++; + i->ASLI.imm |= ((u48)byte << 36); + return code; + } else if ((byte & 07000) == 05000) { // ASLR + i->format = ASLR; + i->ASLR.R = (byte & 0b1) > 0; + i->ASLR.U = (byte & 0b10) > 0; + i->ASLR.N = (byte & 0b100) > 0; + i->ASLR.E = (byte & 0b1000) > 0; + i->ASLR.I = (byte & 0b10000) > 0; + i->ASLR.rl = (byte >> 5) & 017; + return code; + } else if ((byte & 07000) == 06000) { // ASRD + i->format = ASRD; + i->ASRD.R = (byte & 0b1) > 0; + i->ASRD.U = (byte & 0b10) > 0; + i->ASRD.N = (byte & 0b100) > 0; + i->ASRD.E = (byte & 0b1000) > 0; + i->ASRD.I = (byte & 0b10000) > 0; + i->ASRD.rl = (byte >> 5) & 017; + memcpy(&i->ASRD.imm, code++, sizeof(i12)); + return code; + } else return nullptr; // ILLEGAL INSTRUCTION + +} diff --git a/src/asm.c b/src/asm.c index 00a5cb0..7abe1be 100644 --- a/src/asm.c +++ b/src/asm.c @@ -3,6 +3,7 @@ #include #include #include +#include i32 asm_main(i32 argc, char *argv[]) { if (argc != 3) { diff --git a/src/main.c b/src/main.c index d12cd56..51eceec 100644 --- a/src/main.c +++ b/src/main.c @@ -9,19 +9,18 @@ enum subprorgram { const char *available = (R"m( - asm -)m"); + asm)m"); i32 asm_main(i32 argc, char *argv[]); i32 main(i32 argc, char *argv[]) { if (argc < 2) { - fprintf(stderr, "No subprogram called\nAvalible subprograms:%s\n", available); + log_err("No subprogram called\nAvalible subprograms:%s", available); return 1; } if (!strcmp(argv[1], "asm")) { return asm_main(argc - 1, argv + 1); } else { - fprintf(stderr, "Unknown subprogram `%s`\nAvailable subpograms:%s", argv[1], available); + log_err("Unknown subprogram `%s`\nAvailable subpograms:%s", argv[1], available); return 1; } }