192 lines
6.5 KiB
C
192 lines
6.5 KiB
C
#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
|
|
|
|
}
|