ref: ea61a2a8e8601d5b732d2c13257413ad4f864b85
dir: /src/DISAM68K.c/
/* DISAM68K.c Copyright (C) 2010 Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* DISAssemble Motorola 68K instructions. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "ENDIANAC.h" #include "MYOSGLUE.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "M68KITAB.h" #endif #include "DISAM68K.h" LOCALVAR ui5r Disasm_pc; /* don't use get_vm_byte/get_vm_word/get_vm_long so as to be sure of no side effects (if pc points to memory mapped device) */ LOCALVAR ui3p Disasm_pcp; LOCALVAR ui5r Disasm_pc_blockmask; LOCALVAR ui3b Disasm_pcp_dummy[2] = { 0, 0 }; IMPORTFUNC ATTep FindATTel(CPTR addr); LOCALPROC Disasm_Find_pcp(void) { ATTep p; p = FindATTel(Disasm_pc); if (0 == (p->Access & kATTA_readreadymask)) { Disasm_pcp = Disasm_pcp_dummy; Disasm_pc_blockmask = 0; } else { Disasm_pc_blockmask = p->usemask & ~ p->cmpmask; Disasm_pc_blockmask = Disasm_pc_blockmask & ~ (Disasm_pc_blockmask + 1); Disasm_pcp = p->usebase + (Disasm_pc & p->usemask); } } LOCALFUNC ui4r Disasm_nextiword(void) /* NOT sign extended */ { ui4r r = do_get_mem_word(Disasm_pcp); Disasm_pcp += 2; Disasm_pc += 2; if (0 == (Disasm_pc_blockmask & Disasm_pc)) { Disasm_Find_pcp(); } return r; } LOCALINLINEFUNC ui3r Disasm_nextibyte(void) { return (ui3b) Disasm_nextiword(); } LOCALFUNC ui5r Disasm_nextilong(void) { ui5r hi = Disasm_nextiword(); ui5r lo = Disasm_nextiword(); ui5r r = ((hi << 16) & 0xFFFF0000) | (lo & 0x0000FFFF); return r; } LOCALPROC Disasm_setpc(CPTR newpc) { if (newpc != Disasm_pc) { Disasm_pc = newpc; Disasm_Find_pcp(); } } LOCALVAR ui5b Disasm_opcode; LOCALVAR ui5b Disasm_opsize; #define Disasm_b76 ((Disasm_opcode >> 6) & 3) #define Disasm_b8 ((Disasm_opcode >> 8) & 1) #define Disasm_mode ((Disasm_opcode >> 3) & 7) #define Disasm_reg (Disasm_opcode & 7) #define Disasm_md6 ((Disasm_opcode >> 6) & 7) #define Disasm_rg9 ((Disasm_opcode >> 9) & 7) LOCALPROC DisasmOpSizeFromb76(void) { Disasm_opsize = 1 << Disasm_b76; switch (Disasm_opsize) { case 1 : dbglog_writeCStr(".B"); break; case 2 : dbglog_writeCStr(".W"); break; case 4 : dbglog_writeCStr(".L"); break; } } LOCALPROC DisasmModeRegister(ui5b themode, ui5b thereg) { switch (themode) { case 0 : dbglog_writeCStr("D"); dbglog_writeHex(thereg); break; case 1 : dbglog_writeCStr("A"); dbglog_writeHex(thereg); break; case 2 : dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 3 : dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")+"); break; case 4 : dbglog_writeCStr("-(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 5 : dbglog_writeHex(Disasm_nextiword()); dbglog_writeCStr("(A"); dbglog_writeHex(thereg); dbglog_writeCStr(")"); break; case 6 : dbglog_writeCStr("???"); #if 0 ArgKind = AKMemory; ArgAddr.mem = get_disp_ea(m68k_areg(thereg)); #endif break; case 7 : switch (thereg) { case 0 : dbglog_writeCStr("("); dbglog_writeHex(Disasm_nextiword()); dbglog_writeCStr(")"); break; case 1 : dbglog_writeCStr("("); dbglog_writeHex(Disasm_nextilong()); dbglog_writeCStr(")"); break; case 2 : { ui5r s = Disasm_pc; s += ui5r_FromSWord(Disasm_nextiword()); dbglog_writeCStr("("); dbglog_writeHex(s); dbglog_writeCStr(")"); } break; case 3 : dbglog_writeCStr("???"); #if 0 ArgKind = AKMemory; s = get_disp_ea(Disasm_pc); #endif break; case 4 : dbglog_writeCStr("#"); if (Disasm_opsize == 2) { dbglog_writeHex(Disasm_nextiword()); } else if (Disasm_opsize < 2) { dbglog_writeHex(Disasm_nextibyte()); } else { dbglog_writeHex(Disasm_nextilong()); } break; } break; case 8 : dbglog_writeCStr("#"); dbglog_writeHex(thereg); break; } } LOCALPROC DisasmStartOne(char *s) { dbglog_writeCStr(s); } LOCALPROC Disasm_xxxxxxxxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmEaD_xxxxdddxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); dbglog_writeCStr("D"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmI_xxxxxxxxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); if (Disasm_opsize == 2) { dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); } else if (Disasm_opsize < 2) { dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); } else { dbglog_writeHex(ui5r_FromSLong(Disasm_nextilong())); } dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmsAA_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); DisasmModeRegister(3, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(3, Disasm_rg9); dbglog_writeReturn(); } LOCALFUNC ui5r Disasm_octdat(ui5r x) { if (x == 0) { return 8; } else { return x; } } LOCALPROC Disasm_xxxxnnnxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmDEa_xxxxdddxssmmmrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" D"); dbglog_writeHex(Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmEaA_xxxxdddsxxmmmrrr(char *s) { DisasmStartOne(s); Disasm_opsize = Disasm_b8 * 2 + 2; if (Disasm_opsize == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmDD_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROC DisasmAAs_xxxxdddxssxxxrrr(char *s) { DisasmStartOne(s); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(4, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(4, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTst(void) { /* Tst 01001010ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("TST"); } LOCALPROCUSEDONCE DisasmCompare(void) { /* Cmp 1011ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("CMP"); } LOCALPROCUSEDONCE DisasmCmpI(void) { /* CMPI 00001100ssmmmrrr */ DisasmI_xxxxxxxxssmmmrrr("CMP"); } LOCALPROCUSEDONCE DisasmCmpM(void) { /* CmpM 1011ddd1ss001rrr */ DisasmsAA_xxxxdddxssxxxrrr("CMP"); } LOCALPROC DisasmCC(void) { switch ((Disasm_opcode >> 8) & 15) { case 0: dbglog_writeCStr("T"); break; case 1: dbglog_writeCStr("F"); break; case 2: dbglog_writeCStr("HI"); break; case 3: dbglog_writeCStr("LS"); break; case 4: dbglog_writeCStr("CC"); break; case 5: dbglog_writeCStr("CS"); break; case 6: dbglog_writeCStr("NE"); break; case 7: dbglog_writeCStr("EQ"); break; case 8: dbglog_writeCStr("VC"); break; case 9: dbglog_writeCStr("VS"); break; case 10: dbglog_writeCStr("P"); break; case 11: dbglog_writeCStr("MI"); break; case 12: dbglog_writeCStr("GE"); break; case 13: dbglog_writeCStr("LT"); break; case 14: dbglog_writeCStr("GT"); break; case 15: dbglog_writeCStr("LE"); break; default: break; /* shouldn't get here */ } } LOCALPROCUSEDONCE DisasmBcc(void) { /* Bcc 0110ccccnnnnnnnn */ ui5b src = ((ui5b)Disasm_opcode) & 255; ui5r s = Disasm_pc; if (0 == ((Disasm_opcode >> 8) & 15)) { DisasmStartOne("BRA"); } else { DisasmStartOne("B"); DisasmCC(); } dbglog_writeCStr(" "); if (src == 0) { s += ui5r_FromSWord(Disasm_nextiword()); } else #if Use68020 if (src == 255) { s += ui5r_FromSLong(Disasm_nextilong()); /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ } else #endif { s += ui5r_FromSByte(src); } dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDBcc(void) { /* DBcc 0101cccc11001ddd */ ui5r s = Disasm_pc; DisasmStartOne("DB"); DisasmCC(); dbglog_writeCStr(" D"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); s += (si5b)(si4b)Disasm_nextiword(); dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSwap(void) { /* Swap 0100100001000rrr */ DisasmStartOne("SWAP D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmMove(void) /* MOVE */ { DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_md6, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveL(void) { DisasmStartOne("MOVE.L "); Disasm_opsize = 4; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveW(void) { DisasmStartOne("MOVE.W "); Disasm_opsize = 2; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveB(void) { DisasmStartOne("MOVE.B "); Disasm_opsize = 1; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveAL(void) { DisasmStartOne("MOVEA.L "); Disasm_opsize = 4; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveAW(void) { DisasmStartOne("MOVEA.W "); Disasm_opsize = 2; DisasmMove(); } LOCALPROCUSEDONCE DisasmMoveQ(void) { /* MoveQ 0111ddd0nnnnnnnn */ DisasmStartOne("MOVEQ #"); dbglog_writeHex(ui5r_FromSByte(Disasm_opcode)); dbglog_writeCStr(", D"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAddEaR(void) { DisasmEaD_xxxxdddxssmmmrrr("ADD"); } LOCALPROCUSEDONCE DisasmAddQ(void) { /* AddQ 0101nnn0ssmmmrrr */ Disasm_xxxxnnnxssmmmrrr("ADDQ"); } LOCALPROCUSEDONCE DisasmAddI(void) { DisasmI_xxxxxxxxssmmmrrr("ADDI"); } LOCALPROCUSEDONCE DisasmAddREa(void) { DisasmDEa_xxxxdddxssmmmrrr("ADD"); } LOCALPROCUSEDONCE DisasmSubEaR(void) { DisasmEaD_xxxxdddxssmmmrrr("SUB"); } LOCALPROCUSEDONCE DisasmSubQ(void) { /* SubQ 0101nnn1ssmmmrrr */ Disasm_xxxxnnnxssmmmrrr("SUBQ"); } LOCALPROCUSEDONCE DisasmSubI(void) { DisasmI_xxxxxxxxssmmmrrr("SUBI"); } LOCALPROCUSEDONCE DisasmSubREa(void) { DisasmDEa_xxxxdddxssmmmrrr("SUB"); } LOCALPROCUSEDONCE DisasmLea(void) { /* Lea 0100aaa111mmmrrr */ DisasmStartOne("LEA "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmPEA(void) { /* PEA 0100100001mmmrrr */ DisasmStartOne("PEA "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmALine(void) { DisasmStartOne("$"); dbglog_writeHex(Disasm_opcode); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBsr(void) { ui5b src = ((ui5b)Disasm_opcode) & 255; ui5r s = Disasm_pc; DisasmStartOne("BSR "); if (src == 0) { s += (si5b)(si4b)Disasm_nextiword(); } else #if Use68020 if (src == 255) { s += (si5b)Disasm_nextilong(); /* ReportAbnormal("long branch in DoCode6"); */ /* Used by various Apps */ } else #endif { s += (si5b)(si3b)src; } dbglog_writeHex(s); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmJsr(void) { /* Jsr 0100111010mmmrrr */ DisasmStartOne("JSR "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmLinkA6(void) { DisasmStartOne("LINK A6, "); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMRmM(void) { /* MOVEM reg to mem 0100100011s100rrr */ si4b z; ui5r regmask; DisasmStartOne("MOVEM"); if (Disasm_b76 == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); regmask = Disasm_nextiword(); for (z = 16; --z >= 0; ) { if ((regmask & (1 << (15 - z))) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } dbglog_writeCStr(", -(A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(")"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMApR(void) { /* MOVEM mem to reg 0100110011s011rrr */ si4b z; ui5r regmask; regmask = Disasm_nextiword(); DisasmStartOne("MOVEM"); if (Disasm_b76 == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" (A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(")+, "); for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmUnlkA6(void) { DisasmStartOne("UNLINK A6"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRts(void) { /* Rts 0100111001110101 */ DisasmStartOne("RTS"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmJmp(void) { /* JMP 0100111011mmmrrr */ DisasmStartOne("JMP "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmClr(void) { /* Clr 01000010ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("CLR"); } LOCALPROCUSEDONCE DisasmAddA(void) { /* ADDA 1101dddm11mmmrrr */ DisasmEaA_xxxxdddsxxmmmrrr("ADDA"); } LOCALPROCUSEDONCE DisasmAddQA(void) { /* 0101nnn0ss001rrr */ DisasmStartOne("ADDQA #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSubQA(void) { /* 0101nnn1ss001rrr */ DisasmStartOne("SUBQA #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmSubA(void) { /* SUBA 1001dddm11mmmrrr */ DisasmEaA_xxxxdddsxxmmmrrr("SUBA"); } LOCALPROCUSEDONCE DisasmCmpA(void) { DisasmStartOne("CMPA "); Disasm_opsize = Disasm_b8 * 2 + 2; DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", A"); dbglog_writeHex(Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAddXd(void) { DisasmDD_xxxxdddxssxxxrrr("ADDX"); } LOCALPROCUSEDONCE DisasmAddXm(void) { DisasmAAs_xxxxdddxssxxxrrr("ADDX"); } LOCALPROCUSEDONCE DisasmSubXd(void) { DisasmDD_xxxxdddxssxxxrrr("SUBX"); } LOCALPROCUSEDONCE DisasmSubXm(void) { DisasmAAs_xxxxdddxssxxxrrr("SUBX"); } LOCALPROC DisasmBinOp1(ui5r x) { if (! Disasm_b8) { switch (x) { case 0: DisasmStartOne("ASR"); break; case 1: DisasmStartOne("LSR"); break; case 2: DisasmStartOne("RXR"); break; case 3: DisasmStartOne("ROR"); break; default: /* should not get here */ break; } } else { switch (x) { case 0: DisasmStartOne("ASL"); break; case 1: DisasmStartOne("LSL"); break; case 2: DisasmStartOne("RXL"); break; case 3: DisasmStartOne("ROL"); break; default: /* should not get here */ break; } } } LOCALPROCUSEDONCE DisasmRolopNM(void) { DisasmBinOp1(Disasm_rg9); dbglog_writeCStr(" "); Disasm_opsize = 2; DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRolopND(void) { /* 1110cccdss0ttddd */ DisasmBinOp1(Disasm_mode & 3); DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(Disasm_octdat(Disasm_rg9)); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRolopDD(void) { /* 1110rrrdss1ttddd */ DisasmBinOp1(Disasm_mode & 3); DisasmOpSizeFromb76(); dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROC DisasmBinBitOp1(void) { switch (Disasm_b76) { case 0: DisasmStartOne("BTST"); break; case 1: DisasmStartOne("BCHG"); break; case 2: DisasmStartOne("BCLR"); break; case 3: DisasmStartOne("BSET"); break; default: /* should not get here */ break; } } LOCALPROCUSEDONCE DisasmBitOpDD(void) { /* dynamic bit, Opcode = 0000ddd1tt000rrr */ DisasmBinBitOp1(); Disasm_opsize = 4; dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpDM(void) { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ DisasmBinBitOp1(); Disasm_opsize = 1; dbglog_writeCStr(" "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpND(void) { /* static bit 00001010tt000rrr */ DisasmBinBitOp1(); Disasm_opsize = 4; dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmBitOpNM(void) { /* static bit 00001010ttmmmrrr */ DisasmBinBitOp1(); Disasm_opsize = 1; dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSByte(Disasm_nextibyte())); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAndI(void) { DisasmI_xxxxxxxxssmmmrrr("ANDI"); } LOCALPROCUSEDONCE DisasmAndDEa(void) { /* And 1100ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("AND"); } LOCALPROCUSEDONCE DisasmAndEaD(void) { /* And 1100ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("AND"); } LOCALPROCUSEDONCE DisasmOrI(void) { DisasmI_xxxxxxxxssmmmrrr("ORI"); } LOCALPROCUSEDONCE DisasmOrDEa(void) { /* OR 1000ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("OR"); } LOCALPROCUSEDONCE DisasmOrEaD(void) { /* OR 1000ddd0ssmmmrrr */ DisasmEaD_xxxxdddxssmmmrrr("OR"); } LOCALPROCUSEDONCE DisasmEorI(void) { DisasmI_xxxxxxxxssmmmrrr("EORI"); } LOCALPROCUSEDONCE DisasmEor(void) { /* Eor 1011ddd1ssmmmrrr */ DisasmDEa_xxxxdddxssmmmrrr("EOR"); } LOCALPROCUSEDONCE DisasmNot(void) { /* Not 01000110ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NOT"); } LOCALPROCUSEDONCE DisasmScc(void) { /* Scc 0101cccc11mmmrrr */ Disasm_opsize = 1; DisasmStartOne("S"); DisasmCC(); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmEXTL(void) { DisasmStartOne("EXT.L D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmEXTW(void) { DisasmStartOne("EXT.W D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmNeg(void) { /* Neg 01000100ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NEG"); } LOCALPROCUSEDONCE DisasmNegX(void) { /* NegX 01000000ssmmmrrr */ Disasm_xxxxxxxxssmmmrrr("NEGX"); } LOCALPROCUSEDONCE DisasmMulU(void) { /* MulU 1100ddd011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MULU "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMulS(void) { /* MulS 1100ddd111mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MULS "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDivU(void) { /* DivU 1000ddd011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("DIVU "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmDivS(void) { /* DivS 1000ddd111mmmrrr */ Disasm_opsize = 2; DisasmStartOne("DIVS "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgdd(void) { /* Exg 1100ddd101000rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgaa(void) { /* Exg 1100ddd101001rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(1, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(1, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmExgda(void) { /* Exg 1100ddd110001rrr */ Disasm_opsize = 4; DisasmStartOne("EXG "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(1, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveCCREa(void) { /* Move from CCR 0100001011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE CCR, "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveEaCR(void) { /* 0100010011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", CCR"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveSREa(void) { /* Move from SR 0100000011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE SR, "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveEaSR(void) { /* 0100011011mmmrrr */ Disasm_opsize = 2; DisasmStartOne("MOVE "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", SR"); dbglog_writeReturn(); } LOCALPROC DisasmBinOpStatusCCR(void) { switch (Disasm_rg9) { case 0 : DisasmStartOne("OR"); break; case 1 : DisasmStartOne("AND"); break; case 5 : DisasmStartOne("EOR"); break; default: /* should not happen */ break; } DisasmOpSizeFromb76(); dbglog_writeCStr(" #"); dbglog_writeHex(ui5r_FromSWord(Disasm_nextiword())); if (Disasm_b76 != 0) { dbglog_writeCStr(", SR"); } else { dbglog_writeCStr(", CCR"); } dbglog_writeReturn(); } LOCALPROC disasmreglist(si4b direction, ui5b m1, ui5b r1) { si4b z; ui5r regmask; DisasmStartOne("MOVEM"); regmask = Disasm_nextiword(); Disasm_opsize = 2 * Disasm_b76 - 2; if (Disasm_opsize == 2) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); if (direction != 0) { DisasmModeRegister(m1, r1); dbglog_writeCStr(", "); } for (z = 0; z < 16; ++z) { if ((regmask & (1 << z)) != 0) { if (z >= 8) { dbglog_writeCStr("A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr("D"); dbglog_writeHex(z); } } } if (direction == 0) { dbglog_writeCStr(", "); DisasmModeRegister(m1, r1); } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMOVEMrm(void) { /* MOVEM reg to mem 010010001ssmmmrrr */ disasmreglist(0, Disasm_mode, Disasm_reg); } LOCALPROCUSEDONCE DisasmMOVEMmr(void) { /* MOVEM mem to reg 0100110011smmmrrr */ disasmreglist(1, Disasm_mode, Disasm_reg); } LOCALPROC DisasmByteBinOp(char *s, ui5b m1, ui5b r1, ui5b m2, ui5b r2) { DisasmStartOne(s); dbglog_writeCStr(" "); DisasmOpSizeFromb76(); DisasmModeRegister(m1, r1); dbglog_writeCStr(", "); DisasmModeRegister(m2, r2); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmAbcdr(void) { /* ABCD 1100ddd100000rrr */ DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); } LOCALPROCUSEDONCE DisasmAbcdm(void) { /* ABCD 1100ddd100001rrr */ DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); } LOCALPROCUSEDONCE DisasmSbcdr(void) { /* SBCD 1000xxx100000xxx */ DisasmByteBinOp("ABCD", 0, Disasm_reg, 0, Disasm_rg9); } LOCALPROCUSEDONCE DisasmSbcdm(void) { /* SBCD 1000xxx100001xxx */ DisasmByteBinOp("ABCD", 4, Disasm_reg, 4, Disasm_rg9); } LOCALPROCUSEDONCE DisasmNbcd(void) { /* Nbcd 0100100000mmmrrr */ Disasm_xxxxxxxxssmmmrrr("NBCD"); } LOCALPROCUSEDONCE DisasmRte(void) { /* Rte 0100111001110011 */ DisasmStartOne("RTE"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmNop(void) { /* Nop 0100111001110001 */ DisasmStartOne("NOP"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveP(void) { /* MoveP 0000ddd1mm001aaa */ DisasmStartOne("MOVEP"); if (0 == (Disasm_b76 & 1)) { Disasm_opsize = 2; dbglog_writeCStr(".W"); } else { Disasm_opsize = 4; dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); if (Disasm_b76 < 2) { DisasmModeRegister(5, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); } else { DisasmModeRegister(0, Disasm_rg9); dbglog_writeCStr(", "); DisasmModeRegister(5, Disasm_reg); } dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmIllegal(void) { DisasmStartOne("ILLEGAL"); dbglog_writeReturn(); } LOCALPROC DisasmCheck(void) { DisasmStartOne("CHK"); if (2 == Disasm_opsize) { dbglog_writeCStr(".W"); } else { dbglog_writeCStr(".L"); } dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); DisasmModeRegister(0, Disasm_rg9); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmChkW(void) { /* Chk.W 0100ddd110mmmrrr */ Disasm_opsize = 2; DisasmCheck(); } LOCALPROCUSEDONCE DisasmTrap(void) { /* Trap 010011100100vvvv */ DisasmStartOne("TRAP "); dbglog_writeHex(Disasm_opcode & 15); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTrapV(void) { /* TrapV 0100111001110110 */ DisasmStartOne("TRAPV"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmRtr(void) { /* Rtr 0100111001110111 */ DisasmStartOne("RTR"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmLink(void) { DisasmStartOne("LINK A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmUnlk(void) { DisasmStartOne("UNLINK A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveRUSP(void) { /* MOVE USP 0100111001100aaa */ DisasmStartOne("MOVE A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", USP"); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmMoveUSPR(void) { /* MOVE USP 0100111001101aaa */ DisasmStartOne("MOVE USP, A"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmTas(void) { /* Tas 0100101011mmmrrr */ Disasm_opsize = 1; DisasmStartOne("TAS"); dbglog_writeCStr(" "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmFLine(void) { DisasmStartOne("$"); dbglog_writeHex(Disasm_opcode); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmCallMorRtm(void) { DisasmStartOne("CALLM #"); dbglog_writeHex(Disasm_nextibyte()); dbglog_writeCStr(", "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmStop(void) { /* Stop 0100111001110010 */ DisasmStartOne("STOP #"); dbglog_writeHex(Disasm_nextiword()); dbglog_writeReturn(); } LOCALPROCUSEDONCE DisasmReset(void) { /* Reset 0100111001100000 */ DisasmStartOne("RESET"); dbglog_writeReturn(); } #if Use68020 LOCALPROCUSEDONCE DisasmEXTBL(void) { /* EXTB.L */ DisasmStartOne("EXTB.L D"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmTRAPcc(void) { /* TRAPcc 0101cccc11111sss */ DisasmStartOne("TRAP"); DisasmCC(); switch (Disasm_reg) { case 2: dbglog_writeCStr(" "); dbglog_writeHex(Disasm_nextiword()); break; case 3: dbglog_writeCStr(" "); dbglog_writeHex(Disasm_nextilong()); break; case 4: /* no optional data */ break; default: /* illegal format */ break; } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmChkL(void) { /* Chk.L 0100ddd100mmmrrr */ Disasm_opsize = 4; DisasmCheck(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmBkpt(void) { /* BKPT 0100100001001rrr */ DisasmStartOne("BKPT #"); dbglog_writeHex(Disasm_reg); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmDivL(void) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ Disasm_opsize = 4; DisasmStartOne("DIV"); { ui4b extra = Disasm_nextiword(); ui5b rDr = extra & 7; ui5b rDq = (extra >> 12) & 7; if (extra & 0x0800) { dbglog_writeCStr("S"); } else { dbglog_writeCStr("U"); } if (extra & 0x0400) { dbglog_writeCStr("L"); } dbglog_writeCStr(".L "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); if (rDr != rDq) { dbglog_writeCStr("D"); dbglog_writeHex(rDr); dbglog_writeCStr(":"); } dbglog_writeCStr("D"); dbglog_writeHex(rDq); } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMulL(void) { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ Disasm_opsize = 4; DisasmStartOne("MUL"); { ui4b extra = Disasm_nextiword(); ui5b rhi = extra & 7; ui5b rlo = (extra >> 12) & 7; if (extra & 0x0800) { dbglog_writeCStr("S"); } else { dbglog_writeCStr("U"); } dbglog_writeCStr(".L "); DisasmModeRegister(Disasm_mode, Disasm_reg); dbglog_writeCStr(", "); if (extra & 0x400) { dbglog_writeCStr("D"); dbglog_writeHex(rhi); dbglog_writeCStr(":"); } dbglog_writeCStr("D"); dbglog_writeHex(rlo); } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmRtd(void) { /* Rtd 0100111001110100 */ DisasmStartOne("RTD #"); dbglog_writeHex((si5b)(si4b)Disasm_nextiword()); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROC DisasmControlReg(ui4r i) { switch (i) { case 0x0000: dbglog_writeCStr("SFC"); break; case 0x0001: dbglog_writeCStr("DFC"); break; case 0x0002: dbglog_writeCStr("CACR"); break; case 0x0800: dbglog_writeCStr("USP"); break; case 0x0801: dbglog_writeCStr("VBR"); break; case 0x0802: dbglog_writeCStr("CAAR"); break; case 0x0803: dbglog_writeCStr("MSP"); break; case 0x0804: dbglog_writeCStr("ISP"); break; default: dbglog_writeCStr("???"); break; } } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMoveC(void) { /* MOVEC 010011100111101m */ DisasmStartOne("MOVEC "); { ui4b src = Disasm_nextiword(); int regno = (src >> 12) & 0x0F; switch (Disasm_reg) { case 2: DisasmControlReg(src & 0x0FFF); dbglog_writeCStr(", "); if (regno < 8) { dbglog_writeCStr("D"); } else { dbglog_writeCStr("A"); } dbglog_writeHex(regno & 7); break; case 3: if (regno < 8) { dbglog_writeCStr("D"); } else { dbglog_writeCStr("A"); } dbglog_writeHex(regno & 7); dbglog_writeCStr(", "); DisasmControlReg(src & 0x0FFF); break; default: /* illegal */ break; } } dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmLinkL(void) { /* Link.L 0100100000001rrr */ DisasmStartOne("LINK.L A"); dbglog_writeHex(Disasm_reg); dbglog_writeCStr(", "); dbglog_writeHex(Disasm_nextilong()); dbglog_writeReturn(); } #endif #if Use68020 LOCALPROCUSEDONCE DisasmPack(void) { DisasmStartOne("PACK ???"); dbglog_writeReturn(); /* DoCodePack */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmUnpk(void) { DisasmStartOne("UNPK ???"); dbglog_writeReturn(); /* DoCodeUnpk */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCHK2orCMP2(void) { DisasmStartOne("CHK2/CMP2 ???"); dbglog_writeReturn(); /* DoCHK2orCMP2 */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCAS2(void) { DisasmStartOne("CAS2 ???"); dbglog_writeReturn(); /* DoCAS2 */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmCAS(void) { DisasmStartOne("CAS ???"); dbglog_writeReturn(); /* DoDoCAS */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmMOVES(void) { DisasmStartOne("MOVES ???"); dbglog_writeReturn(); /* DoMOVES */ } #endif #if Use68020 LOCALPROCUSEDONCE DisasmBitField(void) { DisasmStartOne("BitField ???"); dbglog_writeReturn(); /* DoBitField */ } #endif LOCALFUNC blnr IsValidAddrMode(void) { return (Disasm_mode != 7) || (Disasm_reg < 5); } LOCALFUNC blnr IsValidDstAddrMode(void) { return (Disasm_md6 != 7) || (Disasm_rg9 < 2); } LOCALFUNC blnr IsValidDataAltAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 0: case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALFUNC blnr IsValidDataAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 0: case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 5; break; } return IsOk; } LOCALFUNC blnr IsValidControlAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: case 3: case 4: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 4; break; } return IsOk; } LOCALFUNC blnr IsValidControlAltAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: case 3: case 4: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALFUNC blnr IsValidAltMemAddrMode(void) { blnr IsOk; switch (Disasm_mode) { case 0: case 1: default: /* keep compiler happy */ IsOk = falseblnr; break; case 2: case 3: case 4: case 5: case 6: IsOk = trueblnr; break; case 7: IsOk = Disasm_reg < 2; break; } return IsOk; } LOCALPROCUSEDONCE DisasmCode0(void) { if (Disasm_b8 == 1) { if (Disasm_mode == 1) { /* MoveP 0000ddd1mm001aaa */ DisasmMoveP(); } else { /* dynamic bit, Opcode = 0000ddd1ttmmmrrr */ if (Disasm_mode == 0) { DisasmBitOpDD(); } else { if (Disasm_b76 == 0) { if (IsValidDataAddrMode()) { DisasmBitOpDM(); } else { DisasmIllegal(); } } else { if (IsValidDataAltAddrMode()) { DisasmBitOpDM(); } else { DisasmIllegal(); } } } } } else { if (Disasm_rg9 == 4) { /* static bit 00001010ssmmmrrr */ if (Disasm_mode == 0) { DisasmBitOpND(); } else { if (Disasm_b76 == 0) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { DisasmIllegal(); } else { if (IsValidDataAddrMode()) { DisasmBitOpNM(); } else { DisasmIllegal(); } } } else { if (IsValidDataAltAddrMode()) { DisasmBitOpNM(); } else { DisasmIllegal(); } } } } else if (Disasm_b76 == 3) { #if Use68020 if (Disasm_rg9 < 3) { /* CHK2 or CMP2 00000ss011mmmrrr */ if (IsValidControlAddrMode()) { DisasmCHK2orCMP2(); } else { DisasmIllegal(); } } else if (Disasm_rg9 >= 5) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { /* CAS2 00001ss011111100 */ DisasmCAS2(); } else { /* CAS 00001ss011mmmrrr */ DisasmCAS2(); } } else if (Disasm_rg9 == 3) { /* CALLM or RTM 0000011011mmmrrr */ DisasmCallMorRtm(); } else #endif { DisasmIllegal(); } } else if (Disasm_rg9 == 6) { /* CMPI 00001100ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmCmpI(); } else { DisasmIllegal(); } } else if (Disasm_rg9 == 7) { #if Use68020 /* MoveS 00001110ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmMoveSREa(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif } else { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { switch (Disasm_rg9) { case 0: case 1: case 5: DisasmBinOpStatusCCR(); break; default: DisasmIllegal(); break; } } else { if (! IsValidDataAltAddrMode()) { DisasmIllegal(); } else { switch (Disasm_rg9) { case 0: DisasmOrI(); break; case 1: DisasmAndI(); break; case 2: DisasmSubI(); break; case 3: DisasmAddI(); break; case 5: DisasmEorI(); break; default: /* for compiler. should be 0, 1, 2, 3, or 5 */ DisasmIllegal(); break; } } } } } } LOCALPROCUSEDONCE DisasmCode1(void) { if ((Disasm_mode == 1) || ! IsValidAddrMode()) { DisasmIllegal(); } else if (Disasm_md6 == 1) { /* MOVEA */ DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveB(); } } LOCALPROCUSEDONCE DisasmCode2(void) { if (Disasm_md6 == 1) { /* MOVEA */ if (IsValidAddrMode()) { DisasmMoveAL(); } else { DisasmIllegal(); } } else if (! IsValidAddrMode()) { DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveL(); } } LOCALPROCUSEDONCE DisasmCode3(void) { if (Disasm_md6 == 1) { /* MOVEA */ if (IsValidAddrMode()) { DisasmMoveAW(); } else { DisasmIllegal(); } } else if (! IsValidAddrMode()) { DisasmIllegal(); } else if (! IsValidDstAddrMode()) { DisasmIllegal(); } else { DisasmMoveW(); } } LOCALPROCUSEDONCE DisasmCode4(void) { if (Disasm_b8 != 0) { switch (Disasm_b76) { case 0: #if Use68020 /* Chk.L 0100ddd100mmmrrr */ if (IsValidDataAddrMode()) { DisasmChkL(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif break; case 1: DisasmIllegal(); break; case 2: /* Chk.W 0100ddd110mmmrrr */ if (IsValidDataAddrMode()) { DisasmChkW(); } else { DisasmIllegal(); } break; case 3: default: /* keep compiler happy */ #if Use68020 if ((0 == Disasm_mode) && (4 == Disasm_rg9)) { DisasmEXTBL(); } else #endif { /* Lea 0100aaa111mmmrrr */ if (IsValidControlAddrMode()) { DisasmLea(); } else { DisasmIllegal(); } } break; } } else { switch (Disasm_rg9) { case 0: if (Disasm_b76 != 3) { /* NegX 01000000ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNegX(); } else { DisasmIllegal(); } } else { #if Use68020 /* reference seems incorrect to say not for 68000 */ #endif /* Move from SR 0100000011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmMoveSREa(); } else { DisasmIllegal(); } } break; case 1: if (Disasm_b76 != 3) { /* Clr 01000010ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmClr(); } else { DisasmIllegal(); } } else { #if Use68020 /* Move from CCR 0100001011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmMoveCCREa(); } else { DisasmIllegal(); } #else DisasmIllegal(); #endif } break; case 2: if (Disasm_b76 != 3) { /* Neg 01000100ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNeg(); } else { DisasmIllegal(); } } else { /* Move to CCR 0100010011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMoveEaCR(); } else { DisasmIllegal(); } } break; case 3: if (Disasm_b76 != 3) { /* Not 01000110ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNot(); } else { DisasmIllegal(); } } else { /* Move from SR 0100011011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMoveEaSR(); } else { DisasmIllegal(); } } break; case 4: switch (Disasm_b76) { case 0: #if Use68020 if (Disasm_mode == 1) { /* Link.L 0100100000001rrr */ DisasmLinkL(); } else #endif { /* Nbcd 0100100000mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmNbcd(); } else { DisasmIllegal(); } } break; case 1: if (Disasm_mode == 0) { /* Swap 0100100001000rrr */ DisasmSwap(); } else #if Use68020 if (Disasm_mode == 1) { DisasmBkpt(); } else #endif { /* PEA 0100100001mmmrrr */ if (IsValidControlAddrMode()) { DisasmPEA(); } else { DisasmIllegal(); } } break; case 2: if (Disasm_mode == 0) { /* EXT.W */ DisasmEXTW(); } else { /* MOVEM Disasm_reg to mem 01001d001ssmmmrrr */ if (Disasm_mode == 4) { DisasmMOVEMRmM(); } else { if (IsValidControlAltAddrMode()) { DisasmMOVEMrm(); } else { DisasmIllegal(); } } } break; case 3: default: /* keep compiler happy */ if (Disasm_mode == 0) { /* EXT.L */ DisasmEXTL(); } else { /* MOVEM Disasm_reg to mem 01001d001ssmmmrrr */ if (Disasm_mode == 4) { DisasmMOVEMRmM(); } else { if (IsValidControlAltAddrMode()) { DisasmMOVEMrm(); } else { DisasmIllegal(); } } } break; } break; case 5: if (Disasm_b76 == 3) { if ((Disasm_mode == 7) && (Disasm_reg == 4)) { /* the ILLEGAL instruction */ DisasmIllegal(); } else { /* Tas 0100101011mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmTas(); } else { DisasmIllegal(); } } } else { /* Tst 01001010ssmmmrrr */ if (Disasm_b76 == 0) { if (IsValidDataAltAddrMode()) { DisasmTst(); } else { DisasmIllegal(); } } else { if (IsValidAddrMode()) { DisasmTst(); } else { DisasmIllegal(); } } } break; case 6: if (((Disasm_opcode >> 7) & 1) == 1) { /* MOVEM mem to Disasm_reg 0100110011smmmrrr */ if (Disasm_mode == 3) { DisasmMOVEMApR(); } else { if (IsValidControlAddrMode()) { DisasmMOVEMmr(); } else { DisasmIllegal(); } } } else { #if Use68020 if (((Disasm_opcode >> 6) & 1) == 1) { /* DIVU 0100110001mmmrrr 0rrr0s0000000rrr */ /* DIVS 0100110001mmmrrr 0rrr1s0000000rrr */ DisasmDivL(); } else { /* MULU 0100110000mmmrrr 0rrr0s0000000rrr */ /* MULS 0100110000mmmrrr 0rrr1s0000000rrr */ DisasmMulL(); } #else DisasmIllegal(); #endif } break; case 7: default: /* keep compiler happy */ switch (Disasm_b76) { case 0: DisasmIllegal(); break; case 1: switch (Disasm_mode) { case 0: case 1: /* Trap 010011100100vvvv */ DisasmTrap(); break; case 2: /* Link */ if (Disasm_reg == 6) { DisasmLinkA6(); } else { DisasmLink(); } break; case 3: /* Unlk */ if (Disasm_reg == 6) { DisasmUnlkA6(); } else { DisasmUnlk(); } break; case 4: /* MOVE USP 0100111001100aaa */ DisasmMoveRUSP(); break; case 5: /* MOVE USP 0100111001101aaa */ DisasmMoveUSPR(); break; case 6: switch (Disasm_reg) { case 0: /* Reset 0100111001100000 */ DisasmReset(); break; case 1: /* Nop Opcode = 0100111001110001 */ DisasmNop(); break; case 2: /* Stop 0100111001110010 */ DisasmStop(); break; case 3: /* Rte 0100111001110011 */ DisasmRte(); break; case 4: /* Rtd 0100111001110100 */ #if Use68020 DisasmRtd(); #else DisasmIllegal(); #endif break; case 5: /* Rts 0100111001110101 */ DisasmRts(); break; case 6: /* TrapV 0100111001110110 */ DisasmTrapV(); break; case 7: default: /* keep compiler happy */ /* Rtr 0100111001110111 */ DisasmRtr(); break; } break; case 7: default: /* keep compiler happy */ #if Use68020 /* MOVEC 010011100111101m */ DisasmMoveC(); #else DisasmIllegal(); #endif break; } break; case 2: /* Jsr 0100111010mmmrrr */ if (IsValidControlAddrMode()) { DisasmJsr(); } else { DisasmIllegal(); } break; case 3: default: /* keep compiler happy */ /* JMP 0100111011mmmrrr */ if (IsValidControlAddrMode()) { DisasmJmp(); } else { DisasmIllegal(); } break; } break; } } } LOCALPROCUSEDONCE DisasmCode5(void) { if (Disasm_b76 == 3) { if (Disasm_mode == 1) { /* DBcc 0101cccc11001ddd */ DisasmDBcc(); } else { #if Use68020 if ((Disasm_mode == 7) && (Disasm_reg >= 2)) { /* TRAPcc 0101cccc11111sss */ DisasmTRAPcc(); } else #endif { /* Scc 0101cccc11mmmrrr */ if (IsValidDataAltAddrMode()) { DisasmScc(); } else { DisasmIllegal(); } } } } else { if (Disasm_mode == 1) { if (Disasm_b8 == 0) { DisasmAddQA(); /* AddQA 0101nnn0ss001rrr */ } else { DisasmSubQA(); /* SubQA 0101nnn1ss001rrr */ } } else { if (Disasm_b8 == 0) { /* AddQ 0101nnn0ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmAddQ(); } else { DisasmIllegal(); } } else { /* SubQ 0101nnn1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmSubQ(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCode6(void) { ui5b cond = (Disasm_opcode >> 8) & 15; if (cond == 1) { /* Bsr 01100001nnnnnnnn */ DisasmBsr(); } else if (cond == 0) { /* Bra 01100000nnnnnnnn */ DisasmBcc(); } else { /* Bcc 0110ccccnnnnnnnn */ DisasmBcc(); } } LOCALPROCUSEDONCE DisasmCode7(void) { if (Disasm_b8 == 0) { DisasmMoveQ(); } else { DisasmIllegal(); } } LOCALPROCUSEDONCE DisasmCode8(void) { if (Disasm_b76 == 3) { if (Disasm_b8 == 0) { /* DivU 1000ddd011mmmrrr */ if (IsValidDataAddrMode()) { DisasmDivU(); } else { DisasmIllegal(); } } else { /* DivS 1000ddd111mmmrrr */ if (IsValidDataAddrMode()) { DisasmDivS(); } else { DisasmIllegal(); } } } else { if (Disasm_b8 == 0) { /* OR 1000ddd0ssmmmrrr */ if (IsValidDataAddrMode()) { DisasmOrEaD(); } else { DisasmIllegal(); } } else { if (Disasm_mode < 2) { switch (Disasm_b76) { case 0: /* SBCD 1000xxx10000mxxx */ if (Disasm_mode == 0) { DisasmSbcdr(); } else { DisasmSbcdm(); } break; #if Use68020 case 1: /* PACK 1000rrr10100mrrr */ DisasmPack(); break; case 2: /* UNPK 1000rrr11000mrrr */ DisasmUnpk(); break; #endif default: DisasmIllegal(); break; } } else { /* OR 1000ddd1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmOrDEa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCode9(void) { if (Disasm_b76 == 3) { /* SUBA 1001dddm11mmmrrr */ if (IsValidAddrMode()) { DisasmSubA(); } else { DisasmIllegal(); } } else { if (Disasm_b8 == 0) { /* SUB 1001ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmSubEaR(); } else { DisasmIllegal(); } } else { if (Disasm_mode == 0) { /* SUBX 1001ddd1ss000rrr */ DisasmSubXd(); } else if (Disasm_mode == 1) { /* SUBX 1001ddd1ss001rrr */ DisasmSubXm(); } else { /* SUB 1001ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmSubREa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeA(void) { DisasmALine(); } LOCALPROCUSEDONCE DisasmCodeB(void) { if (Disasm_b76 == 3) { /* CMPA 1011ddds11mmmrrr */ if (IsValidAddrMode()) { DisasmCmpA(); } else { DisasmIllegal(); } } else if (Disasm_b8 == 1) { if (Disasm_mode == 1) { /* CmpM 1011ddd1ss001rrr */ DisasmCmpM(); } else { /* Eor 1011ddd1ssmmmrrr */ if (IsValidDataAltAddrMode()) { DisasmEor(); } else { DisasmIllegal(); } } } else { /* Cmp 1011ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmCompare(); } else { DisasmIllegal(); } } } LOCALPROCUSEDONCE DisasmCodeC(void) { if (Disasm_b76 == 3) { if (Disasm_b8 == 0) { /* MulU 1100ddd011mmmrrr */ if (IsValidDataAddrMode()) { DisasmMulU(); } else { DisasmIllegal(); } } else { /* MulS 1100ddd111mmmrrr */ if (IsValidDataAddrMode()) { DisasmMulS(); } else { DisasmIllegal(); } } } else { if (Disasm_b8 == 0) { /* And 1100ddd0ssmmmrrr */ if (IsValidDataAddrMode()) { DisasmAndEaD(); } else { DisasmIllegal(); } } else { if (Disasm_mode < 2) { switch (Disasm_b76) { case 0: /* ABCD 1100ddd10000mrrr */ if (Disasm_mode == 0) { DisasmAbcdr(); } else { DisasmAbcdm(); } break; case 1: /* Exg 1100ddd10100trrr */ if (Disasm_mode == 0) { DisasmExgdd(); } else { DisasmExgaa(); } break; case 2: default: /* keep compiler happy */ if (Disasm_mode == 0) { DisasmIllegal(); } else { /* Exg 1100ddd110001rrr */ DisasmExgda(); } break; } } else { /* And 1100ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmAndDEa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeD(void) { if (Disasm_b76 == 3) { /* ADDA 1101dddm11mmmrrr */ if (IsValidAddrMode()) { DisasmAddA(); } else { DisasmIllegal(); } } else { if (Disasm_b8 == 0) { /* ADD 1101ddd0ssmmmrrr */ if (IsValidAddrMode()) { DisasmAddEaR(); } else { DisasmIllegal(); } } else { if (Disasm_mode == 0) { DisasmAddXd(); } else if (Disasm_mode == 1) { DisasmAddXm(); } else { /* ADD 1101ddd1ssmmmrrr */ if (IsValidAltMemAddrMode()) { DisasmAddREa(); } else { DisasmIllegal(); } } } } } LOCALPROCUSEDONCE DisasmCodeE(void) { if (Disasm_b76 == 3) { if ((Disasm_opcode & 0x0800) != 0) { #if Use68020 /* 11101???11mmmrrr */ switch (Disasm_mode) { case 1: case 3: case 4: default: /* keep compiler happy */ DisasmIllegal(); break; case 0: case 2: case 5: case 6: DisasmBitField(); break; case 7: switch (Disasm_reg) { case 0: case 1: DisasmBitField(); break; case 2: case 3: switch ((Disasm_opcode >> 8) & 7) { case 0: /* BFTST */ case 1: /* BFEXTU */ case 3: /* BFEXTS */ case 5: /* BFFFO */ DisasmBitField(); break; default: DisasmIllegal(); break; } break; default: DisasmIllegal(); break; } break; } #else DisasmIllegal(); #endif } else { /* 11100ttd11mmmddd */ if (IsValidAltMemAddrMode()) { DisasmRolopNM(); } else { DisasmIllegal(); } } } else { if (Disasm_mode < 4) { /* 1110cccdss0ttddd */ DisasmRolopND(); } else { /* 1110rrrdss1ttddd */ DisasmRolopDD(); } } } LOCALPROCUSEDONCE DisasmCodeF(void) { DisasmFLine(); } LOCALPROC m68k_Disasm_one(void) { Disasm_opcode = Disasm_nextiword(); switch (Disasm_opcode >> 12) { case 0x0: DisasmCode0(); break; case 0x1: DisasmCode1(); break; case 0x2: DisasmCode2(); break; case 0x3: DisasmCode3(); break; case 0x4: DisasmCode4(); break; case 0x5: DisasmCode5(); break; case 0x6: DisasmCode6(); break; case 0x7: DisasmCode7(); break; case 0x8: DisasmCode8(); break; case 0x9: DisasmCode9(); break; case 0xA: DisasmCodeA(); break; case 0xB: DisasmCodeB(); break; case 0xC: DisasmCodeC(); break; case 0xD: DisasmCodeD(); break; case 0xE: DisasmCodeE(); break; case 0xF: default: /* keep compiler happy */ DisasmCodeF(); break; } } #define Ln2SavedPCs 4 #define NumSavedPCs (1 << Ln2SavedPCs) #define SavedPCsMask (NumSavedPCs - 1) LOCALVAR ui5r SavedPCs[NumSavedPCs]; LOCALVAR ui5r SavedPCsIn = 0; LOCALVAR ui5r SavedPCsOut = 0; #define DisasmIncludeCycles 0 LOCALPROCUSEDONCE DisasmOneAndBack(ui5r pc) { #if DisasmIncludeCycles dbglog_writeHex(GetCuriCount()); dbglog_writeCStr(" "); #endif dbglog_writeHex(pc); dbglog_writeCStr(" "); Disasm_setpc(pc); m68k_Disasm_one(); } LOCALPROCUSEDONCE DisasmSavedPCs(void) { ui5r n = SavedPCsIn - SavedPCsOut; if (n != 0) { ui5r pc; #if DisasmIncludeCycles ui5r i; #endif #if 0 blnr Skipped = falseblnr; #endif ui5r j = SavedPCsOut; SavedPCsOut = SavedPCsIn; /* do first, prevent recursion in case of error while disassembling. (i.e. failure to read emulated memory.) */ #if DisasmIncludeCycles i = GetCuriCount(); #endif if (n > NumSavedPCs) { n = NumSavedPCs; j = SavedPCsIn - NumSavedPCs; dbglog_writeReturn(); #if 0 Skipped = trueblnr; #endif } do { --n; pc = SavedPCs[j & SavedPCsMask]; #if DisasmIncludeCycles dbglog_writeHex(i /* - n */); dbglog_writeCStr("-? "); #endif dbglog_writeHex(pc); dbglog_writeCStr(" "); Disasm_setpc(pc); m68k_Disasm_one(); ++j; } while (n != 0); #if 0 if (Skipped) { si4b z; for (z = 0; z < 16; ++z) { if (z >= 8) { dbglog_writeCStr(" A"); dbglog_writeHex(z - 8); } else { dbglog_writeCStr(" D"); dbglog_writeHex(z); } dbglog_writeCStr(" = "); dbglog_writeHex(regs.regs[z]); dbglog_writeReturn(); } } #endif } } LOCALVAR ui5r DisasmCounter = 0; GLOBALPROC DisasmOneOrSave(ui5r pc) { if (0 != DisasmCounter) { DisasmOneAndBack(pc); --DisasmCounter; } else { SavedPCs[SavedPCsIn & SavedPCsMask] = pc; ++SavedPCsIn; } } GLOBALPROC m68k_WantDisasmContext(void) { DisasmSavedPCs(); DisasmCounter = /* 256 */ 128; }