1
0

asm: Instruction encoding and decoding

This commit is contained in:
2026-05-31 18:29:38 +02:00
parent 103c50b71b
commit c4dbfc0480
5 changed files with 254 additions and 6 deletions

View File

@ -4,8 +4,64 @@
#include <assert.h>
#include <common.h>
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

View File

@ -9,6 +9,7 @@
#include <sys/types.h>
// # NUMBER TYPES
typedef unsigned _BitInt(4) u4;
typedef uint8_t u8;
typedef unsigned _BitInt(12) u12;
typedef uint16_t u16;

191
src/ain48.c Normal file
View File

@ -0,0 +1,191 @@
#include <ain48.h>
#include <string.h>
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
}

View File

@ -3,6 +3,7 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ain48.h>
i32 asm_main(i32 argc, char *argv[]) {
if (argc != 3) {

View File

@ -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;
}
}