// asm8008.c #define versionName "8008 assembler" #include "asmx.h" enum { CPU_8008, }; enum instrType { o_None, // No operands o_Immediate, // one-byte immediate operand o_LImmediate, // two-byte immediate operand (mostly JMPs) o_MOV, // MOV r,r opcode o_RST, // RST instruction o_Arith, // Arithmetic instructions o_MVI, // MVI instruction o_LXI, // LXI instruciton o_INR, // INR/DCR instructions o_IN, // IN instructions o_OUT, // OUT instructions // o_Foo = o_LabelOp, }; const char I8008_regs1[] = "A B C D E H L M"; const char I8008_regs2[] = "B D H"; // new-style mnemonics static const struct OpcdRec I8008_opcdTab[] = { {"RLC", o_None, 0x02}, {"RNC", o_None, 0x03}, // also RFC {"RET", o_None, 0x07}, {"RRC", o_None, 0x0A}, {"RNZ", o_None, 0x0B}, // also RFZ {"RAL", o_None, 0x12}, {"RP", o_None, 0x13}, // also RFS {"RPO", o_None, 0x1B}, // also RFP {"RAR", o_None, 0x1A}, {"RC", o_None, 0x23}, // also RTC {"RZ", o_None, 0x2B}, // also RTZ {"RM", o_None, 0x33}, // also RTS {"RPE", o_None, 0x3B}, // also RTP {"NOP", o_None, 0xC0}, {"HLT", o_None, 0xFF}, {"ADI", o_Immediate, 0x04}, {"ACI", o_Immediate, 0x0C}, {"SUI", o_Immediate, 0x14}, {"SCI", o_Immediate, 0x1C}, // also SBI {"ANI", o_Immediate, 0x24}, // also NDI {"XRI", o_Immediate, 0x2C}, {"ORI", o_Immediate, 0x34}, {"CPI", o_Immediate, 0x3C}, {"JNC", o_LImmediate, 0x40}, // also JFC {"CNC", o_LImmediate, 0x42}, // also CFC {"JMP", o_LImmediate, 0x44}, {"CALL",o_LImmediate, 0x46}, // also CAL {"JNZ", o_LImmediate, 0x48}, // also JFZ {"CNZ", o_LImmediate, 0x4A}, // also CFZ {"JP", o_LImmediate, 0x50}, // also JFS {"CP", o_LImmediate, 0x52}, // also CFS {"JPO", o_LImmediate, 0x58}, // also JFP {"CPO", o_LImmediate, 0x5A}, // also CFP {"JC", o_LImmediate, 0x60}, // also JTC {"CC", o_LImmediate, 0x62}, // also CTC {"JZ", o_LImmediate, 0x68}, // also JTZ {"CZ", o_LImmediate, 0x6A}, // also CTZ {"JM", o_LImmediate, 0x70}, // also JTS {"CM", o_LImmediate, 0x72}, // also CTS {"JPE", o_LImmediate, 0x78}, // also JTP {"CPE", o_LImmediate, 0x7A}, // also CTP {"MOV", o_MOV, 0xC0}, {"RST", o_RST, 0x05}, {"ADD", o_Arith, 0x80}, // also ADA..ADM {"ADC", o_Arith, 0x88}, // also ACA..ACM {"SUB", o_Arith, 0x90}, // also SUA..SUM {"SBB", o_Arith, 0x98}, // also SBA..SBM {"ANA", o_Arith, 0xA0}, // also NDA..NDM {"XRA", o_Arith, 0xA8}, // also XRA..XRM {"ORA", o_Arith, 0xB0}, // also ORA..ORM {"CMP", o_Arith, 0xB8}, // also CRA..CRM {"MVI", o_MVI, 0x06}, {"LXI", o_LXI, 0x16}, {"INR", o_INR, 0x00}, // also INA..INM {"DCR", o_INR, 0x01}, // also DCA..DCM {"IN", o_IN, 0x41}, // also INP {"OUT", o_OUT, 0x41}, {"", o_Illegal, 0} }; // old-style mnemonics const struct OpcdRec I8008old_opcdTab[] = { {"RLC", o_None, 0x02}, {"RFC", o_None, 0x03}, {"RET", o_None, 0x07}, {"RRC", o_None, 0x0A}, {"RFZ", o_None, 0x0B}, {"RAL", o_None, 0x12}, {"RFS", o_None, 0x13}, {"RFP", o_None, 0x1B}, {"RAR", o_None, 0x1A}, {"RTC", o_None, 0x23}, {"RTZ", o_None, 0x2B}, {"RTS", o_None, 0x33}, {"RTP", o_None, 0x3B}, {"NOP", o_None, 0xC0}, {"HLT", o_None, 0xFF}, {"ADI", o_Immediate, 0x04}, {"ACI", o_Immediate, 0x0C}, {"SUI", o_Immediate, 0x14}, {"SBI", o_Immediate, 0x1C}, {"NDI", o_Immediate, 0x24}, {"XRI", o_Immediate, 0x2C}, {"ORI", o_Immediate, 0x34}, {"CPI", o_Immediate, 0x3C}, {"JFC", o_LImmediate, 0x40}, {"CFC", o_LImmediate, 0x42}, {"JMP", o_LImmediate, 0x44}, {"CAL", o_LImmediate, 0x46}, {"JFZ", o_LImmediate, 0x48}, {"CFZ", o_LImmediate, 0x4A}, {"JFS", o_LImmediate, 0x50}, {"CFS", o_LImmediate, 0x52}, {"JFP", o_LImmediate, 0x58}, {"CFP", o_LImmediate, 0x5A}, {"JTC", o_LImmediate, 0x60}, {"CTC", o_LImmediate, 0x62}, {"JTZ", o_LImmediate, 0x68}, {"CTZ", o_LImmediate, 0x6A}, {"JTS", o_LImmediate, 0x70}, {"CTS", o_LImmediate, 0x72}, {"JTP", o_LImmediate, 0x78}, {"CTP", o_LImmediate, 0x7A}, {"LAA", o_None, 0xC0}, {"LAB", o_None, 0xC1}, {"LAC", o_None, 0xC2}, {"LAD", o_None, 0xC3}, {"LAE", o_None, 0xC4}, {"LAH", o_None, 0xC5}, {"LAL", o_None, 0xC6}, {"LAM", o_None, 0xC7}, {"LBA", o_None, 0xC8}, {"LBB", o_None, 0xC9}, {"LBC", o_None, 0xCA}, {"LBD", o_None, 0xCB}, {"LBE", o_None, 0xCC}, {"LBH", o_None, 0xCD}, {"LBL", o_None, 0xCE}, {"LBM", o_None, 0xCF}, {"LCA", o_None, 0xD0}, {"LCB", o_None, 0xD1}, {"LCC", o_None, 0xD2}, {"LCD", o_None, 0xD3}, {"LCE", o_None, 0xD4}, {"LCH", o_None, 0xD5}, {"LCL", o_None, 0xD6}, {"LCM", o_None, 0xD7}, {"LDA", o_None, 0xD8}, {"LDB", o_None, 0xD9}, {"LDC", o_None, 0xDA}, {"LDD", o_None, 0xDB}, {"LDE", o_None, 0xDC}, {"LDH", o_None, 0xDD}, {"LDL", o_None, 0xDE}, {"LDM", o_None, 0xDF}, {"LEA", o_None, 0xE0}, {"LEB", o_None, 0xE1}, {"LEC", o_None, 0xE2}, {"LED", o_None, 0xE3}, {"LEE", o_None, 0xE4}, {"LEH", o_None, 0xE5}, {"LEL", o_None, 0xE6}, {"LEM", o_None, 0xE7}, {"LHA", o_None, 0xE8}, {"LHB", o_None, 0xE9}, {"LHC", o_None, 0xEA}, {"LHD", o_None, 0xEB}, {"LHE", o_None, 0xEC}, {"LHH", o_None, 0xED}, {"LHL", o_None, 0xEE}, {"LHM", o_None, 0xEF}, {"LLA", o_None, 0xF0}, {"LLB", o_None, 0xF1}, {"LLC", o_None, 0xF2}, {"LLD", o_None, 0xF3}, {"LLE", o_None, 0xF4}, {"LLH", o_None, 0xF5}, {"LLL", o_None, 0xF6}, {"LLM", o_None, 0xF7}, {"LMA", o_None, 0xF8}, {"LMB", o_None, 0xF9}, {"LMC", o_None, 0xFA}, {"LMD", o_None, 0xFB}, {"LME", o_None, 0xFC}, {"LMH", o_None, 0xFD}, {"LML", o_None, 0xFE}, {"ADA", o_None, 0x80}, {"ADB", o_None, 0x81}, {"ADC", o_None, 0x82}, {"ADD", o_None, 0x83}, {"ADE", o_None, 0x84}, {"ADH", o_None, 0x85}, {"ADL", o_None, 0x86}, {"ADM", o_None, 0x87}, {"ACA", o_None, 0x88}, {"ACB", o_None, 0x89}, {"ACC", o_None, 0x8A}, {"ACD", o_None, 0x8B}, {"ACE", o_None, 0x8C}, {"ACH", o_None, 0x8D}, {"ACL", o_None, 0x8E}, {"ACM", o_None, 0x8F}, {"SUA", o_None, 0x90}, {"SUB", o_None, 0x91}, {"SUC", o_None, 0x92}, {"SUD", o_None, 0x93}, {"SUE", o_None, 0x94}, {"SUH", o_None, 0x95}, {"SUL", o_None, 0x96}, {"SUM", o_None, 0x97}, {"SBA", o_None, 0x98}, {"SBB", o_None, 0x99}, {"SBC", o_None, 0x9A}, {"SBD", o_None, 0x9B}, {"SBE", o_None, 0x9C}, {"SBH", o_None, 0x9D}, {"SBL", o_None, 0x9E}, {"SBM", o_None, 0x9F}, {"NDA", o_None, 0xA0}, {"NDB", o_None, 0xA1}, {"NDC", o_None, 0xA2}, {"NDD", o_None, 0xA3}, {"NDE", o_None, 0xA4}, {"NDH", o_None, 0xA5}, {"NDL", o_None, 0xA6}, {"NDM", o_None, 0xA7}, {"XRA", o_None, 0xA8}, {"XRB", o_None, 0xA9}, {"XRC", o_None, 0xAA}, {"XRD", o_None, 0xAB}, {"XRE", o_None, 0xAC}, {"XRH", o_None, 0xAD}, {"XRL", o_None, 0xAE}, {"XRM", o_None, 0xAF}, {"ORA", o_None, 0xB0}, {"ORB", o_None, 0xB1}, {"ORC", o_None, 0xB2}, {"ORD", o_None, 0xB3}, {"ORL", o_None, 0xB4}, {"ORH", o_None, 0xB5}, {"ORL", o_None, 0xB6}, {"ORM", o_None, 0xB7}, {"CPA", o_None, 0xB8}, {"CPB", o_None, 0xB9}, {"CPC", o_None, 0xBA}, {"CPD", o_None, 0xBB}, {"CPL", o_None, 0xBC}, {"CPH", o_None, 0xBD}, {"CPL", o_None, 0xBE}, {"CPM", o_None, 0xBF}, {"LAI", o_Immediate, 0x06}, {"LBI", o_Immediate, 0x0E}, {"LCI", o_Immediate, 0x16}, {"LDI", o_Immediate, 0x1E}, {"LEI", o_Immediate, 0x26}, {"LHI", o_Immediate, 0x2E}, {"LLI", o_Immediate, 0x36}, {"LMI", o_Immediate, 0x3E}, {"INA", o_None, 0x00}, {"INB", o_None, 0x08}, {"INC", o_None, 0x10}, {"IND", o_None, 0x18}, {"INE", o_None, 0x20}, {"INH", o_None, 0x28}, {"INL", o_None, 0x30}, {"INM", o_None, 0x38}, {"DCA", o_None, 0x01}, {"DCB", o_None, 0x09}, {"DCC", o_None, 0x11}, {"DCD", o_None, 0x19}, {"DCE", o_None, 0x21}, {"DCH", o_None, 0x29}, {"DCL", o_None, 0x31}, {"DCM", o_None, 0x39}, {"INP", o_IN, 0x41}, {"OUT", o_OUT, 0x41}, {"", o_Illegal, 0} }; // -------------------------------------------------------------- static int I8008_DoCPUOpcode(int typ, int parm) { int val, reg1, reg2; Str255 word; char *oldLine; // int token; switch (typ) { case o_None: InstrB(parm & 255); break; case o_Immediate: val = Eval(); InstrBB(parm & 0xFF, val); break; case o_LImmediate: val = Eval(); InstrBW(parm, val); break; case o_MOV: GetWord(word); reg1 = FindReg(word, I8008_regs1); if (reg1 < 0) { IllegalOperand(); } else { oldLine = linePtr; if (GetWord(word) != ',') { linePtr = oldLine; Comma(); } else { GetWord(word); reg2 = FindReg(word, I8008_regs1); if (reg2 < 0 || (reg1 == 7 && reg2 == 7)) { IllegalOperand(); } else { InstrB(parm + (reg1 << 3) + reg2); } } } break; case o_RST: val = Eval(); if (0 <= val && val <= 7) { InstrB(parm + val*8); } else { IllegalOperand(); } break; case o_Arith: GetWord(word); reg1 = FindReg(word, I8008_regs1); if (reg1 < 0) { IllegalOperand(); } else { InstrB(parm + reg1); } break; case o_MVI: GetWord(word); reg1 = FindReg(word, I8008_regs1); if (reg1 < 0) { IllegalOperand(); } else { oldLine = linePtr; if (GetWord(word) != ',') { linePtr = oldLine; Comma(); } else { val = Eval(); InstrBB(parm + (reg1 << 3), val); } } break; case o_LXI: GetWord(word); reg1 = FindReg(word, I8008_regs2); if (reg1 < 0) { IllegalOperand(); } else { oldLine = linePtr; if (GetWord(word) != ',') { linePtr = oldLine; Comma(); } else { val = Eval(); InstrBBBB(parm + (reg1 << 4), val & 0xFF, parm + (reg1 << 4) - 8, val >> 8); } } break; case o_INR: GetWord(word); reg1 = FindReg(word, I8008_regs1); if ((reg1 < 0) || (reg1 == 0) || (reg1 == 7)) { IllegalOperand(); } else { InstrB(parm + (reg1 << 3)); } break; case o_IN: val = Eval(); if ((val < 0) || (val > 7)) { IllegalOperand(); } else { InstrB(parm + val*2); } break; case o_OUT: val = Eval(); if ((val < 8) || (val > 31)) { IllegalOperand(); } else { InstrB(parm + val*2); } break; default: return 0; break; } return 1; } void Asm8008Init(void) { void *p = AddAsm(versionName, &I8008_DoCPUOpcode, NULL, NULL); AddCPU(p, "8008", CPU_8008, LITTLE_END, ADDR_16, LIST_24, 8, 0, I8008_opcdTab); AddCPU(p, "8008NEW", CPU_8008, LITTLE_END, ADDR_16, LIST_24, 8, 0, I8008_opcdTab); AddCPU(p, "8008OLD", CPU_8008, LITTLE_END, ADDR_16, LIST_24, 8, 0, I8008old_opcdTab); }