// asmscmp.c #define versionName "SC/MP assembler" #include "asmx.h" enum { o_None, // - no operands o_Immed, // - immediate byte o_PtrJmp, // - JMP/JP/JZ/JNZ o_Ptr, // - indexed ptr + disp o_MPtr, // - indexed mptr + disp o_XP, // - XPAL/XPAH/XPPC o_JS, // - Jump to Subroutine pseudo-op o_LDPI, // - Load Pointer Immediate pseudo-op // o_Foo = o_LabelOp, }; enum cputype { CPU_SCMP }; static const struct OpcdRec SCMP_opcdTab[] = { {"HALT", o_None, 0x00}, {"XAE", o_None, 0x01}, {"CCL", o_None, 0x02}, {"SCL", o_None, 0x03}, {"DINT", o_None, 0x04}, {"IEN", o_None, 0x05}, {"CSA", o_None, 0x06}, {"CAS", o_None, 0x07}, {"NOP", o_None, 0x08}, {"SIO", o_None, 0x19}, {"SR", o_None, 0x1C}, {"SRL", o_None, 0x1D}, {"RR", o_None, 0x1E}, {"RRL", o_None, 0x1F}, // pointer but not P0? {"XPAL", o_XP, 0x30}, {"XPAH", o_XP, 0x34}, {"XPPC", o_XP, 0x3C}, {"LDE", o_None, 0x40}, {"ANE", o_None, 0x50}, {"ORE", o_None, 0x58}, {"XRE", o_None, 0x60}, {"DAE", o_None, 0x68}, {"ADE", o_None, 0x70}, {"CAE", o_None, 0x78}, {"DLY", o_Immed, 0x8F}, // JMP ptr+disp {"JMP", o_PtrJmp, 0x90}, {"JP", o_PtrJmp, 0x94}, {"JZ", o_PtrJmp, 0x98}, {"JNZ", o_PtrJmp, 0x9C}, // ILD/DLD ptr+disp {"ILD", o_Ptr, 0xA8}, {"DLD", o_Ptr, 0xB8}, // mptr+disp {"LD", o_MPtr, 0xC0}, {"ST", o_MPtr, 0xC8}, {"AND", o_MPtr, 0xD0}, {"OR", o_MPtr, 0xD8}, {"XOR", o_MPtr, 0xE0}, {"DAD", o_MPtr, 0xE8}, {"ADD", o_MPtr, 0xF0}, {"CAD", o_MPtr, 0xF8}, // immed {"LDI", o_Immed, 0xC4}, // {"STI", o_Immed, 0xCC}, {"ANI", o_Immed, 0xD4}, {"ORI", o_Immed, 0xDC}, {"XRI", o_Immed, 0xE4}, {"DAI", o_Immed, 0xEC}, {"ADI", o_Immed, 0xF4}, {"CAI", o_Immed, 0xFC}, // pseudo-ops {"JS", o_JS, 0}, {"LDPI", o_LDPI, 0}, // note that this is a common macro {"", o_Illegal, 0} }; static const char P_regs[] = "P0 P1 P2 P3"; // -------------------------------------------------------------- static int EvalSCMPBranch(int instrLen) { int32_t val = Eval(); int32_t ofs = val - locPtr - instrLen; if (!errFlag && (locPtr & 0xF000) != (val & 0xF000)) { Warning("Reference crosses page boundary"); } if (!errFlag && (ofs < -128 || ofs > 127)) { if (instrLen == 1) { Error("Short reference out of range"); } else { Error("Short branch out of range"); } } return ofs & 0xFF; } static int SCMP_DoCPUOpcode(int typ, int parm) { int val;//, val2, val3; Str255 word; int token; char reg; char *oldLine = linePtr; switch (typ) { case o_None: // - no operands InstrB(parm); break; case o_Immed: // - immediate byte val = EvalByte(); InstrBB(parm, val); break; case o_PtrJmp: // - JMP/JP/JZ/JNZ case o_Ptr: // - indexed ptr + disp case o_MPtr: // - indexed mptr + disp if (typ == o_MPtr) { // check for "@ofs(Pn)" token = GetWord(word); if (token == '@') { // check for "@(Pn)" oldLine = linePtr; token = GetWord(word); if (token == '(') { reg = GetReg(P_regs); if (reg >= 0) { Expect(")"); InstrBB(parm + 4 + reg, 0); break; } } linePtr = oldLine; val = Eval(); Expect("("); reg = GetReg(P_regs); if (reg < 1) break; Expect(")"); CheckStrictByte(val); InstrBB(parm + 4 + reg, val); break; } linePtr = oldLine; } // check for "(Pn)" token = GetWord(word); if (token == '(') { reg = GetReg(P_regs); if (reg >= 0) { Expect(")"); InstrBB(parm + reg, 0); break; } } linePtr = oldLine; val = Eval(); token = GetWord(word); if (token == '(') { // ofs(Pn) reg = GetReg(P_regs); if (reg < 1) break; Expect(")"); CheckStrictByte(val); InstrBB(parm + reg, val); } else if (token) { IllegalOperand(); } else { // PC-relative linePtr = oldLine; val = EvalSCMPBranch(2 - (typ == o_MPtr)); InstrBB(parm, val); } break; case o_XP: // - XPAL/XPAH/XPPC reg = GetReg(P_regs); if (reg < 0) break; InstrB(parm + reg); break; case o_JS: // - Jump to Subroutine pseudo-op // JS Pn,addr -> LDI H(addr-1) | XPAH Pn // LDI L(addr-1) | XPAL Pn | XPPC Pn case o_LDPI: // - Load Pointer Immediate pseudo-op // LDPI Pn,addr -> LDI H(addr) | XPAH Pn // LDI L(addr) | XPAL Pn reg = GetReg(P_regs); if (reg < 1) { IllegalOperand(); break; } Comma(); val = Eval() - (typ == o_JS); InstrClear(); InstrAdd3(0xC40034 + reg + (val & 0xFF00)); InstrAdd3(0xC40030 + reg + (val & 0x00FF)*256); if (typ == o_JS) { InstrAddB(0x3C + reg); } break; default: return 0; break; } return 1; } void AsmSCMPInit(void) { void *p = AddAsm(versionName, &SCMP_DoCPUOpcode, NULL, NULL); AddCPU(p, "SCMP", CPU_SCMP, BIG_END, ADDR_16, LIST_24, 8, 0, SCMP_opcdTab); }