/* This file is in the public domain. */ #include #include #include #include "machine.h" #include "fnprintf.h" typedef struct instr INSTR; struct instr { unsigned int nbytes; const char *fmt; int can_sp; } ; static INSTR instrs[256] = { { /*00*/ 3, "brset 0,~d1,~b2" }, { /*01*/ 3, "brclr 0,~d1,~b2" }, { /*02*/ 3, "brset 1,~d1,~b2" }, { /*03*/ 3, "brclr 1,~d1,~b2" }, { /*04*/ 3, "brset 2,~d1,~b2" }, { /*05*/ 3, "brclr 2,~d1,~b2" }, { /*06*/ 3, "brset 3,~d1,~b2" }, { /*07*/ 3, "brclr 3,~d1,~b2" }, { /*08*/ 3, "brset 4,~d1,~b2" }, { /*09*/ 3, "brclr 4,~d1,~b2" }, { /*0a*/ 3, "brset 5,~d1,~b2" }, { /*0b*/ 3, "brclr 5,~d1,~b2" }, { /*0c*/ 3, "brset 6,~d1,~b2" }, { /*0d*/ 3, "brclr 6,~d1,~b2" }, { /*0e*/ 3, "brset 7,~d1,~b2" }, { /*0f*/ 3, "brclr 7,~d1,~b2" }, { /*10*/ 2, "bset 0,~d1" }, { /*11*/ 2, "bclr 0,~d1" }, { /*12*/ 2, "bset 1,~d1" }, { /*13*/ 2, "bclr 1,~d1" }, { /*14*/ 2, "bset 2,~d1" }, { /*15*/ 2, "bclr 2,~d1" }, { /*16*/ 2, "bset 3,~d1" }, { /*17*/ 2, "bclr 3,~d1" }, { /*18*/ 2, "bset 4,~d1" }, { /*19*/ 2, "bclr 4,~d1" }, { /*1a*/ 2, "bset 5,~d1" }, { /*1b*/ 2, "bclr 5,~d1" }, { /*1c*/ 2, "bset 6,~d1" }, { /*1d*/ 2, "bclr 6,~d1" }, { /*1e*/ 2, "bset 7,~d1" }, { /*1f*/ 2, "bclr 7,~d1" }, { /*20*/ 2, "bra ~b1" }, { /*21*/ 2, "brn ~b1" }, { /*22*/ 2, "bhi ~b1" }, { /*23*/ 2, "bls ~b1" }, { /*24*/ 2, "bcc ~b1" }, { /*25*/ 2, "bcs ~b1" }, { /*26*/ 2, "bne ~b1" }, { /*27*/ 2, "beq ~b1" }, { /*28*/ 2, "bhcc ~b1" }, { /*29*/ 2, "bhcs ~b1" }, { /*2a*/ 2, "bpl ~b1" }, { /*2b*/ 2, "bmi ~b1" }, { /*2c*/ 2, "bmc ~b1" }, { /*2d*/ 2, "bms ~b1" }, { /*2e*/ 2, "bil ~b1" }, { /*2f*/ 2, "bih ~b1" }, { /*30*/ 2, "neg ~d1" }, { /*31*/ 3, "cbeq ~d1,~b2" }, { /*32*/ 1, "HOLE-0x32" }, { /*33*/ 2, "com ~d1" }, { /*34*/ 2, "lsr ~d1" }, { /*35*/ 2, "sthx ~d1" }, { /*36*/ 2, "ror ~d1" }, { /*37*/ 2, "asr ~d1" }, { /*38*/ 2, "lsl ~d1" }, { /*39*/ 2, "rol ~d1" }, { /*3a*/ 2, "dec ~d1" }, { /*3b*/ 3, "dbnz ~d1,~b2" }, { /*3c*/ 2, "inc ~d1" }, { /*3d*/ 2, "tst ~d1" }, { /*3e*/ 2, "HOLE-0x3e" }, { /*3f*/ 2, "clr ~d1" }, { /*40*/ 1, "neg a" }, { /*41*/ 3, "cbeq a,#~i1,~b2" }, { /*42*/ 1, "mul" }, { /*43*/ 1, "com a" }, { /*44*/ 1, "lsr a" }, { /*45*/ 3, "ldhx #~I1" }, { /*46*/ 1, "ror a" }, { /*47*/ 1, "asr a" }, { /*48*/ 1, "lsl a" }, { /*49*/ 1, "rol a" }, { /*4a*/ 1, "dec a" }, { /*4b*/ 2, "dbnz a,~b1" }, { /*4c*/ 1, "inc a" }, { /*4d*/ 1, "tst a" }, { /*4e*/ 3, "mov ~d1,~d2" }, { /*4f*/ 1, "clr a" }, { /*50*/ 1, "neg x" }, { /*51*/ 3, "cbeq x,#~i1,~b2" }, { /*52*/ 1, "div" }, { /*53*/ 1, "com x" }, { /*54*/ 1, "lsr x" }, { /*55*/ 2, "ldhx ~d1" }, { /*56*/ 1, "ror x" }, { /*57*/ 1, "asr x" }, { /*58*/ 1, "lsl x" }, { /*59*/ 1, "rol x" }, { /*5a*/ 1, "dec x" }, { /*5b*/ 2, "dbnz x,~b1" }, { /*5c*/ 1, "inc x" }, { /*5d*/ 1, "tst x" }, { /*5e*/ 2, "mov ~d1,x+" }, { /*5f*/ 1, "clr x" }, { /*60*/ 2, "neg ~i1,~x" }, { /*61*/ 3, "cbeq ~i1,~X,~b2" }, { /*62*/ 1, "nsa" }, { /*63*/ 2, "com ~i1,~x" }, { /*64*/ 2, "lsr ~i1,~x" }, { /*65*/ 3, "cphx #~I1" }, { /*66*/ 2, "ror ~i1,~x" }, { /*67*/ 2, "asr ~i1,~x" }, { /*68*/ 2, "lsl ~i1,~x" }, { /*69*/ 2, "rol ~i1,~x" }, { /*6a*/ 2, "dec ~i1,~x" }, { /*6b*/ 3, "dbnz ~i1,~x,~b2" }, { /*6c*/ 2, "inc ~i1,~x" }, { /*6d*/ 2, "tst ~i1,~x" }, { /*6e*/ 3, "mov #~i1,~d2" }, { /*6f*/ 2, "clr ~i1,~x" }, { /*70*/ 1, "neg ,x" }, { /*71*/ 2, "cbeq ,x+,~b1" }, { /*72*/ 1, "daa" }, { /*73*/ 1, "com ,x" }, { /*74*/ 1, "lsr ,x" }, { /*75*/ 2, "cphx ~d1" }, { /*76*/ 1, "ror ,x" }, { /*77*/ 1, "asr ,x" }, { /*78*/ 1, "lsl ,x" }, { /*79*/ 1, "rol ,x" }, { /*7a*/ 1, "dec ,x" }, { /*7b*/ 2, "dbnz ,x,~b1" }, { /*7c*/ 1, "inc ,x" }, { /*7d*/ 1, "tst ,x" }, { /*7e*/ 2, "mov ,x+,~d1" }, { /*7f*/ 1, "clr ,x" }, { /*80*/ 1, "rti" }, { /*81*/ 1, "rts" }, { /*82*/ 1, "HOLE-0x82" }, { /*83*/ 1, "swi" }, { /*84*/ 1, "tap" }, { /*85*/ 1, "tpa" }, { /*86*/ 1, "pul a" }, { /*87*/ 1, "psh a" }, { /*88*/ 1, "pul x" }, { /*89*/ 1, "psh x" }, { /*8a*/ 1, "pul h" }, { /*8b*/ 1, "psh h" }, { /*8c*/ 1, "clr h" }, { /*8d*/ 1, "HOLE-0x8d" }, { /*8e*/ 1, "stop" }, { /*8f*/ 1, "wait" }, { /*90*/ 2, "bge ~b1" }, { /*91*/ 2, "blt ~b1" }, { /*92*/ 2, "bgt ~b1" }, { /*93*/ 2, "ble ~b1" }, { /*94*/ 1, "txs" }, { /*95*/ 1, "tsx" }, { /*96*/ 1, "HOLE-0x96" }, { /*97*/ 1, "tax" }, { /*98*/ 1, "clc" }, { /*99*/ 1, "sec" }, { /*9a*/ 1, "cli" }, { /*9b*/ 1, "sei" }, { /*9c*/ 1, "rsp" }, { /*9d*/ 1, "nop" }, { /*9e*/ 0, "" }, /* nbytes 0 is flag value */ { /*9f*/ 1, "txa" }, { /*a0*/ 2, "sub #~i1" }, { /*a1*/ 2, "cmp #~i1" }, { /*a2*/ 2, "sbc #~i1" }, { /*a3*/ 2, "cpx #~i1" }, { /*a4*/ 2, "and #~i1" }, { /*a5*/ 2, "bit #~i1" }, { /*a6*/ 2, "lda #~i1" }, { /*a7*/ 2, "ais #~j1" }, { /*a8*/ 2, "eor #~i1" }, { /*a9*/ 2, "adc #~i1" }, { /*aa*/ 2, "ora #~i1" }, { /*ab*/ 2, "add #~i1" }, { /*ac*/ 1, "HOLE-0xac" }, { /*ad*/ 2, "bsr ~b1" }, { /*ae*/ 2, "ldx #~i1" }, { /*af*/ 2, "aix #~j1" }, { /*b0*/ 2, "sub ~d1" }, { /*b1*/ 2, "cmp ~d1" }, { /*b2*/ 2, "sbc ~d1" }, { /*b3*/ 2, "cpx ~d1" }, { /*b4*/ 2, "and ~d1" }, { /*b5*/ 2, "bit ~d1" }, { /*b6*/ 2, "lda ~d1" }, { /*b7*/ 2, "sta ~d1" }, { /*b8*/ 2, "eor ~d1" }, { /*b9*/ 2, "adc ~d1" }, { /*ba*/ 2, "ora ~d1" }, { /*bb*/ 2, "add ~d1" }, { /*bc*/ 2, "jmp ~d1" }, { /*bd*/ 2, "jsr ~d1" }, { /*be*/ 2, "ldx ~d1" }, { /*bf*/ 2, "stx ~d1" }, { /*c0*/ 3, "sub ~e1" }, { /*c1*/ 3, "cmp ~e1" }, { /*c2*/ 3, "sbc ~e1" }, { /*c3*/ 3, "cpx ~e1" }, { /*c4*/ 3, "and ~e1" }, { /*c5*/ 3, "bit ~e1" }, { /*c6*/ 3, "lda ~e1" }, { /*c7*/ 3, "sta ~e1" }, { /*c8*/ 3, "eor ~e1" }, { /*c9*/ 3, "adc ~e1" }, { /*ca*/ 3, "ora ~e1" }, { /*cb*/ 3, "add ~e1" }, { /*cc*/ 3, "jmp ~e1" }, { /*cd*/ 3, "jsr ~e1" }, { /*ce*/ 3, "ldx ~e1" }, { /*cf*/ 3, "stx ~e1" }, { /*d0*/ 3, "sub ~I1,~x" }, { /*d1*/ 3, "cmp ~I1,~x" }, { /*d2*/ 3, "sbc ~I1,~x" }, { /*d3*/ 3, "cpx ~I1,~x" }, { /*d4*/ 3, "and ~I1,~x" }, { /*d5*/ 3, "bit ~I1,~x" }, { /*d6*/ 3, "lda ~I1,~x" }, { /*d7*/ 3, "sta ~I1,~x" }, { /*d8*/ 3, "eor ~I1,~x" }, { /*d9*/ 3, "adc ~I1,~x" }, { /*da*/ 3, "ora ~I1,~x" }, { /*db*/ 3, "add ~I1,~x" }, { /*dc*/ 3, "jmp ~I1,x" }, { /*dd*/ 3, "jsr ~I1,x" }, { /*de*/ 3, "ldx ~I1,~x" }, { /*df*/ 3, "stx ~I1,~x" }, { /*e0*/ 2, "sub ~i1,~x" }, { /*e1*/ 2, "cmp ~i1,~x" }, { /*e2*/ 2, "sbc ~i1,~x" }, { /*e3*/ 2, "cpx ~i1,~x" }, { /*e4*/ 2, "and ~i1,~x" }, { /*e5*/ 2, "bit ~i1,~x" }, { /*e6*/ 2, "lda ~i1,~x" }, { /*e7*/ 2, "sta ~i1,~x" }, { /*e8*/ 2, "eor ~i1,~x" }, { /*e9*/ 2, "adc ~i1,~x" }, { /*ea*/ 2, "ora ~i1,~x" }, { /*eb*/ 2, "add ~i1,~x" }, { /*ec*/ 2, "jmp ~i1,x" }, { /*ed*/ 2, "jsr ~i1,x" }, { /*ee*/ 2, "ldx ~i1,~x" }, { /*ef*/ 2, "stx ~i1,~x" }, { /*f0*/ 1, "sub ,x" }, { /*f1*/ 1, "cmp ,x" }, { /*f2*/ 1, "sbc ,x" }, { /*f3*/ 1, "cpx ,x" }, { /*f4*/ 1, "and ,x" }, { /*f5*/ 1, "bit ,x" }, { /*f6*/ 1, "lda ,x" }, { /*f7*/ 1, "sta ,x" }, { /*f8*/ 1, "eor ,x" }, { /*f9*/ 1, "adc ,x" }, { /*fa*/ 1, "ora ,x" }, { /*fb*/ 1, "add ,x" }, { /*fc*/ 1, "jmp ,x" }, { /*fd*/ 1, "jsr ,x" }, { /*fe*/ 1, "ldx ,x" }, { /*ff*/ 1, "stx ,x" } }; static void print_with_symbol(void (*fn)(char), ADDR a, const char *fmt) { SYMBOL *s; s = symbol_for_addr(a); if (s) { fnprintf(fn,"%s",s->name); } else { fnprintf(fn,fmt,(unsigned long int)a); } maybe_print_stringptr(fn,a); } static void process_format(void (*fn)(char), const char *fmt, ADDR base, CFLAG flg, int spform) { int o; unsigned int v; while (1) { switch (*fmt++) { case '\0': return; break; default: fnprintf(fn,"%c",fmt[-1]); break; case '~': switch (*fmt++) { default: fnprintf(fn,"?~%c",fmt[-1]); break; case '\0': fnprintf(fn,"?~\\0"); return; break; case 'I': case 'b': case 'd': case 'e': case 'i': case 'j': switch (*fmt++) { default: fnprintf(fn,"?~%c%c",fmt[-2],fmt[-1]); break; case '\0': fnprintf(fn,"?~%c\\0",fmt[-2]); return; break; case '1': o = 1; break; case '2': o = 2; break; } switch (fmt[-2]) { case 'I': v = corefetchu(base+o,2); fnprintf(fn,"%04x",v); if (flg & CFF_INST_PTRLITS) maybe_print_ptrlit(fn,v); break; case 'b': print_with_symbol(fn,corebase+base+o+1+corefetchs(base+o,1),"%04x"); break; case 'd': print_with_symbol(fn,corefetchu(base+o,1),"%02x"); break; case 'e': print_with_symbol(fn,corefetchu(base+o,2),"%04x"); break; case 'i': v = corefetchu(base+o,1); fnprintf(fn,"%02x",v); if (flg & CFF_INST_PTRLITS) maybe_print_ptrlit(fn,v); break; case 'j': v = corefetchu(base+o,1); if (v >= 0x80) { fnprintf(fn,"-%02x",0x100-v); } else { fnprintf(fn,"%02x",v); } break; default: abort(); break; } break; case 'X': fnprintf(fn,spform?"sp":"x+"); break; case 'x': fnprintf(fn,spform?"sp":"x"); break; } break; } } } static int do_dis_inst(ADDR addr, void (*fn)(char), CFLAG flg) { unsigned char opc; int i; int nb; int spform; ADDR a; addr -= corebase; if (addr >= coresize) return(-1); opc = corefetchu(addr,1); if (addr+instrs[opc].nbytes > coresize) { flags[addr] = CF_BYTE; return(0); } spform = 0; a = addr; if (instrs[opc].nbytes == 0) { if (addr+1 >= coresize) { flags[addr] = CF_BYTE; return(0); } a ++; opc = corefetchu(a,1); spform = 1; if (! instrs[opc].can_sp) { flags[addr] = CF_BYTE; return(0); } } if (a+instrs[opc].nbytes > coresize) { flags[addr] = CF_BYTE; return(0); } nb = instrs[opc].nbytes + (a - addr); for (i=0;i<4;i++) { if (i < nb) fnprintf(fn,"%02lx ",corefetchu(addr+i,1)); else fnprintf(fn," "); } fnprintf(fn," "); process_format(fn,instrs[opc].fmt,a,flg,spform); if (flg & CFF_INST_PARALLEL) { fnprintf(fn," (parallel)"); return(1); } for (i=nb-1;i>0;i--) flags[addr+i] = CF_PREV; return(nb); } static void mc68hc908_init(void) { int x; INSTR *i; for (x=256-1;x>=0;x--) { i = &instrs[x]; i->can_sp = (strstr(i->fmt,"~x") || strstr(i->fmt,"~X")); } } static int mc68hc908_dis(ADDR addr, void (*fn)(char)) { int rv; if (ISINST(flags[addr-corebase])) { rv = do_dis_inst(addr,fn,flags[addr-corebase]); } else { fnprintf(fn,"",(unsigned long int)flags[addr-corebase]); rv = 1; } return(rv); } static unsigned long int mc68hc908_fetch(const void *base, int size) #define bp(n) ((unsigned long int)(((const unsigned char *)base)[(n)])) { switch (size) { case 1: return(bp(0)); break; case 2: return((bp(0)<<8)|bp(1)); break; case 3: return((bp(0)<<16)|(bp(1)<<8)|bp(2)); break; case 4: return((bp(0)<<24)|(bp(1)<<16)|(bp(2)<<8)|bp(3)); break; } abort(); } #undef bp static const char *mc68hc908_names[] = { "MC68HC908", "mc68hc908", 0 }; MACHINE machine_mc68hc908 = { &mc68hc908_names[0], 2, &mc68hc908_init, 0, &mc68hc908_dis, &mc68hc908_fetch, 0 };