mirror of
https://github.com/zydeco/minivmac4ios.git
synced 2024-12-01 18:50:59 +00:00
2937 lines
53 KiB
C
2937 lines
53 KiB
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 MayNotInline 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;
|
||
|
}
|
||
|
|
||
|
LOCALFUNC ui3r Disasm_nextibyte(void)
|
||
|
{
|
||
|
return (ui3b) Disasm_nextiword();
|
||
|
}
|
||
|
|
||
|
LOCALFUNC MayNotInline 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 MayNotInline 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 MayNotInline 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 MayNotInline 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 MayNotInline 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 MayNotInline 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 MayNotInline 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;
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC DisasmCode1(void)
|
||
|
{
|
||
|
if ((Disasm_mode == 1) || ! IsValidAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else if (Disasm_md6 == 1) { /* MOVEA */
|
||
|
DisasmIllegal();
|
||
|
} else if (! IsValidDstAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else {
|
||
|
DisasmMoveB();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC DisasmCode2(void)
|
||
|
{
|
||
|
if (Disasm_md6 == 1) { /* MOVEA */
|
||
|
if (IsValidAddrMode()) {
|
||
|
DisasmMoveAL();
|
||
|
} else {
|
||
|
DisasmIllegal();
|
||
|
}
|
||
|
} else if (! IsValidAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else if (! IsValidDstAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else {
|
||
|
DisasmMoveL();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC DisasmCode3(void)
|
||
|
{
|
||
|
if (Disasm_md6 == 1) { /* MOVEA */
|
||
|
if (IsValidAddrMode()) {
|
||
|
DisasmMoveAW();
|
||
|
} else {
|
||
|
DisasmIllegal();
|
||
|
}
|
||
|
} else if (! IsValidAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else if (! IsValidDstAddrMode()) {
|
||
|
DisasmIllegal();
|
||
|
} else {
|
||
|
DisasmMoveW();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC DisasmCode7(void)
|
||
|
{
|
||
|
if (Disasm_b8 == 0) {
|
||
|
DisasmMoveQ();
|
||
|
} else {
|
||
|
DisasmIllegal();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC DisasmCodeA(void)
|
||
|
{
|
||
|
DisasmALine();
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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();
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOCALPROC 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
|
||
|
blnr Skipped = falseblnr;
|
||
|
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();
|
||
|
Skipped = trueblnr;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|