//---------------------------------------------------------------------- static void process_operand(op_t &x, bool isload) { ea_t ea; dref_t dref; if ( is_forced_operand(cmd.ea, x.n) ) return; switch ( x.type ) { case o_reg: case o_phrase: break; case o_imm: if ( !isload ) interr("emu1"); process_immediate_number(x.n); if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dr_O, OOFS_IFSIGN|OOFW_IMM); break; case o_mem: ea = calc_mem(x.addr); ua_dodata2(x.offb, ea, x.dtyp); dref = cmd.itype == I960_lda ? dr_O : isload ? dr_R : dr_W; ua_add_dref(x.offb, ea, dref); break; case o_near: { cref_t ftype = fl_JN; ea = calc_mem(x.addr); if ( InstrIsSet(cmd.itype, CF_CALL) ) { flow = func_does_return(ea); ftype = fl_CN; } ua_add_cref(x.offb, ea, ftype); } break; case o_displ: dref = cmd.itype == I960_lda ? dr_O : isload ? dr_R : dr_W; process_immediate_number(x.n); if ( x.reg == IP ) { ea_t ea = cmd.ea + 8 + x.addr; ua_add_dref(x.offb, ea, dref); } else { if ( isOff(uFlag, x.n) ) ua_add_off_drefs2(x, dref, OOFS_IFSIGN|OOF_SIGNED|OOF_ADDR|OOFW_32); } break; default: interr("emu"); } }
//---------------------------------------------------------------------- bool idaapi outop(op_t &x) { ea_t ea; if ( x.type == o_imm ) out_symbol('#'); char buf[MAXSTR]; switch ( x.type ) { case o_void: return 0; case o_imm: OutValue(x, OOFS_IFSIGN|OOFW_IMM); break; case o_reg: outreg(x.reg); break; case o_mem: // no break; case o_near: { ea = calc_mem(x); if ( ea == cmd.ea+cmd.size ) out_ip_rel(cmd.size); else if ( !out_name_expr(x, ea, x.addr) ) out_bad_address(x.addr); } break; case o_phrase: { qsnprintf(buf, sizeof(buf), "%%%c%" FMT_EA "x", 'a' + x.reg, x.value); ea = calc_data_mem(x, as + x.reg); if ( ( ea != BADADDR ) && ( ( x.reg != SR3 ) || ( x.value < 6 ) ) ) { out_line(buf, COLOR_AUTOCMT); out_symbol(' '); out_address(ea, x); } else out_line(buf, COLOR_REG); } break; default: interr("out"); break; } return 1; }
//---------------------------------------------------------------------- bool outop(op_t &x) { ea_t ea; char buf[MAXSTR]; if ( x.type == o_imm ) out_symbol('#'); switch ( x.type ) { case o_void: return 0; case o_imm: if ( x.amode & amode_signed ) OutValue(x, OOF_SIGNED|OOFW_IMM); else OutValue(x, OOFS_IFSIGN|OOFW_IMM); break; case o_reg: outreg(x.reg); break; case o_mem: // no break; ea = calc_mem(x); if ( ea != BADADDR ) out_address(ea, x); else { out_tagon(COLOR_ERROR); OutValue(x, OOFW_IMM|OOF_ADDR|OOFW_16); out_tagoff(COLOR_ERROR); } break; case o_near: { ea_t ea = calc_mem(x); // xmem ioports if ( x.amode & (amode_x) && out_port_address(x.addr) ) { char nbuf[MAXSTR]; const char *pnam = find_port(x.addr); const char *name = get_true_name(BADADDR, ea, nbuf, sizeof(nbuf)); if ( name == NULL || strcmp(name, pnam) != 0 ) set_name(ea, pnam); break; } if ( ea == cmd.ea+cmd.size ) out_ip_rel(cmd.size); else if ( !out_name_expr(x, ea, x.addr) ) out_bad_address(x.addr); } break; case o_phrase: { if ( x.phtype < 4 ) { qsnprintf(buf, sizeof(buf), formats[x.phtype], x.phrase); out_colored_register_line(buf); } if ( x.phtype == 4 ) { out_symbol('('); outreg(x.reg); out_symbol(')'); } } break; case o_local: { out_colored_register_line(formats2[x.phtype]); OutValue(x, OOF_SIGNED|OOF_ADDR); if ( x.phtype == 0 ) out_symbol(')'); break; } case o_textphrase: { char buf[MAXSTR]; switch ( x.textphtype ) { case text_swap: out_line(swap_formats[x.phrase], COLOR_REG); break; case text_banke: int comma; char r0[10], r1[10], r4[10], cfgi[10]; comma = 0; r0[0]=r1[0]=r4[0]=cfgi[0]='\0'; if ( x.phrase & 0x01 ) //cfgi { qsnprintf(cfgi, sizeof(cfgi), "cfgi"); comma = 1; } if ( x.phrase & 0x02 ) //r4 { qsnprintf(r4, sizeof(r4), "r4%s", (comma?", ":"")); comma = 1; } if ( x.phrase & 0x04 ) //r1 { qsnprintf(r1, sizeof(r1), "r1%s", (comma?", ":"")); comma = 1; } if ( x.phrase & 0x08 ) //r0 qsnprintf(r0, sizeof(r0), "r0%s", (comma?", ":"")); qsnprintf(buf, sizeof(buf), "%s%s%s%s", r0, r1, r4, cfgi ); out_line(buf, COLOR_REG); break; case text_cntx: out_symbol( (x.phrase ? 'r': 's') ); break; case text_dmod: if ( x.phrase ) qsnprintf(buf, sizeof(buf), " no modulo"); else qsnprintf(buf, sizeof(buf), " modulo"); out_line(buf, COLOR_REG); break; case text_eu: qsnprintf(buf, sizeof(buf), " eu"); out_line(buf, COLOR_REG); break; } } break; default: interr("out"); break; } return 1; }
//---------------------------------------------------------------------- bool outop(op_t &x) { switch ( x.type ) { case o_void: return 0; case o_reg: outreg(x.reg); break; case o_imm: out_symbol('#'); OutValue(x, OOFS_IFSIGN|OOFW_IMM); break; case o_displ: // o_displ Short Direct Indexed ld A,($10,X) 00..1FE + 1 // o_displ Long Direct Indexed ld A,($1000,X) 0000..FFFF + 2 out_symbol('('); OutValue(x, OOFS_IFSIGN |OOF_ADDR |((cmd.auxpref & aux_16) ? OOFW_16 : OOFW_8)); out_symbol(','); outreg(x.reg); out_symbol(')'); break; case o_phrase: out_symbol('('); outreg(x.reg); out_symbol(')'); break; case o_mem: // o_mem Short Direct ld A,$10 00..FF + 1 // o_mem Long Direct ld A,$1000 0000..FFFF + 2 // o_mem Short Indirect ld A,[$10] 00..FF 00..FF byte + 2 // o_mem Long Indirect ld A,[$10.w] 0000..FFFF 00..FF word + 2 // o_mem Short Indirect Indexed ld A,([$10],X) 00..1FE 00..FF byte + 2 // o_mem Long Indirect Indexed ld A,([$10.w],X) 0000..FFFF 00..FF word + 2 // o_mem Relative Indirect jrne [$10] PC+/-127 00..FF byte + 2 // o_mem Bit Direct bset $10,#7 00..FF + 1 // o_mem Bit Indirect bset [$10],#7 00..FF 00..FF byte + 2 // o_mem Bit Direct Relative btjt $10,#7,skip 00..FF + 2 // o_mem Bit Indirect Relative btjt [$10],#7,skip 00..FF 00..FF byte + 3 if ( cmd.auxpref & aux_index ) out_symbol('('); if ( cmd.auxpref & aux_indir ) out_symbol('['); outmem(x, calc_mem(x.addr)); if ( cmd.auxpref & aux_long ) out_symbol('.'); if ( cmd.auxpref & aux_long ) out_symbol('w'); if ( cmd.auxpref & aux_indir ) out_symbol(']'); if ( cmd.auxpref & aux_index ) { out_symbol(','); outreg(x.reg); out_symbol(')'); } break; case o_near: outmem(x, calc_mem(x.addr)); break; default: interr("out"); break; } return 1; }
//---------------------------------------------------------------------- bool outop(op_t &x) { switch ( x.type ) { case o_void: return 0; case o_reg: outreg(x.reg); break; case o_reglist: out_symbol('('); out_reglist(x.reg, 8); out_symbol(')'); break; case o_imm: out_symbol('#'); OutValue(x, calc_opimm_flags()); out_sizer(x); break; case o_mem: out_symbol('@'); case o_near: case o_far: { ea_t ea = calc_mem(x); if ( !out_name_expr(x, ea, BADADDR) ) out_bad_address(x.addr); out_sizer(x); } break; case o_phrase: if ( x.phtype == ph_normal ) { bool outdisp = isOff(uFlag,x.n) || isStkvar(uFlag,x.n) || isEnum(uFlag,x.n) || isStroff(uFlag,x.n); if ( outdisp ) goto OUTDISP; } out_symbol('@'); if ( x.phtype == ph_pre ) out_symbol('-'); outreg(x.phrase); if ( x.phtype == ph_post ) out_symbol('+'); break; case o_displ: OUTDISP: out_symbol('@'); out_symbol('('); OutValue(x, calc_opdispl_flags()); out_sizer(x); out_symbol(','); outreg(x.reg); out_symbol(')'); break; default: interr("out"); break; } return 1; }
//-------------------------------------------------------------------------- int ana(void) { int code = ua_next_byte(); int saved_code = code; char dtyp = dt_byte; if ( code < 0x60 ) { cmd.itype = A2[code]; } else { if ( code & 8 ) { cmd.auxpref |= aux_word; dtyp = dt_word; } else { cmd.auxpref |= aux_byte; dtyp = dt_byte; } cmd.itype = A2tail[(code>>4)-6]; } if ( cmd.itype == H8500_null ) return 0; switch ( code ) { case 0x02: // ldm.w @sp+, <reglist> // cmd.auxpref |= aux_word; phrase(cmd.Op1, SP, ph_post, dt_word); cmd.Op2.type = o_reglist; cmd.Op2.reg = ua_next_byte(); if ( !cmd.Op2.reg ) return 0; break; case 0x12: // stm.w <reglist>, @-sp // cmd.auxpref |= aux_word; cmd.Op1.type = o_reglist; cmd.Op1.reg = ua_next_byte(); if ( !cmd.Op1.reg ) return 0; phrase(cmd.Op2, SP, ph_pre, dt_word); break; case 0x01: // scb/f cmd.auxpref |= aux_f; break; case 0x06: // scb/ne cmd.auxpref |= aux_ne; break; case 0x07: // scb/eq cmd.auxpref |= aux_eq; break; case 0x08: // trapa #xx code = ua_next_byte(); if ( (code & 0xF0) != 0x10 ) return 0; cmd.Op1.type = o_imm; cmd.Op1.dtyp = dt_byte; cmd.Op1.value = code & 15; break; case 0x0F: // unlk reg(cmd.Op1, FP, dt_word); break; case 0x10: // jmp @aa:16 case 0x18: // jsr @aa:16 aa16(cmd.Op1, dt_code); cmd.Op1.type = o_near; cmd.Op1.addr += cmd.ea & ~0xFFFF; break; case 0x17: // link #xx:8 reg(cmd.Op1, FP, dt_word); imm8(cmd.Op2); break; case 0x1F: // link #xx:16 reg(cmd.Op1, FP, dt_word); imm16(cmd.Op2); break; case 0x03: // pjsr @aa:24 case 0x13: // pjmp @aa:24 { cmd.auxpref |= aux_disp24; uint32 page = ua_next_byte(); cmd.Op1.type = o_far; cmd.Op1.dtyp = dt_code; cmd.Op1.addr = (page<<16) | ua_next_word(); } break; case 0x04: // #xx:8 cmd.auxpref |= aux_byte; case 0x14: // #xx:8 imm8(cmd.Op1); break; case 0x05: // #aa:8.B cmd.auxpref |= aux_byte; aa8(cmd.Op1, dt_byte); break; case 0x15: // #aa:16.B cmd.auxpref |= aux_byte; aa16(cmd.Op1, dt_byte); break; case 0x0C: // #xx:16 cmd.auxpref |= aux_word; case 0x1C: // #xx:16 imm16(cmd.Op1); break; case 0x0D: // #aa:8.W cmd.auxpref |= aux_word; aa8(cmd.Op1, dt_word); dtyp = dt_word; break; case 0x1D: // #aa:16.W cmd.auxpref |= aux_word; aa16(cmd.Op1, dt_word); dtyp = dt_word; break; case 0x0E: // bsr d:8 case 0x20: case 0x21: case 0x22: case 0x23: // d:8 case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2A: case 0x2B: case 0x2C: case 0x2D: case 0x2E: case 0x2F: d8(cmd.Op1); break; case 0x1E: // bsr d:16 case 0x30: case 0x31: case 0x32: case 0x33: // d:16 case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3A: case 0x3B: case 0x3C: case 0x3D: case 0x3E: case 0x3F: { cmd.auxpref |= aux_disp16; int32 disp = short(ua_next_word()); cmd.Op1.type = o_near; cmd.Op1.dtyp = dt_code; cmd.Op1.addr = cmd.ip + cmd.size + disp; } break; case 0x40: case 0x41: case 0x42: case 0x43: // cmp:e #xx:8, Rn case 0x44: case 0x45: case 0x46: case 0x47: case 0x50: case 0x51: case 0x52: case 0x53: // mov:e #xx:8, Rn case 0x54: case 0x55: case 0x56: case 0x57: cmd.auxpref |= aux_byte; imm8(cmd.Op1); reg(cmd.Op2, code, dtyp); break; case 0x48: case 0x49: case 0x4A: case 0x4B: // cmp:i #xx:16, Rn case 0x4C: case 0x4D: case 0x4E: case 0x4F: case 0x58: case 0x59: case 0x5A: case 0x5B: // mov:i #xx:16, Rn case 0x5C: case 0x5D: case 0x5E: case 0x5F: cmd.auxpref |= aux_word; imm16(cmd.Op1); reg(cmd.Op2, code, dtyp); break; case 0x60: case 0x61: case 0x62: case 0x63: // @aa:8, Rn case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6A: case 0x6B: case 0x6C: case 0x6D: case 0x6E: case 0x6F: aa8(cmd.Op1, dtyp); reg(cmd.Op2, code, dtyp); break; case 0x70: case 0x71: case 0x72: case 0x73: // Rn, @aa:8 case 0x74: case 0x75: case 0x76: case 0x77: case 0x78: case 0x79: case 0x7A: case 0x7B: case 0x7C: case 0x7D: case 0x7E: case 0x7F: reg(cmd.Op1, code, dtyp); aa8(cmd.Op2, dtyp); break; case 0x80: case 0x81: case 0x82: case 0x83: // mov:f @(d:8, R6), Rn case 0x84: case 0x85: case 0x86: case 0x87: case 0x88: case 0x89: case 0x8A: case 0x8B: case 0x8C: case 0x8D: case 0x8E: case 0x8F: ds8(cmd.Op1, R6, dtyp); reg(cmd.Op2, code, dtyp); break; case 0x90: case 0x91: case 0x92: case 0x93: // mov:f Rn, @(d:8, R6) case 0x94: case 0x95: case 0x96: case 0x97: case 0x98: case 0x99: case 0x9A: case 0x9B: case 0x9C: case 0x9D: case 0x9E: case 0x9F: reg(cmd.Op1, code, dtyp); ds8(cmd.Op2, R6, dtyp); break; case 0xA0: case 0xA1: case 0xA2: case 0xA3: // Rn, Rn case 0xA4: case 0xA5: case 0xA6: case 0xA7: case 0xA8: case 0xA9: case 0xAA: case 0xAB: case 0xAC: case 0xAD: case 0xAE: case 0xAF: reg(cmd.Op1, code, dtyp); break; case 0xB0: case 0xB1: case 0xB2: case 0xB3: // @-Rn, Rn case 0xB4: case 0xB5: case 0xB6: case 0xB7: case 0xB8: case 0xB9: case 0xBA: case 0xBB: case 0xBC: case 0xBD: case 0xBE: case 0xBF: phrase(cmd.Op1, code, ph_pre, dtyp); break; case 0xC0: case 0xC1: case 0xC2: case 0xC3: // @Rn+, Rn case 0xC4: case 0xC5: case 0xC6: case 0xC7: case 0xC8: case 0xC9: case 0xCA: case 0xCB: case 0xCC: case 0xCD: case 0xCE: case 0xCF: phrase(cmd.Op1, code, ph_post, dtyp); break; case 0xD0: case 0xD1: case 0xD2: case 0xD3: // @Rn, Rn case 0xD4: case 0xD5: case 0xD6: case 0xD7: case 0xD8: case 0xD9: case 0xDA: case 0xDB: case 0xDC: case 0xDD: case 0xDE: case 0xDF: phrase(cmd.Op1, code, ph_normal, dtyp); break; case 0xE0: case 0xE1: case 0xE2: case 0xE3: // @(d:8,Rn), Rn case 0xE4: case 0xE5: case 0xE6: case 0xE7: case 0xE8: case 0xE9: case 0xEA: case 0xEB: case 0xEC: case 0xED: case 0xEE: case 0xEF: ds8(cmd.Op1, code, dtyp); break; case 0xF0: case 0xF1: case 0xF2: case 0xF3: // @(d:16,Rn), Rn case 0xF4: case 0xF5: case 0xF6: case 0xF7: case 0xF8: case 0xF9: case 0xFA: case 0xFB: case 0xFC: case 0xFD: case 0xFE: case 0xFF: ds16(cmd.Op1, code, dtyp); break; } while ( cmd.itype > H8500_last ) // while MAPs are not resolved { int index = -(3+short(cmd.itype)); if ( index < 0 || index >= qnumber(tables) ) interr("ana1"); code = ua_next_byte(); if ( code < 0x20 ) { cmd.itype = tables[index].head[code]; } else { cmd.itype = tables[index].tail[(code>>3)-4]; reg(cmd.Op2, code, dtyp); } if ( index == 3 ) switch ( saved_code ) // MAP6 { case 0x01: case 0x06: case 0x07: if ( cmd.itype != H8500_scb ) return 0; break; case 0x11: if ( cmd.itype != H8500_prts && cmd.itype != H8500_prtd && cmd.itype != H8500_jmp && cmd.itype != H8500_pjmp && cmd.itype != H8500_jsr && cmd.itype != H8500_pjsr ) return 0; break; default: if ( cmd.itype != H8500_movfpe && cmd.itype != H8500_movtpe && cmd.itype != H8500_dadd && cmd.itype != H8500_dsub ) return 0; } switch ( cmd.itype ) { case H8500_null: return 0; case H8500_add_q: cmd.Op2 = cmd.Op1; switch ( code ) { case 0x08: immv(cmd.Op1, 1); break; case 0x09: immv(cmd.Op1, 2); break; case 0x0C: immv(cmd.Op1, -1); break; case 0x0D: immv(cmd.Op1, -2); break; } break; case H8500_bset: case H8500_bclr: case H8500_bnot: case H8500_btst: cmd.Op2 = cmd.Op1; if ( code < 0xC0 ) reg(cmd.Op1, code, dtyp); else immv(cmd.Op1, code & 15); break; case H8500_mov_g: if ( (code & 0xF8) == 0x80 ) break; cmd.Op2 = cmd.Op1; if ( code == 0x06 ) { if ( (cmd.auxpref & aux_word) == 0 ) cmd.auxpref |= aux_byte; cmd.Op1.type = o_imm; cmd.Op1.dtyp = dt_byte; cmd.Op1.value = ua_next_byte(); } else if ( code == 0x07 ) { if ( (cmd.auxpref & aux_byte) == 0 ) cmd.auxpref |= aux_word; cmd.auxpref |= aux_mov16; cmd.Op1.type = o_imm; cmd.Op1.dtyp = dt_word; cmd.Op1.value = ua_next_word(); } else reg(cmd.Op1, code, dtyp); break; case H8500_cmp_g: if ( code > 5 ) break; cmd.Op2 = cmd.Op1; if ( code == 0x04 ) { cmd.auxpref |= aux_byte; cmd.Op1.type = o_imm; cmd.Op1.dtyp = dt_byte; cmd.Op1.value = ua_next_byte(); } else { cmd.auxpref |= aux_word; cmd.Op1.type = o_imm; cmd.Op1.dtyp = dt_word; cmd.Op1.value = ua_next_word(); } break; case H8500_andc: case H8500_orc: case H8500_xorc: case H8500_ldc: case H8500_stc: cmd.Op2.reg += SR; if ( cmd.Op2.reg == RES1 || cmd.Op2.reg == CP ) return 0; if ( ((cmd.auxpref & aux_word) != 0) != (cmd.Op2.reg == SR) ) return 0; if ( cmd.itype != H8500_stc ) break; // no break case H8500_movtpe: { op_t x = cmd.Op1; cmd.Op1 = cmd.Op2; cmd.Op2 = x; } break; case H8500_pjmp: case H8500_pjsr: case H8500_jmp: case H8500_jsr: cmd.Op2.type = o_void; switch ( code & 0xF0 ) { case 0xC0: case 0xD0: phrase(cmd.Op1, code, ph_normal, dt_code); break; case 0xE0: ds8(cmd.Op1, code, dt_code); break; case 0xF0: ds16(cmd.Op1, code, dt_code); break; } break; case H8500_rtd: case H8500_prtd: if ( code == 0x14 ) imm8(cmd.Op1); else imm16(cmd.Op1); break; case H8500_scb: cmd.Op1 = cmd.Op2; d8(cmd.Op2); break; case H8500_dadd: case H8500_dsub: if ( (cmd.auxpref & aux_byte) == 0 ) return 0; cmd.auxpref &= ~aux_byte; break; } } if ( (idpflags & AFIDP_MIXSIZE) == 0 ) // Disassemble mixed size instructions? { if ( (cmd.auxpref & aux_word) && cmd.Op1.dtyp == dt_byte || (cmd.auxpref & aux_byte) && cmd.Op1.dtyp == dt_word ) if ( cmd.itype != H8500_mov_g ) return 0; } return cmd.size; }