update to ida 7.6, add builds
This commit is contained in:
409
idasdk76/module/h8500/out.cpp
Normal file
409
idasdk76/module/h8500/out.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "h8500.hpp"
|
||||
#include <segregs.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_h8500_t : public outctx_t
|
||||
{
|
||||
out_h8500_t(void) = delete; // not used
|
||||
public:
|
||||
void outreg(int r) { out_register(ph.reg_names[r]); }
|
||||
void out_bad_address(ea_t addr);
|
||||
void out_sizer(const op_t &x);
|
||||
void out_reglist(int reg, int cnt);
|
||||
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
};
|
||||
CASSERT(sizeof(out_h8500_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_h8500_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8500_t::out_bad_address(ea_t addr)
|
||||
{
|
||||
h8500_t &pm = *static_cast<h8500_t *>(procmod);
|
||||
const char *name = pm.find_sym((int)addr);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(addr, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
static int calc_sizer(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
if ( insn.itype == H8500_mov_g && x.type == o_imm )
|
||||
return insn.auxpref & aux_mov16 ? 16 : 8;
|
||||
// special case: cmp:g.b #x:8, @(d:16,r)
|
||||
// special case: cmp:g.w #x:16, @(d:8,r)
|
||||
else if ( insn.itype == H8500_cmp_g && x.type == o_imm )
|
||||
return insn.auxpref & aux_word ? 16 : 8;
|
||||
else
|
||||
return (insn.auxpref & aux_disp24) ? 24 : (insn.auxpref & aux_disp16) ? 16 : 8;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_mem(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
if ( x.type == o_near )
|
||||
return to_ea(insn.cs, x.addr);
|
||||
|
||||
// Before this was simply to_ea, now we do it like this:
|
||||
// (if someone complains, both methods should be retained)
|
||||
ea_t ea = x.addr;
|
||||
switch ( calc_sizer(insn, x) )
|
||||
{
|
||||
case 8:
|
||||
if ( insn.auxpref & aux_page )
|
||||
{
|
||||
ea &= 0xFF;
|
||||
sel_t br = get_sreg(insn.ea, BR);
|
||||
if ( br != BADSEL )
|
||||
ea |= br << 8;
|
||||
else
|
||||
ea = BADADDR;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
ea &= 0xFFFF;
|
||||
if ( x.type == o_mem )
|
||||
{
|
||||
sel_t dp = get_sreg(insn.ea, DP);
|
||||
if ( dp != BADSEL )
|
||||
ea |= dp << 16;
|
||||
else
|
||||
ea = BADADDR;
|
||||
}
|
||||
else
|
||||
{
|
||||
ea |= insn.ea & ~0xFFFF;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return ea;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8500_t::out_sizer(const op_t &x)
|
||||
{
|
||||
h8500_t &pm = *static_cast<h8500_t *>(procmod);
|
||||
if ( pm.show_sizer == -1 )
|
||||
pm.show_sizer = !qgetenv("H8_NOSIZER");
|
||||
if ( !pm.show_sizer )
|
||||
return;
|
||||
if ( (insn.auxpref & (aux_disp8|aux_disp16|aux_disp24)) == 0 )
|
||||
return;
|
||||
out_symbol(':');
|
||||
// 1D 00 11 07 00 01 mov:g.w #1:16, @0x11:16
|
||||
// 1D 00 11 06 01 mov:g.w #1:16, @0x11:16
|
||||
// 0D 11 07 00 01 mov:g.w #1:8, @0x11:8
|
||||
// 0D 11 06 01 mov:g.w #1:8, @0x11:8
|
||||
// 0D 11 07 00 01 mov:g.w #1:8, @0x11:8
|
||||
// 1D 00 11 07 00 01 mov:g.w #1:16, @0x11:16
|
||||
// 15 00 11 06 01 mov:g.b #1:16, @0x11:16
|
||||
// 05 11 06 01 mov:g.b #1:8, @0x11:8
|
||||
int s = calc_sizer(insn, x);
|
||||
out_long(s, 10);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8500_t::out_reglist(int reg, int cnt)
|
||||
{
|
||||
int bit = 1;
|
||||
int delayed = -1;
|
||||
int first = 1;
|
||||
for ( int i=0; i <= cnt; i++,bit<<=1 )
|
||||
{
|
||||
if ( (reg & bit) == 0 )
|
||||
{
|
||||
if ( delayed >= 0 )
|
||||
{
|
||||
if ( !first )
|
||||
out_symbol(',');
|
||||
if ( delayed == (i-1) )
|
||||
{
|
||||
outreg(delayed);
|
||||
}
|
||||
else if ( delayed == (i-2) )
|
||||
{
|
||||
outreg(delayed);
|
||||
out_symbol(',');
|
||||
outreg(delayed+1);
|
||||
}
|
||||
else
|
||||
{
|
||||
outreg(delayed);
|
||||
out_symbol('-');
|
||||
outreg(i-1);
|
||||
}
|
||||
delayed = -1;
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( delayed < 0 )
|
||||
delayed = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int calc_opimm_flags(const insn_t &insn)
|
||||
{
|
||||
bool sign = insn.itype == H8500_add_q
|
||||
|| insn.itype == H8500_adds
|
||||
|| insn.itype == H8500_subs;
|
||||
return OOFS_IFSIGN|OOFW_IMM|(sign ? OOF_SIGNED : 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int calc_opdispl_flags(const insn_t &insn)
|
||||
{
|
||||
bool sign = (insn.auxpref & aux_disp8) != 0;
|
||||
return OOF_ADDR | OOFS_IFSIGN | (sign ? OOF_SIGNED : 0)
|
||||
| (insn.auxpref & aux_disp24 ? OOFW_32
|
||||
: insn.auxpref & aux_disp16 ? OOFW_16
|
||||
: OOFW_8);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_h8500_t::out_operand(const 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('#');
|
||||
out_value(x, calc_opimm_flags(insn));
|
||||
out_sizer(x);
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
out_symbol('@');
|
||||
// fallthrough
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
ea_t ea = calc_mem(insn, 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 = is_off(F, x.n)
|
||||
|| is_stkvar(F, x.n)
|
||||
|| is_enum(F, x.n)
|
||||
|| is_stroff(F, 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('(');
|
||||
out_value(x, calc_opdispl_flags(insn));
|
||||
out_sizer(x);
|
||||
out_symbol(',');
|
||||
outreg(x.reg);
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10099);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8500_t::out_proc_mnem(void)
|
||||
{
|
||||
const char *postfix = NULL;
|
||||
if ( insn.auxpref & aux_byte )
|
||||
postfix = ".b";
|
||||
else if ( insn.auxpref & aux_word )
|
||||
postfix = ".w";
|
||||
else if ( insn.auxpref & aux_f )
|
||||
postfix = "/f";
|
||||
else if ( insn.auxpref & aux_ne )
|
||||
postfix = "/ne";
|
||||
else if ( insn.auxpref & aux_eq )
|
||||
postfix = "/eq";
|
||||
out_mnem(8, postfix);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_h8500_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
out_one_operand(0);
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Srange) could be made const
|
||||
void h8500_t::h8500_segstart(outctx_t &ctx, segment_t *Srange) const
|
||||
{
|
||||
const char *predefined[] =
|
||||
{
|
||||
".text", // Text section
|
||||
".rdata", // Read-only data section
|
||||
".data", // Data sections
|
||||
".lit8", // Data sections
|
||||
".lit4", // Data sections
|
||||
".sdata", // Small data section, addressed through register $gp
|
||||
".sbss", // Small bss section, addressed through register $gp
|
||||
".bss", // bss (block started by storage) section, which loads zero-initialized data
|
||||
};
|
||||
|
||||
if ( is_spec_segm(Srange->type) )
|
||||
return;
|
||||
|
||||
qstring sname;
|
||||
qstring sclas;
|
||||
get_segm_name(&sname, Srange);
|
||||
get_segm_class(&sclas, Srange);
|
||||
|
||||
if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) )
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT),
|
||||
sclas == "CODE" ? ".text" :
|
||||
sclas == "BSS" ? ".bss" :
|
||||
".data",
|
||||
ash.cmnt,
|
||||
sname.c_str());
|
||||
if ( Srange->orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), Srange->orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi h8500_segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
void h8500_t::h8500_assume(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *seg = getseg(ea);
|
||||
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL )
|
||||
return;
|
||||
bool seg_started = (ea == seg->start_ea);
|
||||
|
||||
for ( int i=ph.reg_first_sreg; i <= ph.reg_last_sreg; i++ )
|
||||
{
|
||||
if ( i == ph.reg_code_sreg )
|
||||
continue;
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) )
|
||||
continue;
|
||||
bool show = sra.start_ea == ea;
|
||||
if ( show )
|
||||
{
|
||||
sreg_range_t prev_sra;
|
||||
if ( get_prev_sreg_range(&prev_sra, ea, i) )
|
||||
show = sra.val != prev_sra.val;
|
||||
}
|
||||
if ( seg_started || show )
|
||||
{
|
||||
if ( ctx.outbuf.empty() )
|
||||
{
|
||||
ctx.out_tagon(COLOR_AUTOCMT);
|
||||
ctx.out_line(ash.cmnt);
|
||||
ctx.out_line(" assume ");
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.out_line(", ");
|
||||
}
|
||||
ctx.out_line(ph.reg_names[i]);
|
||||
ctx.out_char(':');
|
||||
if ( sra.val == BADSEL )
|
||||
ctx.out_line("nothing");
|
||||
else
|
||||
ctx.out_btoa(sra.val, 16);
|
||||
}
|
||||
}
|
||||
if ( !ctx.outbuf.empty() )
|
||||
{
|
||||
ctx.out_tagoff(COLOR_AUTOCMT);
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void idaapi h8500_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL);
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void h8500_t::h8500_footer(outctx_t &ctx) const
|
||||
{
|
||||
qstring nbuf = get_colored_name(inf_get_start_ea());
|
||||
const char *name = nbuf.c_str();
|
||||
const char *end = ash.end;
|
||||
if ( end == NULL )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name);
|
||||
else
|
||||
ctx.gen_printf(DEFAULT_INDENT,
|
||||
COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT),
|
||||
ash.end, ash.cmnt, name);
|
||||
}
|
||||
Reference in New Issue
Block a user