update to ida 7.6, add builds
This commit is contained in:
1796
idasdk76/module/st9/ana.cpp
Normal file
1796
idasdk76/module/st9/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
489
idasdk76/module/st9/emu.cpp
Normal file
489
idasdk76/module/st9/emu.cpp
Normal file
@@ -0,0 +1,489 @@
|
||||
|
||||
#include "st9.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static sel_t calc_page(ea_t insn_ea, ushort addr)
|
||||
{
|
||||
return get_sreg(insn_ea, rDPR0+(addr>>14));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ea_t calc_data_mem_without_mapping(ea_t insn_ea, ea_t addr)
|
||||
{
|
||||
sel_t page = calc_page(insn_ea, (ushort)addr);
|
||||
if ( page == BADSEL )
|
||||
return BADADDR;
|
||||
ea_t ea = use_mapping((page<<14) + (addr & 0x3FFF));
|
||||
return ea;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t get_dest_addr(const insn_t &insn, const op_t &x)
|
||||
{
|
||||
if ( x.type == o_far )
|
||||
return x.addr;
|
||||
else if ( x.type == o_mem )
|
||||
return calc_data_mem_without_mapping(insn.ea, x.addr);
|
||||
else if ( x.type == o_near )
|
||||
return to_ea(insn.cs, x.addr);
|
||||
else
|
||||
return BADADDR;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Emulate an operand.
|
||||
void st9_t::handle_operand(const insn_t &insn, const op_t &op, bool lwrite)
|
||||
{
|
||||
switch ( op.type )
|
||||
{
|
||||
// Code address
|
||||
case o_near:
|
||||
case o_far:
|
||||
{
|
||||
cref_t mode;
|
||||
ea_t ea = get_dest_addr(insn, op);
|
||||
|
||||
// call or jump ?
|
||||
if ( is_call_insn(insn) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
mode = op.type == o_near ? fl_CN: fl_CF;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = op.type == o_near ? fl_JN: fl_JF;
|
||||
}
|
||||
insn.add_cref(ea, op.offb, mode);
|
||||
}
|
||||
break;
|
||||
|
||||
// Memory address
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = get_dest_addr(insn, op);
|
||||
insn.add_dref(ea, op.offb, lwrite ? dr_W : dr_R);
|
||||
insn.create_op_data(ea, op);
|
||||
}
|
||||
break;
|
||||
|
||||
// Immediate value
|
||||
case o_imm:
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
flags_t F = get_flags(insn.ea);
|
||||
// create a comment if this immediate is represented in the .cfg file
|
||||
{
|
||||
const ioport_t * port = find_sym(op.value);
|
||||
if ( port != NULL && !has_cmt(F) )
|
||||
set_cmt(insn.ea, port->cmt.c_str(), false);
|
||||
}
|
||||
// if the value was converted to an offset, then create a data xref:
|
||||
if ( op_adds_xrefs(F, op.n) )
|
||||
insn.add_off_drefs(op, dr_O, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
// Displacement
|
||||
case o_displ:
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( op_adds_xrefs(F, op.n) )
|
||||
{
|
||||
ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR);
|
||||
insn.create_op_data(ea, op);
|
||||
}
|
||||
|
||||
// create stack variables if required
|
||||
if ( may_create_stkvars() && !is_defarg(F, op.n) && op.reg == rrr14 )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL && pfn->flags & FUNC_FRAME )
|
||||
{
|
||||
adiff_t displ = (int16)op.addr;
|
||||
if ( insn.create_stkvar(op, displ, STKVAR_VALID_SIZE) )
|
||||
{
|
||||
op_stkvar(insn.ea, op.n);
|
||||
if ( insn.Op2.type == o_reg )
|
||||
{
|
||||
regvar_t *r = find_regvar(pfn, insn.ea, ph.reg_names[insn.Op2.reg]);
|
||||
if ( r != NULL )
|
||||
{
|
||||
struc_t *s = get_frame(pfn);
|
||||
member_t *m = get_stkvar(NULL, insn, op, displ);
|
||||
if ( s != NULL && m != NULL )
|
||||
{
|
||||
char b[20];
|
||||
qsnprintf(b, sizeof b, "%scopy", r->user);
|
||||
set_member_name(s, m->soff, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Register - Phrase - Void: do nothing
|
||||
case o_reg:
|
||||
case o_phrase:
|
||||
case o_void:
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10076);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Emulate an instruction.
|
||||
int st9_t::st9_emu(const insn_t &insn)
|
||||
{
|
||||
uint32 feature = insn.get_canon_feature(ph);
|
||||
flow = ((feature & CF_STOP) == 0);
|
||||
// is it "jump always"?
|
||||
if ( is_jmp_cc(insn.itype) && insn.auxpref == cT )
|
||||
flow = false;
|
||||
|
||||
if ( insn.Op1.type != o_void) handle_operand(insn, insn.Op1, (feature & CF_CHG1) != 0);
|
||||
if ( insn.Op2.type != o_void) handle_operand(insn, insn.Op2, (feature & CF_CHG2) != 0);
|
||||
if ( insn.Op3.type != o_void) handle_operand(insn, insn.Op3, (feature & CF_CHG3) != 0);
|
||||
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea + insn.size, fl_F);
|
||||
|
||||
// Following code will update the current value of the two virtual
|
||||
// segment registers: RW (register window) and RP (register page).
|
||||
|
||||
bool rw_has_changed = false;
|
||||
bool rp_has_changed = false;
|
||||
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case st9_srp:
|
||||
{
|
||||
sel_t val = insn.Op1.value;
|
||||
if ( val % 2 )
|
||||
val--; // even reduced
|
||||
split_sreg_range(insn.ea+insn.size, rRW, val | (val << 8), SR_auto);
|
||||
}
|
||||
rw_has_changed = true;
|
||||
break;
|
||||
|
||||
case st9_srp0:
|
||||
{
|
||||
sel_t RW = get_sreg(insn.ea, rRW);
|
||||
split_sreg_range(insn.ea+insn.size, rRW, insn.Op1.value | (RW & 0xFF00), SR_auto);
|
||||
}
|
||||
rw_has_changed = true;
|
||||
break;
|
||||
|
||||
case st9_srp1:
|
||||
{
|
||||
sel_t RW = get_sreg(insn.ea, rRW);
|
||||
split_sreg_range(insn.ea+insn.size, rRW, (insn.Op1.value << 8) | (RW & 0x00FF), SR_auto);
|
||||
}
|
||||
rw_has_changed = true;
|
||||
break;
|
||||
|
||||
case st9_spp:
|
||||
split_sreg_range(insn.ea+insn.size, rRP, insn.Op1.value, SR_auto);
|
||||
rp_has_changed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// If RW / RP registers have changed, print a comment which explains the new mapping of
|
||||
// the general registers.
|
||||
|
||||
flags_t F = get_flags(insn.ea);
|
||||
if ( rw_has_changed && !has_cmt(F) )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
sel_t RW = get_sreg(insn.ea+insn.size, rRW);
|
||||
int low = RW & 0x00FF;
|
||||
int high = (RW & 0xFF00) >> 8;
|
||||
|
||||
low *= 8;
|
||||
high *= 8;
|
||||
|
||||
const char *const fmt =
|
||||
"r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n"
|
||||
"r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d";
|
||||
|
||||
qsnprintf(buf, sizeof buf, fmt,
|
||||
0 + low,
|
||||
1 + low,
|
||||
2 + low,
|
||||
3 + low,
|
||||
4 + low,
|
||||
5 + low,
|
||||
6 + low,
|
||||
7 + low,
|
||||
8 + high,
|
||||
9 + high,
|
||||
10 + high,
|
||||
11 + high,
|
||||
12 + high,
|
||||
13 + high,
|
||||
14 + high,
|
||||
15 + high);
|
||||
|
||||
set_cmt(insn.ea, buf, false);
|
||||
}
|
||||
|
||||
if ( rp_has_changed && !has_cmt(F) )
|
||||
{
|
||||
char buf[MAXSTR];
|
||||
int rpval = get_sreg(insn.ea+insn.size, rRP);
|
||||
qsnprintf(buf, sizeof buf, "Registers R240-R255 will now be referred to the page %d of paged registers",
|
||||
rpval);
|
||||
set_cmt(insn.ea, buf, false);
|
||||
}
|
||||
|
||||
// reanalyze switch info
|
||||
if ( insn.itype == st9_jp && get_auto_state() == AU_USED )
|
||||
{
|
||||
switch_info_t si;
|
||||
if ( get_switch_info(&si, insn.ea) > 0 && !si.is_user_defined() )
|
||||
{
|
||||
delete_switch_table(insn.ea, si);
|
||||
if ( st9_is_switch(&si, insn) )
|
||||
{
|
||||
set_switch_info(insn.ea, si);
|
||||
create_switch_table(insn.ea, si);
|
||||
}
|
||||
else
|
||||
{
|
||||
del_switch_info(insn.ea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Analyze an instruction
|
||||
static ea_t next_insn(insn_t *insn, ea_t ea)
|
||||
{
|
||||
if ( decode_insn(insn, ea) == 0 )
|
||||
return 0;
|
||||
ea += insn->size;
|
||||
return ea;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// does a far return instruction precede 'ea'?
|
||||
static bool is_far_return(ea_t ea)
|
||||
{
|
||||
insn_t insn;
|
||||
if ( decode_prev_insn(&insn, ea) != BADADDR )
|
||||
return insn.itype == st9_rets;
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// if a function ends with a far return, mark it as such
|
||||
// NB: we only handle regular (non-chunked) functions
|
||||
static void setup_far_func(func_t *pfn)
|
||||
{
|
||||
if ( (pfn->flags & FUNC_FAR) == 0 )
|
||||
{
|
||||
if ( is_far_return(pfn->end_ea) )
|
||||
{
|
||||
pfn->flags |= FUNC_FAR;
|
||||
update_func(pfn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Create a function frame
|
||||
bool st9_t::create_func_frame(func_t *pfn) const
|
||||
{
|
||||
setup_far_func(pfn);
|
||||
|
||||
ea_t ea = pfn->start_ea;
|
||||
|
||||
insn_t insn;
|
||||
ea = next_insn(&insn, ea);
|
||||
if ( !ea )
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Get the total frame size
|
||||
*
|
||||
* LINK rr14, #size
|
||||
*/
|
||||
|
||||
if ( insn.itype != st9_link )
|
||||
return 0;
|
||||
|
||||
int link_register = insn.Op1.reg;
|
||||
size_t total_size = (size_t)insn.Op2.value;
|
||||
|
||||
/*
|
||||
* Get arguments size
|
||||
*
|
||||
* LDW 0x??(rr14), RR??? a word
|
||||
* LD '' a byte
|
||||
*/
|
||||
|
||||
int args_size = 0;
|
||||
|
||||
for ( int i = 0; true; i++ )
|
||||
{
|
||||
insn_t ldi;
|
||||
ea = next_insn(&ldi, ea);
|
||||
if ( !ea )
|
||||
return 0;
|
||||
|
||||
if ( ldi.Op1.type != o_displ || ldi.Op2.type != o_reg )
|
||||
break;
|
||||
|
||||
if ( ldi.Op1.reg != link_register )
|
||||
break;
|
||||
|
||||
if ( ldi.itype == st9_ld ) // byte
|
||||
args_size++;
|
||||
else if ( ldi.itype == st9_ldw ) // word
|
||||
args_size += 2;
|
||||
else
|
||||
break;
|
||||
|
||||
char regvar[10];
|
||||
qsnprintf(regvar, sizeof regvar, "arg_%d", i);
|
||||
int err = add_regvar(pfn, ldi.ea, ldi.ea + ldi.size,
|
||||
ph.reg_names[ldi.Op2.reg], regvar, NULL);
|
||||
if ( err )
|
||||
msg("add_regvar() failed : error %d\n", err);
|
||||
}
|
||||
|
||||
//msg("LOCAL: %d\nARGS: %d\n", total_size - args_size, args_size);
|
||||
|
||||
pfn->flags |= FUNC_FRAME;
|
||||
return add_frame(pfn, total_size - args_size, 0, args_size);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
/*
|
||||
GCC?-produced switch:
|
||||
|
||||
ldw ridx, rin [optional]
|
||||
cpw rin, #n
|
||||
jpugt default | jrugt default
|
||||
addw ridx, ridx
|
||||
spm
|
||||
ldw rjmp, jtbl(ridx)
|
||||
sdm
|
||||
jp (rjmp)
|
||||
jtbl: .word case0, case1, ...
|
||||
*/
|
||||
|
||||
static ea_t check_prev_insn(int itype, insn_t &insn)
|
||||
{
|
||||
ea_t ea = decode_prev_insn(&insn, insn.ea);
|
||||
if ( ea == BADADDR || insn.itype != itype )
|
||||
return BADADDR;
|
||||
return ea;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static bool is_gcc_switch(switch_info_t *_si, insn_t &insn)
|
||||
{
|
||||
switch_info_t &si = *_si;
|
||||
int rjmp, ridx;
|
||||
// si.flags |= SWI_J32;
|
||||
ea_t ea, jtbl_insn;
|
||||
//
|
||||
// Check jump insn and get register number
|
||||
// jp (rjmp)
|
||||
if ( insn.itype != st9_jp
|
||||
|| insn.Op1.type != o_reg
|
||||
|| !is_ind(insn.Op1) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
rjmp = insn.Op1.reg;
|
||||
// sdm
|
||||
ea = check_prev_insn(st9_sdm, insn);
|
||||
if ( ea == BADADDR )
|
||||
return false;
|
||||
// ldw rjmp, jtbl(ridx)
|
||||
ea = check_prev_insn(st9_ldw, insn);
|
||||
if ( ea == BADADDR
|
||||
|| !insn.Op1.is_reg(rjmp)
|
||||
|| insn.Op2.type != o_displ )
|
||||
return false;
|
||||
ridx = insn.Op2.reg;
|
||||
jtbl_insn = ea;
|
||||
// this addr is offset in current code segment because of spm
|
||||
si.jumps = to_ea(insn.cs, insn.Op2.addr);
|
||||
// spm
|
||||
ea = check_prev_insn(st9_spm, insn);
|
||||
if ( ea == BADADDR )
|
||||
return false;
|
||||
|
||||
// addw ridx, ridx
|
||||
ea = check_prev_insn(st9_addw, insn);
|
||||
if ( ea == BADADDR
|
||||
|| !insn.Op1.is_reg(ridx)
|
||||
|| !insn.Op2.is_reg(ridx) )
|
||||
return false;
|
||||
|
||||
// jpugt default | jrugt default
|
||||
ea = decode_prev_insn(&insn, ea);
|
||||
if ( ea != BADADDR
|
||||
&& is_jmp_cc(insn.itype)
|
||||
&& insn.auxpref == cUGT )
|
||||
{
|
||||
si.defjump = get_dest_addr(insn, insn.Op1);
|
||||
// cpw rin, #n
|
||||
ea = check_prev_insn(st9_cpw, insn);
|
||||
if ( ea == BADADDR
|
||||
|| insn.Op2.type != o_imm )
|
||||
return false;
|
||||
int rin = insn.Op1.reg;
|
||||
si.ncases = ushort(insn.Op2.value+1);
|
||||
// is rin the same as ridx?
|
||||
bool ok = insn.Op1.is_reg(ridx);
|
||||
if ( !ok )
|
||||
{
|
||||
// check for preceding ldw ridx, rin
|
||||
ea_t ea2 = decode_prev_insn(&insn, ea);
|
||||
if ( ea2 != BADADDR
|
||||
&& insn.itype == st9_ldw
|
||||
&& insn.Op1.is_reg(ridx)
|
||||
&& insn.Op2.is_reg(rin) )
|
||||
ok = true;
|
||||
}
|
||||
if ( !ok )
|
||||
return false;
|
||||
si.set_expr(rin, insn.Op1.dtype);
|
||||
}
|
||||
//
|
||||
// Everything ok.
|
||||
//
|
||||
msg("SWITCH %a: gcc_switch\n", insn.ea);
|
||||
si.startea = ea;
|
||||
si.set_jtable_element_size(2);
|
||||
si.set_shift(0);
|
||||
op_num(ea, 1); // cpw rin, #n
|
||||
op_plain_offset(jtbl_insn, 1, to_ea(insn.cs, 0)); // ldw rjmp, jtbl(ridx)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool st9_is_switch(switch_info_t *si, const insn_t &insn)
|
||||
{
|
||||
if ( insn.itype == st9_jp )
|
||||
{
|
||||
insn_t copy = insn;
|
||||
return is_gcc_switch(si, copy);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
113
idasdk76/module/st9/ins.cpp
Normal file
113
idasdk76/module/st9/ins.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
|
||||
#include "st9.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
{ "", 0 }, // Null instruction.
|
||||
{ "ld", CF_CHG1|CF_USE2 }, // Load.
|
||||
{ "ldw", CF_CHG1|CF_USE2 }, // Load word.
|
||||
{ "ldpp", CF_CHG1|CF_USE2 }, // Load (using CSR) => (using CSR).
|
||||
{ "ldpd", CF_CHG1|CF_USE2 }, // Load (using DPRx) => (using CSR).
|
||||
{ "lddp", CF_CHG1|CF_USE2 }, // Load (using CSR) => (using DPRx).
|
||||
{ "lddd", CF_CHG1|CF_USE2 }, // Load (using DPRx) => (using DPRx).
|
||||
{ "add", CF_CHG1|CF_USE2 }, // Add.
|
||||
{ "addw", CF_CHG1|CF_USE2 }, // Add Word.
|
||||
{ "adc", CF_CHG1|CF_USE2 }, // Add with Carry.
|
||||
{ "adcw", CF_CHG1|CF_USE2 }, // Add Word with Carry.
|
||||
{ "sub", CF_CHG1|CF_USE2 }, // Substract.
|
||||
{ "subw", CF_CHG1|CF_USE2 }, // Substract Word.
|
||||
{ "sbc", CF_CHG1|CF_USE2 }, // Substract with Carry.
|
||||
{ "sbcw", CF_CHG1|CF_USE2 }, // Substract Word with Carry.
|
||||
{ "and", CF_CHG1|CF_USE2 }, // Logical AND.
|
||||
{ "andw", CF_CHG1|CF_USE2 }, // Logical Word AND.
|
||||
{ "or", CF_CHG1|CF_USE2 }, // Logical OR.
|
||||
{ "orw", CF_CHG1|CF_USE2 }, // Logical Word OR.
|
||||
{ "xor", CF_CHG1|CF_USE2 }, // Logical Exclusive OR.
|
||||
{ "xorw", CF_CHG1|CF_USE2 }, // Logical Word Exclusive OR.
|
||||
{ "cp", CF_USE1|CF_USE2 }, // Compare.
|
||||
{ "cpw", CF_USE1|CF_USE2 }, // Compare Word.
|
||||
{ "tm", CF_USE1|CF_USE2 }, // Test under Mask.
|
||||
{ "tmw", CF_USE1|CF_USE2 }, // Test Word under Mask.
|
||||
{ "tcm", CF_USE1|CF_USE2 }, // Test Complement under Mask.
|
||||
{ "tcmw", CF_USE1|CF_USE2 }, // Test Word Complement under Mask.
|
||||
{ "inc", CF_USE1|CF_CHG1 }, // Increment.
|
||||
{ "incw", CF_USE1|CF_CHG1 }, // Increment Word.
|
||||
{ "dec", CF_USE1|CF_CHG1 }, // Decrement.
|
||||
{ "decw", CF_USE1|CF_CHG1 }, // Decrement Word.
|
||||
{ "sla", CF_USE1|CF_CHG1 }, // Shift Left Arithmetic.
|
||||
{ "slaw", CF_USE1|CF_CHG1 }, // Shift Word Left Arithmetic.
|
||||
{ "sra", CF_USE1|CF_CHG1 }, // Shift Right Arithmetic.
|
||||
{ "sraw", CF_USE1|CF_CHG1 }, // Shift Word Right Arithmetic.
|
||||
{ "rrc", CF_USE1|CF_CHG1 }, // Rotate Right through Carry.
|
||||
{ "rrcw", CF_USE1|CF_CHG1 }, // Rotate Word Right through Carry.
|
||||
{ "rlc", CF_USE1|CF_CHG1 }, // Rotate Left through Carry.
|
||||
{ "rlcw", CF_USE1|CF_CHG1 }, // Rotate Word Left through Carry.
|
||||
{ "ror", CF_USE1|CF_CHG1 }, // Rotate Right.
|
||||
{ "rol", CF_USE1|CF_CHG1 }, // Rotate Left.
|
||||
{ "clr", CF_USE1|CF_CHG1 }, // Clear Register.
|
||||
{ "cpl", CF_USE1|CF_CHG1 }, // Complement Register.
|
||||
{ "swap", CF_USE1|CF_CHG1 }, // Swap Nibbles.
|
||||
{ "da", CF_USE1|CF_CHG1 }, // Decimal ajust.
|
||||
{ "push", CF_USE1 }, // Push on System Stack.
|
||||
{ "pushw", CF_USE1 }, // Push Word on System Stack.
|
||||
{ "pea", CF_USE1 }, // Push Effective Address on System Stack.
|
||||
{ "pop", CF_CHG1 }, // Pop from System Stack.
|
||||
{ "popw", CF_CHG1 }, // Pop Word from System Stack.
|
||||
{ "pushu", CF_USE1 }, // Push on User Stack.
|
||||
{ "pushuw", CF_USE1 }, // Push Word on User Stack.
|
||||
{ "peau", CF_USE1 }, // Push Effective Address on User Stack.
|
||||
{ "popu", CF_CHG1 }, // Pop from User Stack.
|
||||
{ "popuw", CF_CHG1 }, // Pop Word from User Stack.
|
||||
{ "link", CF_USE1|CF_USE2 }, // Move System Stack Pointer upward; support for high-level language.
|
||||
{ "unlink", CF_USE1|CF_USE2 }, // Move System Stack Pointer backward; support for high-level language.
|
||||
{ "linku", CF_USE1|CF_USE2 }, // Move User Stack Pointer upward; support for high-level language.
|
||||
{ "unlinku", CF_USE1|CF_USE2 }, // Move User Stack Pointer backward; support for high-level language.
|
||||
{ "mul", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply 8x8.
|
||||
{ "div", CF_USE1|CF_USE2|CF_CHG1 }, // Divide 8x8.
|
||||
{ "divws", CF_USE1|CF_USE2|CF_USE3|CF_CHG1|CF_CHG2 }, // Divide Word Stepped 32/16.
|
||||
{ "bset", CF_USE1|CF_CHG1 }, // Bit Set.
|
||||
{ "bres", CF_USE1|CF_CHG1 }, // Bit Reset.
|
||||
{ "bcpl", CF_USE1|CF_CHG1 }, // Bit Complement.
|
||||
{ "btset", CF_USE1|CF_CHG1 }, // Bit Test and Set.
|
||||
{ "bld", CF_USE1|CF_CHG1 }, // Bit Load.
|
||||
{ "band", CF_USE1|CF_CHG1 }, // Bit AND.
|
||||
{ "bor", CF_USE1|CF_CHG1 }, // Bit OR.
|
||||
{ "bxor", CF_USE1|CF_CHG1 }, // Bit XOR.
|
||||
{ "ret", CF_STOP }, // Return from Subroutine.
|
||||
{ "rets", CF_STOP }, // Inter-segment Return to Subroutine.
|
||||
{ "iret", CF_STOP }, // Return from Interrupt.
|
||||
{ "jr", CF_USE1 }, // Jump Relative if Condition ``cc'' is Met.
|
||||
{ "jp", CF_USE1 }, // Jump if Condition ``cc'' is Met.
|
||||
{ "jp", CF_USE1|CF_JUMP|CF_STOP }, // Unconditional Jump.
|
||||
{ "jps", CF_USE1|CF_JUMP|CF_STOP }, // Unconditional Inter-segment Jump.
|
||||
{ "call", CF_USE1|CF_CALL|CF_JUMP }, // Unconditional Call.
|
||||
{ "calls", CF_USE1|CF_CALL|CF_JUMP }, // Inter-segment Call to Subroutine.
|
||||
{ "btjf", CF_USE1|CF_USE2 }, // Bit Test and Jump if False.
|
||||
{ "btjt", CF_USE1|CF_USE2 }, // Bit Test and Jump if True.
|
||||
{ "djnz", CF_USE1|CF_CHG1|CF_USE2 }, // Decrement a Working Register and Jump if Non Zero.
|
||||
{ "dwjnz", CF_USE1|CF_CHG1|CF_USE2 }, // Decrement a Register Pair and Jump if Non Zero.
|
||||
{ "cpjfi", CF_USE1|CF_USE2|CF_USE3 }, // Compare and Jump on False. Otherwise Post Increment.
|
||||
{ "cpjti", CF_USE1|CF_USE2|CF_USE3 }, // Compare and Jump on True. Otherwise Post Increment.
|
||||
{ "xch", CF_USE1|CF_USE2 }, // Exchange Registers.
|
||||
{ "srp", CF_USE1 }, // Set Register Pointer Long (16 working registers).
|
||||
{ "srp0", CF_USE1 }, // Set Register Pointer 0 (8 LSB working registers).
|
||||
{ "srp1", CF_USE1 }, // Set Register Pointer 1 (8 MSB working registers).
|
||||
{ "spp", CF_USE1 }, // Set Page Pointer.
|
||||
{ "ext", CF_USE1|CF_CHG1 }, // Sign Extend.
|
||||
{ "ei", 0 }, // Enable Interrupts.
|
||||
{ "di", 0 }, // Disable Interrupts.
|
||||
{ "scf", 0 }, // Set Carry Flag.
|
||||
{ "rcf", 0 }, // Reset Carry Flag.
|
||||
{ "ccf", 0 }, // Complement Carry Flag.
|
||||
{ "spm", 0 }, // Select Extended Memory addressing scheme through CSR Register.
|
||||
{ "sdm", 0 }, // Select Extended Memory addressing scheme through DPR Registers.
|
||||
{ "nop", 0 }, // No Operation.
|
||||
{ "wfi", 0 }, // Stop Program Execution and Wait for the next Enable Interrupt.
|
||||
{ "halt", 0 }, // Stop Program Execution until System Reset.
|
||||
{ "etrap", 0 }, // Undocumented instruction.
|
||||
{ "eret", CF_STOP }, // Undocumented instruction.
|
||||
{ "ald", 0 }, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED.
|
||||
{ "aldw", 0 } // PSEUDO INSTRUCTION. SHOULD NEVER BE USED.
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == st9_last);
|
||||
118
idasdk76/module/st9/ins.hpp
Normal file
118
idasdk76/module/st9/ins.hpp
Normal file
@@ -0,0 +1,118 @@
|
||||
|
||||
#ifndef __INS_HPP
|
||||
#define __INS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
st9_null = 0, // Unknown Operation.
|
||||
st9_ld, // Load.
|
||||
st9_ldw, // Load word.
|
||||
st9_ldpp, // Load (using CSR) => (using CSR).
|
||||
st9_ldpd, // Load (using DPRx) => (using CSR).
|
||||
st9_lddp, // Load (using CSR) => (using DPRx).
|
||||
st9_lddd, // Load (using DPRx) => (using DPRx).
|
||||
st9_add, // Add.
|
||||
st9_addw, // Add Word.
|
||||
st9_adc, // Add with Carry.
|
||||
st9_adcw, // Add Word with Carry.
|
||||
st9_sub, // Substract.
|
||||
st9_subw, // Substract Word.
|
||||
st9_sbc, // Substract with Carry.
|
||||
st9_sbcw, // Substract Word with Carry.
|
||||
st9_and, // Logical AND.
|
||||
st9_andw, // Logical Word AND.
|
||||
st9_or, // Logical OR.
|
||||
st9_orw, // Logical Word OR.
|
||||
st9_xor, // Logical Exclusive OR.
|
||||
st9_xorw, // Logical Word Exclusive OR.
|
||||
st9_cp, // Compare.
|
||||
st9_cpw, // Compare Word.
|
||||
st9_tm, // Test under Mask.
|
||||
st9_tmw, // Test Word under Mask.
|
||||
st9_tcm, // Test Complement under Mask.
|
||||
st9_tcmw, // Test Word Complement under Mask.
|
||||
st9_inc, // Increment.
|
||||
st9_incw, // Increment Word.
|
||||
st9_dec, // Decrement.
|
||||
st9_decw, // Decrement Word.
|
||||
st9_sla, // Shift Left Arithmetic.
|
||||
st9_slaw, // Shift Word Left Arithmetic.
|
||||
st9_sra, // Shift Right Arithmetic.
|
||||
st9_sraw, // Shift Word Right Arithmetic.
|
||||
st9_rrc, // Rotate Right through Carry.
|
||||
st9_rrcw, // Rotate Word Right through Carry.
|
||||
st9_rlc, // Rotate Left through Carry.
|
||||
st9_rlcw, // Rotate Word Left through Carry.
|
||||
st9_ror, // Rotate Right.
|
||||
st9_rol, // Rotate Left.
|
||||
st9_clr, // Clear Register.
|
||||
st9_cpl, // Complement Register.
|
||||
st9_swap, // Swap Nibbles.
|
||||
st9_da, // Decimal ajust.
|
||||
st9_push, // Push on System Stack.
|
||||
st9_pushw, // Push Word on System Stack.
|
||||
st9_pea, // Push Effective Address on System Stack.
|
||||
st9_pop, // Pop from System Stack.
|
||||
st9_popw, // Pop Word from System Stack.
|
||||
st9_pushu, // Push on User Stack.
|
||||
st9_pushuw, // Push Word on User Stack.
|
||||
st9_peau, // Push Effective Address on User Stack.
|
||||
st9_popu, // Pop from User Stack.
|
||||
st9_popuw, // Pop Word from User Stack.
|
||||
st9_link, // Move System Stack Pointer upward; support for high-level language.
|
||||
st9_unlink, // Move System Stack Pointer backward; support for high-level language.
|
||||
st9_linku, // Move User Stack Pointer upward; support for high-level language.
|
||||
st9_unlinku, // Move User Stack Pointer backward; support for high-level language.
|
||||
st9_mul, // Multiply 8x8.
|
||||
st9_div, // Divide 8x8.
|
||||
st9_divws, // Divide Word Stepped 32/16.
|
||||
st9_bset, // Bit Set.
|
||||
st9_bres, // Bit Reset .
|
||||
st9_bcpl, // Bit Complement.
|
||||
st9_btset, // Bit Test and Set.
|
||||
st9_bld, // Bit Load.
|
||||
st9_band, // Bit AND.
|
||||
st9_bor, // Bit OR.
|
||||
st9_bxor, // Bit XOR.
|
||||
st9_ret, // Return from Subroutine.
|
||||
st9_rets, // Inter-segment Return to Subroutine.
|
||||
st9_iret, // Return from Interrupt.
|
||||
st9_jrcc, // Jump Relative if Condition ``cc'' is Met.
|
||||
st9_jpcc, // Jump if Condition ``cc'' is Met.
|
||||
st9_jp, // Unconditional Jump.
|
||||
st9_jps, // Unconditional Inter-segment Jump.
|
||||
st9_call, // Unconditional Call.
|
||||
st9_calls, // Inter-segment Call to Subroutine.
|
||||
st9_btjf, // Bit Test and Jump if False.
|
||||
st9_btjt, // Bit Test and Jump if True.
|
||||
st9_djnz, // Decrement a Working Register and Jump if Non Zero.
|
||||
st9_dwjnz, // Decrement a Register Pair and Jump if Non Zero.
|
||||
st9_cpjfi, // Compare and Jump on False. Otherwise Post Increment.
|
||||
st9_cpjti, // Compare and Jump on True. Otherwise Post Increment.
|
||||
st9_xch, // Exchange Registers.
|
||||
st9_srp, // Set Register Pointer Long (16 working registers).
|
||||
st9_srp0, // Set Register Pointer 0 (8 LSB working registers).
|
||||
st9_srp1, // Set Register Pointer 1 (8 MSB working registers).
|
||||
st9_spp, // Set Page Pointer.
|
||||
st9_ext, // Sign Extend.
|
||||
st9_ei, // Enable Interrupts.
|
||||
st9_di, // Disable Interrupts.
|
||||
st9_scf, // Set Carry Flag.
|
||||
st9_rcf, // Reset Carry Flag.
|
||||
st9_ccf, // Complement Carry Flag.
|
||||
st9_spm, // Select Extended Memory addressing scheme through CSR Register.
|
||||
st9_sdm, // Select Extended Memory addressing scheme through DPR Registers.
|
||||
st9_nop, // No Operation.
|
||||
st9_wfi, // Stop Program Execution and Wait for the next Enable Interrupt.
|
||||
st9_halt, // Stop Program Execution until System Reset.
|
||||
st9_etrap, // Undocumented instruction.
|
||||
st9_eret, // Undocumented instruction.
|
||||
st9_ald, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED.
|
||||
st9_aldw, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED.
|
||||
st9_last
|
||||
};
|
||||
|
||||
#endif /* __INS_HPP */
|
||||
|
||||
57
idasdk76/module/st9/makefile
Normal file
57
idasdk76/module/st9/makefile
Normal file
@@ -0,0 +1,57 @@
|
||||
PROC=st9
|
||||
CONFIGS=st9.cfg
|
||||
|
||||
|
||||
include ../module.mak
|
||||
|
||||
# MAKEDEP dependency list ------------------
|
||||
$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ana.cpp ins.hpp st9.hpp
|
||||
$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp st9.hpp
|
||||
$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ins.cpp ins.hpp st9.hpp
|
||||
$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp st9.hpp
|
||||
$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
|
||||
$(I)config.hpp $(I)diskio.hpp \
|
||||
$(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \
|
||||
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
|
||||
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \
|
||||
$(I)nalt.hpp $(I)name.hpp \
|
||||
$(I)netnode.hpp $(I)offset.hpp $(I)pro.h \
|
||||
$(I)problems.hpp $(I)range.hpp $(I)segment.hpp \
|
||||
$(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \
|
||||
../idaidp.hpp ../iohandler.hpp ins.hpp reg.cpp st9.hpp
|
||||
585
idasdk76/module/st9/out.cpp
Normal file
585
idasdk76/module/st9/out.cpp
Normal file
@@ -0,0 +1,585 @@
|
||||
|
||||
#include "st9.hpp"
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_st9_t : public outctx_t
|
||||
{
|
||||
out_st9_t(void) = delete; // not used
|
||||
st9_t &pm() { return *static_cast<st9_t *>(procmod); }
|
||||
|
||||
public:
|
||||
const char *get_general_register_description(const ushort reg) const;
|
||||
void out_reg(ushort reg);
|
||||
void out_reg(const op_t &op);
|
||||
void out_imm(const op_t &op, bool no_shift = false);
|
||||
void out_addr(const op_t &op, bool find_label = true);
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
void out_proc_mnem(void);
|
||||
};
|
||||
CASSERT(sizeof(out_st9_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS(out_st9_t)
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Get description for a given general register.
|
||||
// Description may change according to the current number of the registers page.
|
||||
const char *out_st9_t::get_general_register_description(const ushort reg) const
|
||||
{
|
||||
if ( reg <= rRR239 && reg >= rRR224 )
|
||||
{
|
||||
// pairs of system registers (group E)
|
||||
switch ( reg )
|
||||
{
|
||||
case rRR236: return "User Stack Pointer";
|
||||
case rRR238: return "System Stack Pointer";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
if ( reg <= rR239 && reg >= rR224 )
|
||||
{
|
||||
// system registers (group E)
|
||||
switch ( reg )
|
||||
{
|
||||
case rR224: return "Port 0 Data Register (EMR2.5 == 0) or Data Page Register 0 (EMR2.5 == 1)";
|
||||
case rR225: return "Port 1 Data Register (EMR2.5 == 0) or Data Page Register 1 (EMR2.5 == 1)";
|
||||
case rR226: return "Port 2 Data Register (EMR2.5 == 0) or Data Page Register 2 (EMR2.5 == 1)";
|
||||
case rR227: return "Port 3 Data Register (EMR2.5 == 0) or Data Page Register 3 (EMR2.5 == 1)";
|
||||
case rR228: return "Port 4 Data Register";
|
||||
case rR229: return "Port 5 Data Register";
|
||||
case rR230: return "Central Interrupt Control Register";
|
||||
case rR231: return "Flag Register";
|
||||
case rR232: return "Pointer 0 Register";
|
||||
case rR233: return "Pointer 1 Register";
|
||||
case rR234: return "Page Pointer Register";
|
||||
case rR235: return "Mode Register";
|
||||
case rR236: return "User Stack Pointer High Register";
|
||||
case rR237: return "User Stack Pointer Low Register";
|
||||
case rR238: return "System Stack Pointer High Register";
|
||||
case rR239: return "System Stack Pointer Low Register";
|
||||
}
|
||||
}
|
||||
|
||||
// only handle paged register below (group F)
|
||||
if ( reg < rR240 || reg > rR255 )
|
||||
return NULL;
|
||||
|
||||
switch ( get_sreg(insn.ea, rRP) )
|
||||
{
|
||||
// page: N/A
|
||||
case BADSEL:
|
||||
break;
|
||||
|
||||
// page: 0
|
||||
case 0:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR241: return "Minor Register";
|
||||
case rR242: return "External Interrupt Trigger Register";
|
||||
case rR243: return "External Interrupt Pending Register";
|
||||
case rR244: return "External Interrupt Mask-bit Register";
|
||||
case rR245: return "External Interrupt Priority Level Register";
|
||||
case rR246: return "External Interrupt Vector Register";
|
||||
case rR247: return "Nested Interrupt Control";
|
||||
case rR248: return "Watchdog Timer High Register";
|
||||
case rR249: return "Watchdog Timer Low Register";
|
||||
case rR250: return "Watchdog Timer Prescaler Register";
|
||||
case rR251: return "Watchdog Timer Control Register";
|
||||
case rR252: return "Wait Control Register";
|
||||
case rR253: return "SPI Data Register";
|
||||
case rR254: return "SPI Control Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 2
|
||||
case 2:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Port 0 Configuration Register 0";
|
||||
case rR241: return "Port 0 Configuration Register 1";
|
||||
case rR242: return "Port 0 Configuration Register 2";
|
||||
case rR244: return "Port 1 Configuration Register 0";
|
||||
case rR245: return "Port 1 Configuration Register 1";
|
||||
case rR246: return "Port 1 Configuration Register 2";
|
||||
case rR248: return "Port 2 Configuration Register 0";
|
||||
case rR249: return "Port 2 Configuration Register 1";
|
||||
case rR250: return "Port 2 Configuration Register 2";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 3
|
||||
case 3:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Port 4 Configuration Register 0";
|
||||
case rR241: return "Port 4 Configuration Register 1";
|
||||
case rR242: return "Port 4 Configuration Register 2";
|
||||
case rR244: return "Port 5 Configuration Register 0";
|
||||
case rR245: return "Port 5 Configuration Register 1";
|
||||
case rR246: return "Port 5 Configuration Register 2";
|
||||
case rR248: return "Port 6 Configuration Register 0";
|
||||
case rR249: return "Port 6 Configuration Register 1";
|
||||
case rR250: return "Port 6 Configuration Register 2";
|
||||
case rR251: return "Port 6 Data Register";
|
||||
case rR252: return "Port 7 Configuration Register 0";
|
||||
case rR253: return "Port 7 Configuration Register 1";
|
||||
case rR254: return "Port 7 Configuration Register 2";
|
||||
case rR255: return "Port 7 Data Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 8, 10 or 12
|
||||
case 8:
|
||||
case 10:
|
||||
case 12:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Capture Load Register 0 High";
|
||||
case rR241: return "Capture Load Register 0 Low";
|
||||
case rR242: return "Capture Load Register 1 High";
|
||||
case rR243: return "Capture Load Register 1 Low";
|
||||
case rR244: return "Compare 0 Register High";
|
||||
case rR245: return "Compare 0 Register Low";
|
||||
case rR246: return "Compare 1 Register High";
|
||||
case rR247: return "Compare 1 Register Low";
|
||||
case rR248: return "Timer Control Register";
|
||||
case rR249: return "Timer Mode Register";
|
||||
case rR250: return "External Input Control Register";
|
||||
case rR251: return "Prescaler Register";
|
||||
case rR252: return "Output A Control Register";
|
||||
case rR253: return "Output B Control Register";
|
||||
case rR254: return "Flags Register";
|
||||
case rR255: return "Interrupt/DMA Mask Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 9
|
||||
case 9:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240:
|
||||
case rR244: return "DMA Counter Pointer Register";
|
||||
case rR241:
|
||||
case rR245: return "DMA Address Pointer Register";
|
||||
case rR242:
|
||||
case rR246: return "Interrupt Vector Register";
|
||||
case rR243:
|
||||
case rR247: return "Interrupt/DMA Control Register";
|
||||
case rR248: return "I/O Connection Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 11
|
||||
case 11:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Counter High Byte Register";
|
||||
case rR241: return "Counter Low Byte Register";
|
||||
case rR242: return "Standard Timer Prescaler Register";
|
||||
case rR243: return "Standard Timer Control Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 13
|
||||
case 13:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR244: return "DMA Counter Pointer Register";
|
||||
case rR245: return "DMA Address Pointer Register";
|
||||
case rR246: return "Interrupt Vector Register";
|
||||
case rR247: return "Interrupt/DMA Control Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 21
|
||||
case 21:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Data Page Register 0";
|
||||
case rR241: return "Data Page Register 1";
|
||||
case rR242: return "Data Page Register 2";
|
||||
case rR243: return "Data Page Register 3";
|
||||
case rR244: return "Code Segment Register";
|
||||
case rR248: return "Interrupt Segment Register";
|
||||
case rR249: return "DMA Segment Register";
|
||||
case rR245: return "External Memory Register 1";
|
||||
case rR246: return "External Memory Register 2";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 24 or 25
|
||||
case 24:
|
||||
case 25:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Receiver DMA Transaction Counter Pointer";
|
||||
case rR241: return "Receiver DMA Source Address Pointer";
|
||||
case rR242: return "Transmitter DMA Transaction Counter Pointer";
|
||||
case rR243: return "Transmitter DMA Source Address Pointer";
|
||||
case rR244: return "Interrupt Vector Register";
|
||||
case rR245: return "Address/Data Compare Register";
|
||||
case rR246: return "Interrupt Mask Register";
|
||||
case rR247: return "Interrupt Status Register";
|
||||
case rR248: return "Receive/Transmitter Buffer Register";
|
||||
case rR249: return "Interrupt/DMA Priority Register";
|
||||
case rR250: return "Character Configuration Register";
|
||||
case rR251: return "Clock Configuration Register";
|
||||
case rR252: return "Baud Rate Generator High Register";
|
||||
case rR253: return "Baud Rate Generator Low Register";
|
||||
case rR254: return "Synchronous Input Control";
|
||||
case rR255: return "Synchronous Output Control";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 43
|
||||
case 43:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR248: return "Port 8 Configuration Register 0";
|
||||
case rR249: return "Port 8 Configuration Register 1";
|
||||
case rR250: return "Port 8 Configuration Register 2";
|
||||
case rR251: return "Port 8 Data Register";
|
||||
case rR252: return "Port 9 Configuration Register 0";
|
||||
case rR253: return "Port 9 Configuration Register 1";
|
||||
case rR254: return "Port 9 Configuration Register 2";
|
||||
case rR255: return "Port 9 Data Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 55
|
||||
case 55:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Clock Control Register";
|
||||
case rR242: return "Clock Flag Register";
|
||||
case rR246: return "PLL Configuration Register";
|
||||
}
|
||||
break;
|
||||
|
||||
// page: 63
|
||||
case 63:
|
||||
switch ( reg )
|
||||
{
|
||||
case rR240: return "Channel 0 Data Register";
|
||||
case rR241: return "Channel 1 Data Register";
|
||||
case rR242: return "Channel 2 Data Register";
|
||||
case rR243: return "Channel 3 Data Register";
|
||||
case rR244: return "Channel 4 Data Register";
|
||||
case rR245: return "Channel 5 Data Register";
|
||||
case rR246: return "Channel 6 Data Register";
|
||||
case rR247: return "Channel 7 Data Register";
|
||||
case rR248: return "Channel 6 Lower Threshold Register";
|
||||
case rR249: return "Channel 6 Lower Threshold Register";
|
||||
case rR250: return "Channel 7 Upper Threshold Register";
|
||||
case rR251: return "Channel 7 Upper Threshold Register";
|
||||
case rR252: return "Compare Result Register";
|
||||
case rR253: return "Control Logic Register";
|
||||
case rR254: return "Interrupt Control Register";
|
||||
case rR255: return "Interrupt Vector Register";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output a register
|
||||
void out_st9_t::out_reg(ushort reg)
|
||||
{
|
||||
out_register(ph.reg_names[reg]);
|
||||
if ( !has_cmt(F) )
|
||||
{
|
||||
const char *cmt = get_general_register_description(reg);
|
||||
if ( cmt != NULL )
|
||||
pm().gr_cmt = cmt;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output an operand as a register
|
||||
void out_st9_t::out_reg(const op_t &op)
|
||||
{
|
||||
out_reg(op.reg);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output an operand as an immediate value
|
||||
void out_st9_t::out_imm(const op_t &op, bool no_shift)
|
||||
{
|
||||
if ( !is_imm_no_shift(op) && !no_shift )
|
||||
out_symbol('#');
|
||||
out_value(op, OOFW_IMM);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output an operand as an address
|
||||
void out_st9_t::out_addr(const op_t &op, bool find_label)
|
||||
{
|
||||
ea_t full_addr = get_dest_addr(insn, op);
|
||||
if ( !find_label || !out_name_expr(op, full_addr, BADADDR) )
|
||||
out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_16);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Generate disassembly header
|
||||
void idaapi st9_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Generate disassembly footer
|
||||
void st9_t::st9_footer(outctx_t &ctx) const
|
||||
{
|
||||
if ( ash.end != NULL )
|
||||
{
|
||||
ctx.gen_empty_line();
|
||||
ctx.out_line(ash.end, COLOR_ASMDIR);
|
||||
qstring name;
|
||||
if ( get_colored_name(&name, inf_get_start_ea()) > 0 )
|
||||
{
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(name.begin());
|
||||
}
|
||||
ctx.flush_outbuf(DEFAULT_INDENT);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("end of file");
|
||||
}
|
||||
}
|
||||
|
||||
#define BEG_TAG(x) if ( is_ind(x)) out_symbol('(' )
|
||||
#define END_TAG(x) if ( is_ind(x)) out_symbol(')' )
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output an operand
|
||||
bool out_st9_t::out_operand(const op_t &op)
|
||||
{
|
||||
switch ( op.type )
|
||||
{
|
||||
// Data / Code memory address
|
||||
case o_near:
|
||||
case o_far:
|
||||
case o_mem:
|
||||
BEG_TAG(op);
|
||||
out_addr(op);
|
||||
END_TAG(op);
|
||||
break;
|
||||
|
||||
// Immediate value
|
||||
case o_imm:
|
||||
BEG_TAG(op);
|
||||
{
|
||||
const ioport_t *port = pm().find_sym(op.value);
|
||||
// this immediate is represented in the .cfg file
|
||||
if ( port != NULL ) // otherwise, simply print the value
|
||||
out_line(port->name.c_str(), COLOR_IMPNAME);
|
||||
else // otherwise, simply print the value
|
||||
out_imm(op);
|
||||
}
|
||||
END_TAG(op);
|
||||
break;
|
||||
|
||||
// Displacement
|
||||
case o_displ:
|
||||
out_addr(op, false);
|
||||
out_symbol('(');
|
||||
out_reg(op);
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
// Register
|
||||
case o_reg:
|
||||
BEG_TAG(op);
|
||||
out_reg(op);
|
||||
END_TAG(op);
|
||||
if ( is_reg_with_bit(op) )
|
||||
{
|
||||
out_symbol('.');
|
||||
if ( is_bit_compl(op) )
|
||||
out_symbol('!');
|
||||
out_imm(op, true);
|
||||
}
|
||||
break;
|
||||
|
||||
// Phrase
|
||||
case o_phrase:
|
||||
switch ( op.specflag2 )
|
||||
{
|
||||
case fPI: // post increment
|
||||
out_symbol('(');
|
||||
out_reg(op);
|
||||
out_symbol(')');
|
||||
out_symbol('+');
|
||||
break;
|
||||
|
||||
case fPD: // pre decrement
|
||||
out_symbol('-');
|
||||
out_symbol('(');
|
||||
out_reg(op);
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
case fDISP: // displacement
|
||||
out_reg(op);
|
||||
out_symbol('(');
|
||||
{
|
||||
ushort reg = op.specflag2 << 8;
|
||||
reg |= op.specflag3;
|
||||
out_reg(reg);
|
||||
}
|
||||
out_symbol(')');
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10077);
|
||||
}
|
||||
break;
|
||||
|
||||
// No operand
|
||||
case o_void:
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10078);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void out_st9_t::out_proc_mnem(void)
|
||||
{
|
||||
char postfix[5];
|
||||
postfix[0] = '\0';
|
||||
|
||||
if ( is_jmp_cc(insn.itype) )
|
||||
qstrncpy(postfix, ConditionCodes[insn.auxpref], sizeof(postfix));
|
||||
|
||||
out_mnem(8, postfix);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Output an instruction
|
||||
void out_st9_t::out_insn(void)
|
||||
{
|
||||
out_mnemonic();
|
||||
|
||||
//
|
||||
// print insn operands
|
||||
//
|
||||
|
||||
out_one_operand(0); // output the first operand
|
||||
|
||||
if ( insn.Op2.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(1);
|
||||
}
|
||||
|
||||
if ( insn.Op3.type != o_void )
|
||||
{
|
||||
out_symbol(',');
|
||||
out_char(' ');
|
||||
out_one_operand(2);
|
||||
}
|
||||
|
||||
// output a character representation of the immediate values
|
||||
// embedded in the instruction as comments
|
||||
out_immchar_cmts();
|
||||
|
||||
if ( pm().gr_cmt != NULL )
|
||||
{
|
||||
out_char(' ');
|
||||
out_line(ash.cmnt, COLOR_AUTOCMT);
|
||||
out_char(' ');
|
||||
out_line(pm().gr_cmt, COLOR_AUTOCMT);
|
||||
if ( ash.cmnt2 != NULL )
|
||||
{
|
||||
out_char(' ');
|
||||
out_line(ash.cmnt2, COLOR_AUTOCMT);
|
||||
}
|
||||
pm().gr_cmt = NULL;
|
||||
}
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Generate a segment header
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Sarea) could be made const
|
||||
void st9_t::st9_segstart(outctx_t &ctx, segment_t *Sarea) const
|
||||
{
|
||||
qstring sname;
|
||||
get_visible_segm_name(&sname, Sarea);
|
||||
|
||||
const char *segname = sname.c_str();
|
||||
if ( *segname == '_' )
|
||||
segname++;
|
||||
|
||||
if ( ash.uflag & UAS_ASW )
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), segname);
|
||||
else
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR(".section .%s", SCOLOR_ASMDIR), segname);
|
||||
|
||||
ea_t orgbase = ctx.insn_ea - get_segm_para(Sarea);
|
||||
|
||||
if ( orgbase != 0 )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), orgbase);
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void st9_t::st9_assumes(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *sega = getseg(ea);
|
||||
|
||||
if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || sega == NULL )
|
||||
return;
|
||||
bool seg_started = (ea == sega->start_ea);
|
||||
|
||||
for ( int i = rRW; i <= rDPR3; ++i )
|
||||
{
|
||||
if ( i == rCSR )
|
||||
continue;
|
||||
|
||||
sreg_range_t sra;
|
||||
if ( !get_sreg_range(&sra, ea, i) || sra.val == BADSEL )
|
||||
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 )
|
||||
{
|
||||
sel_t r = sra.val;
|
||||
if ( i == rRW )
|
||||
{
|
||||
int rwhi = (r >> 8) & 0xFF;
|
||||
int rwlo = r & 0xFF;
|
||||
ctx.gen_cmt_line("Register window: (%d, %d)", rwhi, rwlo);
|
||||
}
|
||||
else if ( i == rRP )
|
||||
{
|
||||
ctx.gen_cmt_line("Register page: %d", (int)r);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), r);
|
||||
ctx.gen_cmt_line("assume %s: %s (page 0x%a)",
|
||||
ph.reg_names[i],
|
||||
buf,
|
||||
(r << 14));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1237
idasdk76/module/st9/reg.cpp
Normal file
1237
idasdk76/module/st9/reg.cpp
Normal file
File diff suppressed because it is too large
Load Diff
7
idasdk76/module/st9/st9.cfg
Normal file
7
idasdk76/module/st9/st9.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
.default ST9
|
||||
|
||||
.ST9
|
||||
|
||||
DUMMY 0x12345678 Dummy port
|
||||
|
||||
700
idasdk76/module/st9/st9.hpp
Normal file
700
idasdk76/module/st9/st9.hpp
Normal file
@@ -0,0 +1,700 @@
|
||||
|
||||
#ifndef __ST9_HPP
|
||||
#define __ST9_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include "ins.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <struct.hpp>
|
||||
#include "../iohandler.hpp"
|
||||
|
||||
#define PROCMOD_NAME st9
|
||||
#define PROCMOD_NODE_NAME "$ st9"
|
||||
|
||||
// Operand flags
|
||||
#define OP_IS_IND 0x00000001 // Operand is indirect, and should be
|
||||
// printed between ().
|
||||
#define OP_IMM_NO_SHIFT 0x00000002 // Operand is immediate, and should not
|
||||
// be prefixed by the '#' character.
|
||||
#define OP_REG_WITH_BIT 0x00000004 // Operand is register, and a bit number can be
|
||||
// found in the "value" field.
|
||||
#define OP_BIT_COMPL 0x00000008 // Bit number is a complement, and should be
|
||||
// prefixed by the '!' character.
|
||||
#define OP_DISPL_FUNC_ARG 0x00000010 // Operand is a displacement, and should be considered
|
||||
// as a function argument variable.
|
||||
// Flags for ash.uFlag
|
||||
#define UAS_ASW 0x00000001 // current assembler is ASW.
|
||||
|
||||
inline bool is_ind(const op_t &op)
|
||||
{
|
||||
return (op.specflag1 & OP_IS_IND) != 0;
|
||||
}
|
||||
|
||||
inline bool is_imm_no_shift(const op_t &op)
|
||||
{
|
||||
return op.type == o_imm && (op.specflag1 & OP_IMM_NO_SHIFT) != 0;
|
||||
}
|
||||
|
||||
inline bool is_reg_with_bit(const op_t &op)
|
||||
{
|
||||
return op.type == o_reg && (op.specflag1 & OP_REG_WITH_BIT) != 0;
|
||||
}
|
||||
|
||||
inline bool is_bit_compl(const op_t &op)
|
||||
{
|
||||
return (op.specflag1 & OP_BIT_COMPL) != 0;
|
||||
}
|
||||
|
||||
// ST9+ registers :
|
||||
enum st9_registers
|
||||
{
|
||||
rR0,
|
||||
rR1,
|
||||
rR2,
|
||||
rR3,
|
||||
rR4,
|
||||
rR5,
|
||||
rR6,
|
||||
rR7,
|
||||
rR8,
|
||||
rR9,
|
||||
rR10,
|
||||
rR11,
|
||||
rR12,
|
||||
rR13,
|
||||
rR14,
|
||||
rR15,
|
||||
rR16,
|
||||
rR17,
|
||||
rR18,
|
||||
rR19,
|
||||
rR20,
|
||||
rR21,
|
||||
rR22,
|
||||
rR23,
|
||||
rR24,
|
||||
rR25,
|
||||
rR26,
|
||||
rR27,
|
||||
rR28,
|
||||
rR29,
|
||||
rR30,
|
||||
rR31,
|
||||
rR32,
|
||||
rR33,
|
||||
rR34,
|
||||
rR35,
|
||||
rR36,
|
||||
rR37,
|
||||
rR38,
|
||||
rR39,
|
||||
rR40,
|
||||
rR41,
|
||||
rR42,
|
||||
rR43,
|
||||
rR44,
|
||||
rR45,
|
||||
rR46,
|
||||
rR47,
|
||||
rR48,
|
||||
rR49,
|
||||
rR50,
|
||||
rR51,
|
||||
rR52,
|
||||
rR53,
|
||||
rR54,
|
||||
rR55,
|
||||
rR56,
|
||||
rR57,
|
||||
rR58,
|
||||
rR59,
|
||||
rR60,
|
||||
rR61,
|
||||
rR62,
|
||||
rR63,
|
||||
rR64,
|
||||
rR65,
|
||||
rR66,
|
||||
rR67,
|
||||
rR68,
|
||||
rR69,
|
||||
rR70,
|
||||
rR71,
|
||||
rR72,
|
||||
rR73,
|
||||
rR74,
|
||||
rR75,
|
||||
rR76,
|
||||
rR77,
|
||||
rR78,
|
||||
rR79,
|
||||
rR80,
|
||||
rR81,
|
||||
rR82,
|
||||
rR83,
|
||||
rR84,
|
||||
rR85,
|
||||
rR86,
|
||||
rR87,
|
||||
rR88,
|
||||
rR89,
|
||||
rR90,
|
||||
rR91,
|
||||
rR92,
|
||||
rR93,
|
||||
rR94,
|
||||
rR95,
|
||||
rR96,
|
||||
rR97,
|
||||
rR98,
|
||||
rR99,
|
||||
rR100,
|
||||
rR101,
|
||||
rR102,
|
||||
rR103,
|
||||
rR104,
|
||||
rR105,
|
||||
rR106,
|
||||
rR107,
|
||||
rR108,
|
||||
rR109,
|
||||
rR110,
|
||||
rR111,
|
||||
rR112,
|
||||
rR113,
|
||||
rR114,
|
||||
rR115,
|
||||
rR116,
|
||||
rR117,
|
||||
rR118,
|
||||
rR119,
|
||||
rR120,
|
||||
rR121,
|
||||
rR122,
|
||||
rR123,
|
||||
rR124,
|
||||
rR125,
|
||||
rR126,
|
||||
rR127,
|
||||
rR128,
|
||||
rR129,
|
||||
rR130,
|
||||
rR131,
|
||||
rR132,
|
||||
rR133,
|
||||
rR134,
|
||||
rR135,
|
||||
rR136,
|
||||
rR137,
|
||||
rR138,
|
||||
rR139,
|
||||
rR140,
|
||||
rR141,
|
||||
rR142,
|
||||
rR143,
|
||||
rR144,
|
||||
rR145,
|
||||
rR146,
|
||||
rR147,
|
||||
rR148,
|
||||
rR149,
|
||||
rR150,
|
||||
rR151,
|
||||
rR152,
|
||||
rR153,
|
||||
rR154,
|
||||
rR155,
|
||||
rR156,
|
||||
rR157,
|
||||
rR158,
|
||||
rR159,
|
||||
rR160,
|
||||
rR161,
|
||||
rR162,
|
||||
rR163,
|
||||
rR164,
|
||||
rR165,
|
||||
rR166,
|
||||
rR167,
|
||||
rR168,
|
||||
rR169,
|
||||
rR170,
|
||||
rR171,
|
||||
rR172,
|
||||
rR173,
|
||||
rR174,
|
||||
rR175,
|
||||
rR176,
|
||||
rR177,
|
||||
rR178,
|
||||
rR179,
|
||||
rR180,
|
||||
rR181,
|
||||
rR182,
|
||||
rR183,
|
||||
rR184,
|
||||
rR185,
|
||||
rR186,
|
||||
rR187,
|
||||
rR188,
|
||||
rR189,
|
||||
rR190,
|
||||
rR191,
|
||||
rR192,
|
||||
rR193,
|
||||
rR194,
|
||||
rR195,
|
||||
rR196,
|
||||
rR197,
|
||||
rR198,
|
||||
rR199,
|
||||
rR200,
|
||||
rR201,
|
||||
rR202,
|
||||
rR203,
|
||||
rR204,
|
||||
rR205,
|
||||
rR206,
|
||||
rR207,
|
||||
rR208,
|
||||
rR209,
|
||||
rR210,
|
||||
rR211,
|
||||
rR212,
|
||||
rR213,
|
||||
rR214,
|
||||
rR215,
|
||||
rR216,
|
||||
rR217,
|
||||
rR218,
|
||||
rR219,
|
||||
rR220,
|
||||
rR221,
|
||||
rR222,
|
||||
rR223,
|
||||
rR224,
|
||||
rR225,
|
||||
rR226,
|
||||
rR227,
|
||||
rR228,
|
||||
rR229,
|
||||
rR230,
|
||||
rR231,
|
||||
rR232,
|
||||
rR233,
|
||||
rR234,
|
||||
rR235,
|
||||
rR236,
|
||||
rR237,
|
||||
rR238,
|
||||
rR239,
|
||||
rR240,
|
||||
rR241,
|
||||
rR242,
|
||||
rR243,
|
||||
rR244,
|
||||
rR245,
|
||||
rR246,
|
||||
rR247,
|
||||
rR248,
|
||||
rR249,
|
||||
rR250,
|
||||
rR251,
|
||||
rR252,
|
||||
rR253,
|
||||
rR254,
|
||||
rR255,
|
||||
rRR0,
|
||||
rRR1,
|
||||
rRR2,
|
||||
rRR3,
|
||||
rRR4,
|
||||
rRR5,
|
||||
rRR6,
|
||||
rRR7,
|
||||
rRR8,
|
||||
rRR9,
|
||||
rRR10,
|
||||
rRR11,
|
||||
rRR12,
|
||||
rRR13,
|
||||
rRR14,
|
||||
rRR15,
|
||||
rRR16,
|
||||
rRR17,
|
||||
rRR18,
|
||||
rRR19,
|
||||
rRR20,
|
||||
rRR21,
|
||||
rRR22,
|
||||
rRR23,
|
||||
rRR24,
|
||||
rRR25,
|
||||
rRR26,
|
||||
rRR27,
|
||||
rRR28,
|
||||
rRR29,
|
||||
rRR30,
|
||||
rRR31,
|
||||
rRR32,
|
||||
rRR33,
|
||||
rRR34,
|
||||
rRR35,
|
||||
rRR36,
|
||||
rRR37,
|
||||
rRR38,
|
||||
rRR39,
|
||||
rRR40,
|
||||
rRR41,
|
||||
rRR42,
|
||||
rRR43,
|
||||
rRR44,
|
||||
rRR45,
|
||||
rRR46,
|
||||
rRR47,
|
||||
rRR48,
|
||||
rRR49,
|
||||
rRR50,
|
||||
rRR51,
|
||||
rRR52,
|
||||
rRR53,
|
||||
rRR54,
|
||||
rRR55,
|
||||
rRR56,
|
||||
rRR57,
|
||||
rRR58,
|
||||
rRR59,
|
||||
rRR60,
|
||||
rRR61,
|
||||
rRR62,
|
||||
rRR63,
|
||||
rRR64,
|
||||
rRR65,
|
||||
rRR66,
|
||||
rRR67,
|
||||
rRR68,
|
||||
rRR69,
|
||||
rRR70,
|
||||
rRR71,
|
||||
rRR72,
|
||||
rRR73,
|
||||
rRR74,
|
||||
rRR75,
|
||||
rRR76,
|
||||
rRR77,
|
||||
rRR78,
|
||||
rRR79,
|
||||
rRR80,
|
||||
rRR81,
|
||||
rRR82,
|
||||
rRR83,
|
||||
rRR84,
|
||||
rRR85,
|
||||
rRR86,
|
||||
rRR87,
|
||||
rRR88,
|
||||
rRR89,
|
||||
rRR90,
|
||||
rRR91,
|
||||
rRR92,
|
||||
rRR93,
|
||||
rRR94,
|
||||
rRR95,
|
||||
rRR96,
|
||||
rRR97,
|
||||
rRR98,
|
||||
rRR99,
|
||||
rRR100,
|
||||
rRR101,
|
||||
rRR102,
|
||||
rRR103,
|
||||
rRR104,
|
||||
rRR105,
|
||||
rRR106,
|
||||
rRR107,
|
||||
rRR108,
|
||||
rRR109,
|
||||
rRR110,
|
||||
rRR111,
|
||||
rRR112,
|
||||
rRR113,
|
||||
rRR114,
|
||||
rRR115,
|
||||
rRR116,
|
||||
rRR117,
|
||||
rRR118,
|
||||
rRR119,
|
||||
rRR120,
|
||||
rRR121,
|
||||
rRR122,
|
||||
rRR123,
|
||||
rRR124,
|
||||
rRR125,
|
||||
rRR126,
|
||||
rRR127,
|
||||
rRR128,
|
||||
rRR129,
|
||||
rRR130,
|
||||
rRR131,
|
||||
rRR132,
|
||||
rRR133,
|
||||
rRR134,
|
||||
rRR135,
|
||||
rRR136,
|
||||
rRR137,
|
||||
rRR138,
|
||||
rRR139,
|
||||
rRR140,
|
||||
rRR141,
|
||||
rRR142,
|
||||
rRR143,
|
||||
rRR144,
|
||||
rRR145,
|
||||
rRR146,
|
||||
rRR147,
|
||||
rRR148,
|
||||
rRR149,
|
||||
rRR150,
|
||||
rRR151,
|
||||
rRR152,
|
||||
rRR153,
|
||||
rRR154,
|
||||
rRR155,
|
||||
rRR156,
|
||||
rRR157,
|
||||
rRR158,
|
||||
rRR159,
|
||||
rRR160,
|
||||
rRR161,
|
||||
rRR162,
|
||||
rRR163,
|
||||
rRR164,
|
||||
rRR165,
|
||||
rRR166,
|
||||
rRR167,
|
||||
rRR168,
|
||||
rRR169,
|
||||
rRR170,
|
||||
rRR171,
|
||||
rRR172,
|
||||
rRR173,
|
||||
rRR174,
|
||||
rRR175,
|
||||
rRR176,
|
||||
rRR177,
|
||||
rRR178,
|
||||
rRR179,
|
||||
rRR180,
|
||||
rRR181,
|
||||
rRR182,
|
||||
rRR183,
|
||||
rRR184,
|
||||
rRR185,
|
||||
rRR186,
|
||||
rRR187,
|
||||
rRR188,
|
||||
rRR189,
|
||||
rRR190,
|
||||
rRR191,
|
||||
rRR192,
|
||||
rRR193,
|
||||
rRR194,
|
||||
rRR195,
|
||||
rRR196,
|
||||
rRR197,
|
||||
rRR198,
|
||||
rRR199,
|
||||
rRR200,
|
||||
rRR201,
|
||||
rRR202,
|
||||
rRR203,
|
||||
rRR204,
|
||||
rRR205,
|
||||
rRR206,
|
||||
rRR207,
|
||||
rRR208,
|
||||
rRR209,
|
||||
rRR210,
|
||||
rRR211,
|
||||
rRR212,
|
||||
rRR213,
|
||||
rRR214,
|
||||
rRR215,
|
||||
rRR216,
|
||||
rRR217,
|
||||
rRR218,
|
||||
rRR219,
|
||||
rRR220,
|
||||
rRR221,
|
||||
rRR222,
|
||||
rRR223,
|
||||
rRR224,
|
||||
rRR225,
|
||||
rRR226,
|
||||
rRR227,
|
||||
rRR228,
|
||||
rRR229,
|
||||
rRR230,
|
||||
rRR231,
|
||||
rRR232,
|
||||
rRR233,
|
||||
rRR234,
|
||||
rRR235,
|
||||
rRR236,
|
||||
rRR237,
|
||||
rRR238,
|
||||
rRR239,
|
||||
rRR240,
|
||||
rRR241,
|
||||
rRR242,
|
||||
rRR243,
|
||||
rRR244,
|
||||
rRR245,
|
||||
rRR246,
|
||||
rRR247,
|
||||
rRR248,
|
||||
rRR249,
|
||||
rRR250,
|
||||
rRR251,
|
||||
rRR252,
|
||||
rRR253,
|
||||
rRR254,
|
||||
rRR255,
|
||||
rr0,
|
||||
rr1,
|
||||
rr2,
|
||||
rr3,
|
||||
rr4,
|
||||
rr5,
|
||||
rr6,
|
||||
rr7,
|
||||
rr8,
|
||||
rr9,
|
||||
rr10,
|
||||
rr11,
|
||||
rr12,
|
||||
rr13,
|
||||
rr14,
|
||||
rr15,
|
||||
rrr0,
|
||||
rrr1,
|
||||
rrr2,
|
||||
rrr3,
|
||||
rrr4,
|
||||
rrr5,
|
||||
rrr6,
|
||||
rrr7,
|
||||
rrr8,
|
||||
rrr9,
|
||||
rrr10,
|
||||
rrr11,
|
||||
rrr12,
|
||||
rrr13,
|
||||
rrr14,
|
||||
rrr15,
|
||||
rRW, // register window number
|
||||
rRP, // register page
|
||||
rCSR, // code segment register
|
||||
rDPR0, rDPR1, rDPR2, rDPR3, // Data page registers
|
||||
st9_lastreg = rDPR3,
|
||||
};
|
||||
|
||||
// ST9 condition codes
|
||||
enum st9_cond_codes
|
||||
{
|
||||
cUNKNOWN,
|
||||
cF, // always false
|
||||
cT, // always true
|
||||
cC, // carry
|
||||
cNC, // not carry
|
||||
cZ, // zero
|
||||
cNZ, // not zero
|
||||
cPL, // plus
|
||||
cMI, // minus
|
||||
cOV, // overflow
|
||||
cNOV, // no overflow
|
||||
cEQ, // equal
|
||||
cNE, // not equal
|
||||
cGE, // greater than or equal
|
||||
cLT, // less than
|
||||
cGT, // greater than
|
||||
cLE, // less than or equal
|
||||
cUGE, // unsigned greated than or equal
|
||||
cUL, // unsigned less than
|
||||
cUGT, // unsigned greater than
|
||||
cULE // unsigned less than or equal
|
||||
};
|
||||
|
||||
enum st9_phrases ENUM_SIZE(uint8)
|
||||
{
|
||||
fPI, // post incrementation (rr)+
|
||||
fPD, // pre decrementation -(rr)
|
||||
fDISP // displacement rrx(rry)
|
||||
};
|
||||
|
||||
inline bool is_jmp_cc(int insn)
|
||||
{
|
||||
return insn == st9_jpcc || insn == st9_jrcc;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct st9_iohandler_t : public iohandler_t
|
||||
{
|
||||
struct st9_t ±
|
||||
st9_iohandler_t(st9_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {}
|
||||
};
|
||||
|
||||
struct st9_t : public procmod_t
|
||||
{
|
||||
// The netnode helper.
|
||||
// Using this node we will save current configuration information in the
|
||||
// IDA database.
|
||||
netnode helper;
|
||||
st9_iohandler_t ioh = st9_iohandler_t(*this, helper);
|
||||
|
||||
const char *RegNames[st9_lastreg + 1];
|
||||
qstrvec_t dynamic_rgnames; // dynamically generated names for rR1..rR255
|
||||
|
||||
const char *gr_cmt = nullptr;
|
||||
int ref_dpr_id; // id of refinfo handler
|
||||
#define IDP_GR_DEC 0x0001 // print general registers in decimal format
|
||||
#define IDP_GR_HEX 0x0002 // print general registers in hexadecimal format
|
||||
#define IDP_GR_BIN 0x0004 // print general registers in binary format
|
||||
uint32 idpflags = IDP_GR_DEC;
|
||||
ushort print_style = 3;
|
||||
bool flow;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
const ioport_t *find_sym(ea_t address);
|
||||
void patch_general_registers();
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int /*value_type*/,
|
||||
const void * /*value*/,
|
||||
bool idb_loaded);
|
||||
|
||||
int st9_emu(const insn_t &insn);
|
||||
void handle_operand(const insn_t &insn, const op_t &op, bool lwrite);
|
||||
bool create_func_frame(func_t *pfn) const;
|
||||
|
||||
void st9_assumes(outctx_t &ctx);
|
||||
void st9_footer(outctx_t &ctx) const;
|
||||
void st9_segstart(outctx_t &ctx, segment_t *Sarea) const;
|
||||
|
||||
void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
void load_from_idb();
|
||||
};
|
||||
extern int data_id;
|
||||
|
||||
// exporting our routines
|
||||
void idaapi st9_header(outctx_t &ctx);
|
||||
int idaapi st9_ana(insn_t *insn);
|
||||
ea_t get_dest_addr(const insn_t &insn, const op_t &x);
|
||||
bool st9_is_switch(switch_info_t *si, const insn_t &insn);
|
||||
|
||||
extern const char *const ConditionCodes[];
|
||||
|
||||
#endif /* __ST9_HPP */
|
||||
Reference in New Issue
Block a user