update to ida 7.6, add builds
This commit is contained in:
1061
idasdk76/module/pic/ana.cpp
Normal file
1061
idasdk76/module/pic/ana.cpp
Normal file
File diff suppressed because it is too large
Load Diff
509
idasdk76/module/pic/emu.cpp
Normal file
509
idasdk76/module/pic/emu.cpp
Normal file
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pic.hpp"
|
||||
#include <segregs.hpp>
|
||||
#include <frame.hpp>
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool pic_t::is_banked_reg(ea_t addr, int value) const
|
||||
{
|
||||
// on PIC12, bank size is 0x20
|
||||
// on PIC14, bank size is 0x80
|
||||
if ( ptype == PIC12 )
|
||||
return (addr & 0x1F ) == value;
|
||||
if ( ptype == PIC14 )
|
||||
return (addr & 0x7F ) == value;
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// is pcl register?
|
||||
bool pic_t::is_pcl(const insn_t &insn) const
|
||||
{
|
||||
if ( insn.Op1.type == o_mem )
|
||||
{
|
||||
switch ( ptype )
|
||||
{
|
||||
case PIC12:
|
||||
case PIC14: return is_banked_reg(insn.Op1.addr, 0x2);
|
||||
case PIC16: return insn.Op1.addr == PIC16_PCL;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// is bank (status or bsr (PIC18Cxx)) register?
|
||||
bool pic_t::is_bank(const insn_t &insn) const
|
||||
{
|
||||
if ( insn.Op1.type == o_mem )
|
||||
{
|
||||
switch ( ptype )
|
||||
{
|
||||
case PIC12:
|
||||
case PIC14: return is_banked_reg(insn.Op1.addr, 0x3);
|
||||
case PIC16: return insn.Op1.addr == PIC16_BANK;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// is pclath register?
|
||||
bool pic_t::is_pclath(const insn_t &insn) const
|
||||
{
|
||||
if ( insn.Op1.type == o_mem )
|
||||
{
|
||||
switch ( ptype )
|
||||
{
|
||||
case PIC12: return false;
|
||||
case PIC14: return is_banked_reg(insn.Op1.addr, 0xA);
|
||||
case PIC16: return insn.Op1.addr == PIC16_PCLATH;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void pic_t::process_immediate_number(const insn_t &insn, int n) const
|
||||
{
|
||||
set_immd(insn.ea);
|
||||
if ( is_defarg(get_flags(insn.ea), n) )
|
||||
return;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case PIC_iorlw:
|
||||
case PIC_andlw:
|
||||
case PIC_xorlw:
|
||||
op_num(insn.ea, n);
|
||||
break;
|
||||
case PIC_lfsr2:
|
||||
// FSRs are used to address the data memory
|
||||
if ( dataseg != BADADDR )
|
||||
op_offset(insn.ea, n, REF_OFF16, BADADDR, dataseg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pic_t::destroy_if_unnamed_array(ea_t ea) const
|
||||
{
|
||||
flags_t lF = get_flags(ea);
|
||||
if ( is_tail(lF) && segtype(ea) == SEG_IMEM )
|
||||
{
|
||||
ea_t head = prev_not_tail(ea);
|
||||
if ( !has_user_name(get_flags(head)) )
|
||||
{
|
||||
del_items(head, DELIT_SIMPLE);
|
||||
create_byte(head, ea-head);
|
||||
ea_t end = next_that(ea, inf_get_max_ea(), f_is_head);
|
||||
if ( end == BADADDR )
|
||||
end = getseg(ea)->end_ea;
|
||||
create_byte(ea+1, end-ea-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// propagate the bank/pclath register value to the destination
|
||||
void pic_t::propagate_sreg(const insn_t &insn, ea_t ea, int reg) const
|
||||
{
|
||||
if ( is_loaded(ea) )
|
||||
{
|
||||
sel_t v = get_sreg(insn.ea, reg);
|
||||
split_sreg_range(ea, reg, v, SR_auto);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pic_t::handle_operand(const insn_t &insn, const op_t &x, int, bool isload)
|
||||
{
|
||||
if ( insn.Op2.type == o_reg && insn.Op2.reg == F || insn.itype == PIC_swapf )
|
||||
isload = 0;
|
||||
switch ( x.type )
|
||||
{
|
||||
case o_reg:
|
||||
return;
|
||||
case o_imm:
|
||||
if ( !isload )
|
||||
error("interr: emu");
|
||||
process_immediate_number(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, calc_outf(x));
|
||||
break;
|
||||
case o_near:
|
||||
{
|
||||
cref_t ftype = fl_JN;
|
||||
ea_t ea = calc_code_mem(insn, x.addr);
|
||||
if ( has_insn_feature(insn.itype, CF_CALL) )
|
||||
{
|
||||
if ( !func_does_return(ea) )
|
||||
flow = false;
|
||||
ftype = fl_CN;
|
||||
}
|
||||
insn.add_cref(ea, x.offb, ftype);
|
||||
propagate_sreg(insn, ea, BANK);
|
||||
propagate_sreg(insn, ea, PCLATH);
|
||||
}
|
||||
break;
|
||||
case o_mem:
|
||||
{
|
||||
ea_t ea = calc_data_mem(x.addr);
|
||||
destroy_if_unnamed_array(ea);
|
||||
insn.add_dref(ea, x.offb, isload ? dr_R : dr_W);
|
||||
insn.create_op_data(ea, x);
|
||||
if ( may_create_stkvars() )
|
||||
{
|
||||
if ( x.addr == PIC16_INDF2 )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 )
|
||||
{
|
||||
insn.create_stkvar(insn.Op1, 0, STKVAR_VALID_SIZE);
|
||||
}
|
||||
}
|
||||
else if ( x.addr == PIC16_PLUSW2 )
|
||||
{
|
||||
insn_t l = insn;
|
||||
if ( decode_prev_insn(&l, l.ea) != BADADDR
|
||||
&& l.itype == PIC_movlw )
|
||||
{
|
||||
func_t *pfn = get_func(l.ea);
|
||||
if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 )
|
||||
{
|
||||
if ( l.create_stkvar(l.Op1, l.Op1.value, STKVAR_VALID_SIZE) )
|
||||
op_stkvar(l.ea, l.Op1.n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case o_displ:
|
||||
process_immediate_number(insn, x.n);
|
||||
if ( op_adds_xrefs(get_flags(insn.ea), x.n) )
|
||||
insn.add_off_drefs(x, dr_O, OOF_ADDR | OOFW_8);
|
||||
break;
|
||||
default:
|
||||
INTERR(10310);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// change value of virtual register "BANK" and switch to another bank
|
||||
void pic_t::split(const insn_t &insn, int reg, sel_t v)
|
||||
{
|
||||
if ( reg == -1 )
|
||||
{
|
||||
flow = 0;
|
||||
if ( v != BADSEL )
|
||||
{
|
||||
sel_t pclath = get_sreg(insn.ea, PCLATH) & 0x1F;
|
||||
ea_t ea = calc_code_mem(insn, uchar(v) | (pclath<<8));
|
||||
add_cref(insn.ea, ea, fl_JN);
|
||||
propagate_sreg(insn, ea, BANK);
|
||||
propagate_sreg(insn, ea, PCLATH);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( v == BADSEL )
|
||||
v = 0; // assume bank0 if bank is unknown
|
||||
if ( reg == BANK )
|
||||
{
|
||||
// banks 0..15
|
||||
v &= 0xF;
|
||||
}
|
||||
split_sreg_range(get_item_end(insn.ea), reg, v, SR_auto);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// tris PORTn (or movwf TRISn)
|
||||
bool pic_t::is_load_tris_reg(const insn_t &insn)
|
||||
{
|
||||
ea_t addr;
|
||||
const char *key;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case PIC_tris:
|
||||
addr = insn.Op1.value;
|
||||
key = "port";
|
||||
break;
|
||||
case PIC_movwf:
|
||||
addr = insn.Op1.addr;
|
||||
key = "tris";
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
qstring name;
|
||||
addr = calc_data_mem(addr);
|
||||
if ( get_name(&name, addr, GN_NOT_DUMMY) <= 0 )
|
||||
return false;
|
||||
return strnieq(name.begin(), key, 4);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
inline void pic_t::set_plain_offset(ea_t insn_ea, int n, ea_t base) const
|
||||
{
|
||||
if ( base == BADADDR )
|
||||
base = calc_offset_base(insn_ea, n);
|
||||
if ( base != BADADDR )
|
||||
op_plain_offset(insn_ea, n, base);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int pic_t::emu(const insn_t &insn)
|
||||
{
|
||||
uint32 Feature = insn.get_canon_feature(ph);
|
||||
flow = (Feature & CF_STOP) == 0;
|
||||
|
||||
int bit = CF_USE1;
|
||||
bool use = true;
|
||||
while ( true )
|
||||
{
|
||||
for ( int i=0; i < 3; i++,bit<<=1 )
|
||||
{
|
||||
if ( (Feature & bit) == 0 )
|
||||
continue;
|
||||
bool forced = is_forced_operand(insn.ea, i);
|
||||
handle_operand(insn, insn.ops[i], forced, use);
|
||||
}
|
||||
if ( !use )
|
||||
break;
|
||||
use = false;
|
||||
bit = CF_CHG1;
|
||||
}
|
||||
|
||||
// Check for:
|
||||
// - the register bank changes
|
||||
// - PCLATH changes
|
||||
// - PCL changes
|
||||
bool check_regs = false;
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case PIC_movlp: // Move literal to PCLATH
|
||||
split(insn, PCLATH, insn.Op1.value);
|
||||
break;
|
||||
case PIC_movlb: // Move literal to BSR
|
||||
split(insn, BANK, insn.Op1.value);
|
||||
break;
|
||||
default:
|
||||
check_regs = true;
|
||||
break;
|
||||
}
|
||||
|
||||
for ( int i=0; check_regs && i < 3; i++ )
|
||||
{
|
||||
int reg = 0;
|
||||
switch ( i )
|
||||
{
|
||||
case 0:
|
||||
reg = BANK;
|
||||
if ( !is_bank(insn) )
|
||||
continue;
|
||||
break;
|
||||
case 1:
|
||||
reg = PCLATH;
|
||||
if ( !is_pclath(insn) )
|
||||
continue;
|
||||
break;
|
||||
case 2:
|
||||
reg = -1;
|
||||
if ( !is_pcl(insn) )
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
sel_t v = (reg == -1) ? insn.ip : get_sreg(insn.ea, reg);
|
||||
if ( insn.Op2.type == o_reg && insn.Op2.reg == F )
|
||||
{
|
||||
// split(insn, reg, v);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case PIC_bcf:
|
||||
case PIC_bcf3:
|
||||
case PIC_bsf:
|
||||
case PIC_bsf3:
|
||||
if ( (ptype == PIC12 && insn.Op2.value == 5) // bank selector (PA0)
|
||||
|| (ptype == PIC14
|
||||
&& ((reg == BANK && (insn.Op2.value == 5 || insn.Op2.value == 6)) // bank selector (RP1:RP0)
|
||||
|| (reg == PCLATH && (insn.Op2.value == 3 || insn.Op2.value == 4))))
|
||||
|| (ptype == PIC16 && sval_t(insn.Op2.value) >= 0 && insn.Op2.value <= 3) )
|
||||
{
|
||||
if ( v == BADSEL )
|
||||
v = 0;
|
||||
int shift = 0;
|
||||
if ( (ptype == PIC14 || ptype == PIC12) && reg == BANK ) // we use bank selector bits as the bank value
|
||||
shift = 5;
|
||||
if ( insn.itype == PIC_bcf )
|
||||
v = v & ~(sel_t(1) << (insn.Op2.value-shift));
|
||||
else
|
||||
v = v | (sel_t(1) << (insn.Op2.value-shift));
|
||||
split(insn, reg, v);
|
||||
}
|
||||
break;
|
||||
case PIC_clrf:
|
||||
case PIC_clrf2:
|
||||
split(insn, reg, 0);
|
||||
break;
|
||||
case PIC_swapf:
|
||||
case PIC_swapf3:
|
||||
split(insn, reg, ((v>>4) & 15) | ((v & 15) << 4));
|
||||
break;
|
||||
case PIC_movwf:
|
||||
case PIC_movwf2:
|
||||
case PIC_addlw:
|
||||
case PIC_andlw:
|
||||
case PIC_iorlw:
|
||||
case PIC_sublw:
|
||||
case PIC_xorlw:
|
||||
{
|
||||
insn_t l = insn;
|
||||
if ( decode_prev_insn(&l, l.ea) != BADADDR
|
||||
&& l.itype == PIC_movlw )
|
||||
{
|
||||
switch ( insn.itype )
|
||||
{
|
||||
case PIC_movwf:
|
||||
case PIC_movwf2:
|
||||
v = l.Op1.value;
|
||||
break;
|
||||
case PIC_addlw:
|
||||
v += l.Op1.value;
|
||||
break;
|
||||
case PIC_andlw:
|
||||
v &= l.Op1.value;
|
||||
break;
|
||||
case PIC_iorlw:
|
||||
v |= l.Op1.value;
|
||||
break;
|
||||
case PIC_sublw:
|
||||
v -= l.Op1.value;
|
||||
break;
|
||||
case PIC_xorlw:
|
||||
v ^= l.Op1.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
v = BADSEL;
|
||||
}
|
||||
}
|
||||
split(insn, reg, v);
|
||||
break;
|
||||
case PIC_movlw:
|
||||
split(insn, reg, insn.Op2.value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Such as, IDA doesn't seem to convert the following:
|
||||
// tris 6
|
||||
// into
|
||||
// tris PORTB ( or whatever )
|
||||
|
||||
flags_t flags = get_flags(insn.ea);
|
||||
if ( insn.itype == PIC_tris && !is_defarg0(flags) )
|
||||
set_plain_offset(insn.ea, 0, dataseg);
|
||||
|
||||
// movlw value
|
||||
// followed by a
|
||||
// movwf FSR
|
||||
// should convert value into an offset , because FSR is used as a pointer to
|
||||
// the INDF (indirect addressing file)
|
||||
|
||||
if ( insn.itype == PIC_movwf
|
||||
&& insn.Op1.type == o_mem
|
||||
&& is_banked_reg(insn.Op1.addr, 0x4) ) // FSR
|
||||
{
|
||||
insn_t l = insn;
|
||||
if ( decode_prev_insn(&l, l.ea) != BADADDR
|
||||
&& l.itype == PIC_movlw )
|
||||
{
|
||||
set_plain_offset(l.ea, 0, dataseg);
|
||||
}
|
||||
}
|
||||
|
||||
// Also - it seems to make sense to me that a
|
||||
// movlw value
|
||||
// followed by a
|
||||
// tris PORTn (or movwf TRISn)
|
||||
// should convert value into a binary , because the bits indicate whether a
|
||||
// port is defined for input or output.
|
||||
|
||||
if ( is_load_tris_reg(insn) )
|
||||
{
|
||||
insn_t l;
|
||||
if ( decode_prev_insn(&l, insn.ea) != BADADDR
|
||||
&& l.itype == PIC_movlw )
|
||||
{
|
||||
op_bin(l.ea, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Move litteral to BSR
|
||||
|
||||
if ( insn.itype == PIC_movlb1 )
|
||||
split(insn, BANK, insn.Op1.value);
|
||||
|
||||
//
|
||||
// Determine if the next instruction should be executed
|
||||
//
|
||||
if ( !flow )
|
||||
{
|
||||
flags = get_flags(insn.ea);
|
||||
flow = conditional_insn(insn, flags);
|
||||
}
|
||||
if ( segtype(insn.ea) == SEG_XTRN )
|
||||
flow = false;
|
||||
if ( flow )
|
||||
add_cref(insn.ea, insn.ea+insn.size, fl_F);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool pic_t::create_func_frame(func_t *pfn) const
|
||||
{
|
||||
if ( pfn != NULL )
|
||||
{
|
||||
if ( pfn->frame == BADNODE )
|
||||
{
|
||||
ea_t ea = pfn->start_ea;
|
||||
if ( ea + 12 < pfn->end_ea ) // minimum 4 + 4 + 2 + 2 bytes needed
|
||||
{
|
||||
insn_t insn[4];
|
||||
for ( int i=0; i < 4; i++ )
|
||||
{
|
||||
int len = decode_insn(&insn[i], ea);
|
||||
ea += len > 0 ? len : 0;
|
||||
}
|
||||
if ( insn[0].itype == PIC_movff2 // movff FSR2L,POSTINC1
|
||||
&& insn[0].Op1.addr == PIC16_FSR2L && insn[0].Op2.addr == PIC16_POSTINC1
|
||||
&& insn[1].itype == PIC_movff2 // movff FSR1L,FSR2L
|
||||
&& insn[1].Op1.addr == PIC16_FSR1L && insn[1].Op2.addr == PIC16_FSR2L
|
||||
&& insn[2].itype == PIC_movlw // movlw <size>
|
||||
&& insn[3].itype == PIC_addwf3 // addwf FSR1L,f
|
||||
&& insn[3].Op1.addr == PIC16_FSR1L && insn[3].Op2.reg == F )
|
||||
{
|
||||
pfn->flags |= FUNC_FRAME;
|
||||
return add_frame(pfn, insn[2].Op1.value, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
207
idasdk76/module/pic/ins.cpp
Normal file
207
idasdk76/module/pic/ins.cpp
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pic.hpp"
|
||||
|
||||
const instruc_t Instructions[] =
|
||||
{
|
||||
|
||||
{ "", 0 }, // Unknown Operation
|
||||
|
||||
// BYTE-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
{ "addwf", CF_USE1|CF_USE2 }, // Add W and f
|
||||
{ "andwf", CF_USE1|CF_USE2 }, // AND W with f
|
||||
{ "clrf", CF_CHG1 }, // Clear f
|
||||
{ "clrw", 0 }, // Clear W
|
||||
{ "comf", CF_USE1|CF_USE2 }, // Complement f
|
||||
{ "decf", CF_USE1|CF_USE2 }, // Decrement f
|
||||
{ "decfsz", CF_USE1|CF_USE2 }, // Decrement f, Skip if 0
|
||||
{ "incf", CF_USE1|CF_USE2 }, // Increment f
|
||||
{ "incfsz", CF_USE1|CF_USE2 }, // Increment f, Skip if 0
|
||||
{ "iorwf", CF_USE1|CF_USE2 }, // Inclusive OR W with f
|
||||
{ "movf", CF_USE1|CF_USE2 }, // Move f
|
||||
{ "movwf", CF_CHG1 }, // Move W to f
|
||||
{ "nop", 0 }, // No Operation
|
||||
{ "rlf", CF_USE1|CF_USE2 }, // Rotate Left f through Carry
|
||||
{ "rrf", CF_USE1|CF_USE2 }, // Rotate Right f through Carry
|
||||
{ "subwf", CF_USE1|CF_USE2 }, // Subtract W from f
|
||||
{ "swapf", CF_USE1|CF_USE2 }, // Swap nibbles in f
|
||||
{ "xorwf", CF_USE1|CF_USE2 }, // Exclusive OR W with f
|
||||
|
||||
// BIT-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
{ "bcf", CF_CHG1|CF_USE2 }, // Bit Clear f
|
||||
{ "bsf", CF_CHG1|CF_USE2 }, // Bit Set f
|
||||
{ "btfsc", CF_USE1|CF_USE2 }, // Bit Test f, Skip if Clear
|
||||
{ "btfss", CF_USE1|CF_USE2 }, // Bit Test f, Skip if Set
|
||||
|
||||
// LITERAL AND CONTROL OPERATIONS
|
||||
|
||||
{ "addlw", CF_USE1 }, // Add literal and W
|
||||
{ "andlw", CF_USE1 }, // AND literal with W
|
||||
{ "call", CF_USE1|CF_CALL }, // Call subroutine
|
||||
{ "clrwdt", 0 }, // Clear Watchdog Timer
|
||||
{ "goto", CF_USE1|CF_STOP }, // Go to address
|
||||
{ "iorlw", CF_USE1 }, // Inclusive OR literal with W
|
||||
{ "movlw", CF_USE1 }, // Move literal to W
|
||||
{ "retfie", CF_STOP }, // Return from interrupt
|
||||
{ "retlw", CF_USE1|CF_STOP }, // Return with literal in W
|
||||
{ "return", CF_STOP }, // Return from Subroutine
|
||||
{ "sleep", 0 }, // Go into standby mode
|
||||
{ "sublw", CF_USE1 }, // Subtract W from literal
|
||||
{ "xorlw", CF_USE1 }, // Exclusive OR literal with W
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x
|
||||
|
||||
{ "option", 0 }, // Load OPTION register
|
||||
{ "tris", CF_USE1 }, // Load TRIS Register
|
||||
|
||||
// MACROS
|
||||
|
||||
{ "movfw", CF_USE1 }, // Move Contents of File Reg to W
|
||||
{ "tstf", CF_USE1 }, // Test Contents of File Register
|
||||
{ "negf", CF_USE1|CF_USE2 }, // Negate File Register Contents
|
||||
{ "b", CF_USE1|CF_STOP }, // Branch to Address
|
||||
{ "clrc", 0 }, // Clear Carry
|
||||
{ "clrdc", 0 }, // Clear Digit Carry
|
||||
{ "clrz", 0 }, // Clear Zero
|
||||
{ "setc", 0 }, // Set Carry
|
||||
{ "setdc", 0 }, // Set Digit Carry
|
||||
{ "setz", 0 }, // Set Zero
|
||||
{ "skpc", 0 }, // Skip on Carry
|
||||
{ "skpdc", 0 }, // Skip on Digit Carry
|
||||
{ "skpnc", 0 }, // Skip on No Carry
|
||||
{ "skpndc", 0 }, // Skip on No Digit Carry
|
||||
{ "skpnz", 0 }, // Skip on No Zero
|
||||
{ "skpz", 0 }, // Skip on Zero
|
||||
{ "bc", CF_USE1 }, // Branch on Carry to Address k
|
||||
{ "bdc", CF_USE1 }, // Branch on Digit Carry to k
|
||||
{ "bnc", CF_USE1 }, // Branch on No Carry to k
|
||||
{ "bndc", CF_USE1 }, // Branch on No Digit Carry to k
|
||||
{ "bnz", CF_USE1 }, // Branch on No Zero to Address
|
||||
{ "bz", CF_USE1 }, // Branch on Zero to Address k
|
||||
{ "addcf", CF_USE1|CF_USE2 }, // Add Carry to File Register
|
||||
{ "adddcf", CF_USE1|CF_USE2 }, // Add Digit to File Register
|
||||
{ "subcf", CF_USE1|CF_USE2 }, // Subtract Carry from File Reg
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS FOR 18Cxx
|
||||
|
||||
// BYTE-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
{ "addwf", CF_USE1|CF_USE2|CF_USE3 }, // Add W and f
|
||||
{ "addwfc", CF_USE1|CF_USE2|CF_USE3 }, // Add W and Carry to f
|
||||
{ "andwf", CF_USE1|CF_USE2|CF_USE3 }, // AND W with f
|
||||
{ "clrf", CF_CHG1|CF_USE2 }, // Clear f
|
||||
{ "comf", CF_CHG1|CF_USE2|CF_USE3 }, // Complement f
|
||||
{ "cpfseq", CF_USE1|CF_USE2 }, // Compare f with W, Skip if ==
|
||||
{ "cpfsgt", CF_USE1|CF_USE2 }, // Compare f with W, Skip if >
|
||||
{ "cpfslt", CF_USE1|CF_USE2 }, // Compare f with W, Skip if <
|
||||
{ "decf", CF_CHG1|CF_USE2|CF_USE3 }, // Decrement f
|
||||
{ "decfsz", CF_CHG1|CF_USE2|CF_USE3 }, // Decrement f, Skip if 0
|
||||
{ "dcfsnz", CF_CHG1|CF_USE2|CF_USE3 }, // Decrement f, Skip if not 0
|
||||
{ "incf", CF_CHG1|CF_USE2|CF_USE3 }, // Increment f
|
||||
{ "incfsz", CF_CHG1|CF_USE2|CF_USE3 }, // Increment f, Skip if 0
|
||||
{ "infsnz", CF_CHG1|CF_USE2|CF_USE3 }, // Increment f, Skip if not 0
|
||||
{ "iorwf", CF_USE1|CF_USE2|CF_USE3 }, // Inclusive OR W with f
|
||||
{ "movf", CF_USE1|CF_USE2|CF_USE3 }, // Move f
|
||||
{ "movff", CF_USE1|CF_CHG2 }, // Move fs to fd
|
||||
{ "movwf", CF_CHG1|CF_USE2 }, // Move W to f
|
||||
{ "mulwf", CF_USE1|CF_USE2 }, // Multiply W with f
|
||||
{ "negf", CF_CHG1|CF_USE2 }, // Negate f
|
||||
{ "rlcf", CF_CHG1|CF_USE2|CF_USE3 }, // Rotate Left f through Carry
|
||||
{ "rlncf", CF_CHG1|CF_USE2|CF_USE3 }, // Rotate Left f
|
||||
{ "rrcf", CF_CHG1|CF_USE2|CF_USE3 }, // Rotate Right f through Carry
|
||||
{ "rrncf", CF_CHG1|CF_USE2|CF_USE3 }, // Rotate Right f
|
||||
{ "setf", CF_CHG1|CF_USE2 }, // Set f
|
||||
{ "subfwb", CF_USE1|CF_USE2|CF_USE3 }, // Substract f from W with borrow
|
||||
{ "subwf", CF_USE1|CF_USE2|CF_USE3 }, // Substract W from f
|
||||
{ "subwfb", CF_USE1|CF_USE2|CF_USE3 }, // Substract W from f with borrow
|
||||
{ "swapf", CF_CHG1|CF_USE2|CF_USE3 }, // Swap nibbles in f
|
||||
{ "tstfsz", CF_USE1|CF_USE2 }, // Test f, Skip if 0
|
||||
{ "xorwf", CF_USE1|CF_USE2|CF_USE3 }, // Exclusive OR W with f
|
||||
|
||||
// BIT-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
{ "bcf", CF_CHG1|CF_USE2|CF_USE3 }, // Bit Clear f
|
||||
{ "bsf", CF_CHG1|CF_USE2|CF_USE3 }, // Bit Set f
|
||||
{ "btfsc", CF_USE1|CF_USE2|CF_USE3 }, // Bit Test f, Skip if Clear
|
||||
{ "btfss", CF_USE1|CF_USE2|CF_USE3 }, // Bit Test f, Skip if Set
|
||||
{ "btg", CF_CHG1|CF_USE2|CF_USE3 }, // Bit Toggle f
|
||||
|
||||
// CONTROL OPERATIONS
|
||||
|
||||
{ "bc", CF_USE1 }, // Branch if Carry
|
||||
{ "bn", CF_USE1 }, // Branch if Negative
|
||||
{ "bnc", CF_USE1 }, // Branch if not Carry
|
||||
{ "bnn", CF_USE1 }, // Branch if not Negative
|
||||
{ "bnov", CF_USE1 }, // Branch if not Overflow
|
||||
{ "bnz", CF_USE1 }, // Branch if not Zero
|
||||
{ "bov", CF_USE1 }, // Branch if Overflow
|
||||
{ "bra", CF_USE1|CF_STOP }, // Branch unconditionally
|
||||
{ "bz", CF_USE1 }, // Branch if Zero
|
||||
{ "call", CF_USE1|CF_USE2|CF_CALL }, // Call subroutine
|
||||
// clrwdt
|
||||
{ "daw", 0 }, // Decimal Adjust W
|
||||
// goto
|
||||
// nop
|
||||
// nop
|
||||
{ "pop", 0 }, // Pop top of return stack
|
||||
{ "push", 0 }, // Push top of return stack
|
||||
{ "rcall", CF_USE1|CF_CALL }, // Relative Call subroutine
|
||||
{ "reset", 0 }, // Software device Reset
|
||||
{ "retfie", CF_USE1|CF_STOP }, // Return from interrupt enable
|
||||
// retlw
|
||||
{ "return", CF_USE1|CF_STOP }, // Return from Subroutine
|
||||
// sleep
|
||||
|
||||
// LITERAL OPERATIONS
|
||||
|
||||
// addlw
|
||||
// andlw
|
||||
// iorlw
|
||||
{ "lfsr", CF_CHG1|CF_USE2 }, // Move literal to FSR
|
||||
{ "movlb", CF_USE1 }, // Move literal to BSR
|
||||
// movlw
|
||||
{ "mullw", CF_USE1 }, // Multiply literal with W
|
||||
// retlw
|
||||
// sublw
|
||||
// xorlw
|
||||
|
||||
// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS
|
||||
|
||||
{ "tblrd*", 0 }, // Table Read
|
||||
{ "tblrd*+", 0 }, // Table Read with post-increment
|
||||
{ "tblrd*-", 0 }, // Table Read with post-decrement
|
||||
{ "tblrd+*", 0 }, // Table Read with pre-increment
|
||||
{ "tblwt*", 0 }, // Table Write
|
||||
{ "tblwt*+", 0 }, // Table Write with post-increment
|
||||
{ "tblwt*-", 0 }, // Table Write with post-decrement
|
||||
{ "tblwt+*", 0 }, // Table Write with pre-increment
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS FOR 16F1x AND 12F1x
|
||||
|
||||
{ "addwfc", CF_USE1|CF_USE2 }, // Add W and Carry to f
|
||||
{ "movlp", CF_USE1 }, // Move literal to PCLATH
|
||||
{ "movlb", CF_USE1 }, // Move literal to BSR
|
||||
{ "addfsr", CF_CHG1|CF_USE2 }, // Add Literal to FSRn
|
||||
{ "asrf", CF_USE1|CF_USE2 }, // Arithmetic Right Shift
|
||||
{ "lslf", CF_USE1|CF_USE2 }, // Logical Left Shift
|
||||
{ "lsrf", CF_USE1|CF_USE2 }, // Logical Right Shift
|
||||
{ "subwfb", CF_USE1|CF_USE2 }, // Subtract W from f with Borrow
|
||||
{ "bra", CF_USE1|CF_STOP }, // Relative Branch
|
||||
{ "brw", CF_STOP }, // Relative Branch with W
|
||||
{ "callw", CF_CALL }, // Call Subroutine with W
|
||||
{ "reset", 0 }, // Software device Reset
|
||||
{ "moviw", CF_USE1 }, // Move INDFn to W
|
||||
{ "movwi", CF_USE1 }, // Move W to INDFn
|
||||
|
||||
};
|
||||
|
||||
CASSERT(qnumber(Instructions) == PIC_last);
|
||||
211
idasdk76/module/pic/ins.hpp
Normal file
211
idasdk76/module/pic/ins.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-2021 Hex-Rays
|
||||
* ALL RIGHTS RESERVED.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __INSTRS_HPP
|
||||
#define __INSTRS_HPP
|
||||
|
||||
extern const instruc_t Instructions[];
|
||||
|
||||
enum nameNum ENUM_SIZE(uint16)
|
||||
{
|
||||
|
||||
PIC_null = 0, // Unknown Operation
|
||||
|
||||
// BYTE-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
PIC_addwf, // Add W and f
|
||||
PIC_andwf, // AND W with f
|
||||
PIC_clrf, // Clear f
|
||||
PIC_clrw, // Clear W
|
||||
PIC_comf, // Complement f
|
||||
PIC_decf, // Decrement f
|
||||
PIC_decfsz, // Decrement f, Skip if 0
|
||||
PIC_incf, // Increment f
|
||||
PIC_incfsz, // Increment f, Skip if 0
|
||||
PIC_iorwf, // Inclusive OR W with f
|
||||
PIC_movf, // Move f
|
||||
PIC_movwf, // Move W to f
|
||||
PIC_nop, // No Operation
|
||||
PIC_rlf, // Rotate Left f through Carry
|
||||
PIC_rrf, // Rotate Right f through Carry
|
||||
PIC_subwf, // Subtract W from f
|
||||
PIC_swapf, // Swap nibbles in f
|
||||
PIC_xorwf, // Exclusive OR W with f
|
||||
|
||||
// BIT-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
PIC_bcf, // Bit Clear f
|
||||
PIC_bsf, // Bit Set f
|
||||
PIC_btfsc, // Bit Test f, Skip if Clear
|
||||
PIC_btfss, // Bit Test f, Skip if Set
|
||||
|
||||
|
||||
// LITERAL AND CONTROL OPERATIONS
|
||||
|
||||
PIC_addlw, // Add literal and W
|
||||
PIC_andlw, // AND literal with W
|
||||
PIC_call, // Call subroutine
|
||||
PIC_clrwdt, // Clear Watchdog Timer
|
||||
PIC_goto, // Go to address
|
||||
PIC_iorlw, // Inclusive OR literal with W
|
||||
PIC_movlw, // Move literal to W
|
||||
PIC_retfie, // Return from interrupt
|
||||
PIC_retlw, // Return with literal in W
|
||||
PIC_return, // Return from Subroutine
|
||||
PIC_sleep, // Go into standby mode
|
||||
PIC_sublw, // Subtract W from literal
|
||||
PIC_xorlw, // Exclusive OR literal with W
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x
|
||||
|
||||
PIC_option, // Load OPTION register
|
||||
PIC_tris, // Load TRIS Register
|
||||
|
||||
// MACROS
|
||||
|
||||
PIC_movfw, // Move Contents of File Reg to W
|
||||
PIC_tstf, // Test Contents of File Register
|
||||
PIC_negf, // Negate File Register Contents
|
||||
PIC_b, // Branch to Address
|
||||
PIC_clrc, // Clear Carry
|
||||
PIC_clrdc, // Clear Digit Carry
|
||||
PIC_clrz, // Clear Zero
|
||||
PIC_setc, // Set Carry
|
||||
PIC_setdc, // Set Digit Carry
|
||||
PIC_setz, // Set Zero
|
||||
PIC_skpc, // Skip on Carry
|
||||
PIC_skpdc, // Skip on Digit Carry
|
||||
PIC_skpnc, // Skip on No Carry
|
||||
PIC_skpndc, // Skip on No Digit Carry
|
||||
PIC_skpnz, // Skip on No Zero
|
||||
PIC_skpz, // Skip on Zero
|
||||
PIC_bc, // Branch on Carry to Address k
|
||||
PIC_bdc, // Branch on Digit Carry to k
|
||||
PIC_bnc, // Branch on No Carry to k
|
||||
PIC_bndc, // Branch on No Digit Carry to k
|
||||
PIC_bnz, // Branch on No Zero to Address
|
||||
PIC_bz, // Branch on Zero to Address k
|
||||
PIC_addcf, // Add Carry to File Register
|
||||
PIC_adddcf, // Add Digit to File Register
|
||||
PIC_subcf, // Subtract Carry from File Reg
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS FOR 18Cxx
|
||||
|
||||
// BYTE-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
PIC_addwf3, // Add W and f
|
||||
PIC_addwfc3, // Add W and Carry to f
|
||||
PIC_andwf3, // AND W with f
|
||||
PIC_clrf2, // Clear f
|
||||
PIC_comf3, // Complement f
|
||||
PIC_cpfseq2, // Compare f with W, Skip if ==
|
||||
PIC_cpfsgt2, // Compare f with W, Skip if >
|
||||
PIC_cpfslt2, // Compare f with W, Skip if <
|
||||
PIC_decf3, // Decrement f
|
||||
PIC_decfsz3, // Decrement f, Skip if 0
|
||||
PIC_dcfsnz3, // Decrement f, Skip if not 0
|
||||
PIC_incf3, // Increment f
|
||||
PIC_incfsz3, // Increment f, Skip if 0
|
||||
PIC_infsnz3, // Increment f, Skip if not 0
|
||||
PIC_iorwf3, // Inclusive OR W with f
|
||||
PIC_movf3, // Move f
|
||||
PIC_movff2, // Move fs to fd
|
||||
PIC_movwf2, // Move W to f
|
||||
PIC_mulwf2, // Multiply W with f
|
||||
PIC_negf2, // Negate f
|
||||
PIC_rlcf3, // Rotate Left f through Carry
|
||||
PIC_rlncf3, // Rotate Left f
|
||||
PIC_rrcf3, // Rotate Right f through Carry
|
||||
PIC_rrncf3, // Rotate Right f
|
||||
PIC_setf2, // Set f
|
||||
PIC_subfwb3, // Substract f from W with borrow
|
||||
PIC_subwf3, // Substract W from f
|
||||
PIC_subwfb3, // Substract W from f with borrow
|
||||
PIC_swapf3, // Swap nibbles in f
|
||||
PIC_tstfsz2, // Test f, Skip if 0
|
||||
PIC_xorwf3, // Exclusive OR W with f
|
||||
|
||||
// BIT-ORIENTED FILE REGISTER OPERATIONS
|
||||
|
||||
PIC_bcf3, // Bit Clear f
|
||||
PIC_bsf3, // Bit Set f
|
||||
PIC_btfsc3, // Bit Test f, Skip if Clear
|
||||
PIC_btfss3, // Bit Test f, Skip if Set
|
||||
PIC_btg3, // Bit Toggle f
|
||||
|
||||
// CONTROL OPERATIONS
|
||||
|
||||
PIC_bc1, // Branch if Carry
|
||||
PIC_bn1, // Branch if Negative
|
||||
PIC_bnc1, // Branch if not Carry
|
||||
PIC_bnn1, // Branch if not Negative
|
||||
PIC_bnov1, // Branch if not Overflow
|
||||
PIC_bnz1, // Branch if not Zero
|
||||
PIC_bov1, // Branch if Overflow
|
||||
PIC_bra1, // Branch unconditionally
|
||||
PIC_bz1, // Branch if Zero
|
||||
PIC_call2, // Call subroutine
|
||||
// PIC_clrwdt
|
||||
PIC_daw0, // Decimal Adjust W
|
||||
// PIC_goto
|
||||
// PIC_nop
|
||||
// PIC_nop
|
||||
PIC_pop0, // Pop top of return stack
|
||||
PIC_push0, // Push top of return stack
|
||||
PIC_rcall1, // Relative Call subroutine
|
||||
PIC_reset0, // Software device Reset
|
||||
PIC_retfie1, // Return from interrupt enable
|
||||
// PIC_retlw
|
||||
PIC_return1, // Return from Subroutine
|
||||
// PIC_sleep
|
||||
|
||||
// LITERAL OPERATIONS
|
||||
|
||||
// PIC_addlw
|
||||
// PIC_andlw
|
||||
// PIC_iorlw
|
||||
PIC_lfsr2, // Move literal to FSR
|
||||
PIC_movlb1, // Move literal to BSR
|
||||
// PIC_movlw
|
||||
PIC_mullw1, // Multiply literal with W
|
||||
// PIC_retlw
|
||||
// PIC_sublw
|
||||
// PIC_xorlw
|
||||
|
||||
// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS
|
||||
|
||||
PIC_tblrd0, // Table Read
|
||||
PIC_tblrd0p, // Table Read with post-increment
|
||||
PIC_tblrd0m, // Table Read with post-decrement
|
||||
PIC_tblrdp0, // Table Read with pre-increment
|
||||
PIC_tblwt0, // Table Write
|
||||
PIC_tblwt0p, // Table Write with post-increment
|
||||
PIC_tblwt0m, // Table Write with post-decrement
|
||||
PIC_tblwtp0, // Table Write with pre-increment
|
||||
|
||||
// ADDITIONAL INSTRUCTIONS FOR 16F1x and 12F1x
|
||||
|
||||
PIC_addwfc, // Add W and Carry to f
|
||||
PIC_movlp, // Move literal to PCLATH
|
||||
PIC_movlb, // Move literal to BSR
|
||||
PIC_addfsr, // Add Literal to FSRn
|
||||
PIC_asrf, // Arithmetic Right Shift
|
||||
PIC_lslf, // Logical Left Shift
|
||||
PIC_lsrf, // Logical Right Shift
|
||||
PIC_subwfb, // Subtract with Borrow W from f
|
||||
PIC_bra, // Relative Branch
|
||||
PIC_brw, // Relative Branch with W
|
||||
PIC_callw, // Call Subroutine with W
|
||||
PIC_reset, // Software device Reset
|
||||
PIC_moviw, // Move INDFn to W
|
||||
PIC_movwi, // Move W to INDFn
|
||||
|
||||
PIC_last,
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
57
idasdk76/module/pic/makefile
Normal file
57
idasdk76/module/pic/makefile
Normal file
@@ -0,0 +1,57 @@
|
||||
PROC=pic
|
||||
CONFIGS=pic12.cfg pic14.cfg pic16.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)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)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp ana.cpp ins.hpp pic.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)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp emu.cpp ins.hpp pic.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)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)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \
|
||||
ins.cpp ins.hpp pic.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 pic.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)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)ua.hpp $(I)xref.hpp ../idaidp.hpp \
|
||||
../iohandler.hpp ins.hpp pic.hpp reg.cpp
|
||||
418
idasdk76/module/pic/out.cpp
Normal file
418
idasdk76/module/pic/out.cpp
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "pic.hpp"
|
||||
#include <frame.hpp>
|
||||
#include <segregs.hpp>
|
||||
#include <struct.hpp>
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
class out_pic_t : public outctx_t
|
||||
{
|
||||
out_pic_t(void) = delete; // not used
|
||||
pic_t &pm() { return *static_cast<pic_t *>(procmod); }
|
||||
public:
|
||||
void outreg(int r) { out_register(pm().ph.reg_names[r]); }
|
||||
void out_bad_address(ea_t addr);
|
||||
bool out_operand(const op_t &x);
|
||||
void out_insn(void);
|
||||
};
|
||||
CASSERT(sizeof(out_pic_t) == sizeof(outctx_t));
|
||||
|
||||
DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_pic_t)
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_pic_t::out_bad_address(ea_t addr)
|
||||
{
|
||||
out_tagon(COLOR_ERROR);
|
||||
out_btoa(addr, 16);
|
||||
out_tagoff(COLOR_ERROR);
|
||||
remember_problem(PR_NONAME, insn.ea);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t calc_code_mem(const insn_t &insn, ea_t ea)
|
||||
{
|
||||
return to_ea(insn.cs, ea);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t pic_t::calc_data_mem(ea_t ea)
|
||||
{
|
||||
return dataseg + map_port(ea);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
int calc_outf(const op_t &x)
|
||||
{
|
||||
switch ( x.dtype )
|
||||
{
|
||||
default:
|
||||
INTERR(249);
|
||||
case dt_byte: return OOFS_IFSIGN|OOFW_8;
|
||||
case dt_word: return OOFS_IFSIGN|OOFW_16;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool out_pic_t::out_operand(const op_t &x)
|
||||
{
|
||||
ea_t ea;
|
||||
switch ( x.type )
|
||||
{
|
||||
|
||||
case o_void:
|
||||
return 0;
|
||||
|
||||
case o_reg:
|
||||
switch ( x.specflag1 )
|
||||
{
|
||||
|
||||
case 0:
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
out_line("++", COLOR_SYMBOL);
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
out_line("--", COLOR_SYMBOL);
|
||||
outreg(x.reg);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
outreg(x.reg);
|
||||
out_line("++", COLOR_SYMBOL);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
outreg(x.reg);
|
||||
out_line("--", COLOR_SYMBOL);
|
||||
break;
|
||||
|
||||
default:
|
||||
INTERR(10313);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_imm:
|
||||
if ( is_bit_insn(insn) )
|
||||
{
|
||||
const char *name = pm().find_bit(insn.Op1.addr, (int)x.value);
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
break;
|
||||
}
|
||||
}
|
||||
out_value(x, calc_outf(x));
|
||||
break;
|
||||
|
||||
case o_mem:
|
||||
{
|
||||
ea = pm().calc_data_mem(x.addr);
|
||||
const char *name = pm().find_sym(x.addr);
|
||||
if ( name == NULL || name[0] == '\0' )
|
||||
goto OUTNAME;
|
||||
out_addr_tag(ea);
|
||||
out_line(name, COLOR_IMPNAME);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_near:
|
||||
{
|
||||
ea = calc_code_mem(insn, x.addr);
|
||||
OUTNAME:
|
||||
if ( !out_name_expr(x, ea, x.addr) )
|
||||
out_bad_address(x.addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case o_displ:
|
||||
out_value(x, OOF_ADDR | OOFW_8);
|
||||
out_symbol('[');
|
||||
outreg(x.phrase);
|
||||
out_symbol(']');
|
||||
break;
|
||||
default:
|
||||
INTERR(10314);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
bool pic_t::conditional_insn(const insn_t &insn, flags_t flags) const
|
||||
{
|
||||
if ( is_flow(flags) )
|
||||
{
|
||||
int code;
|
||||
switch ( ptype )
|
||||
{
|
||||
case PIC12:
|
||||
code = get_wide_byte(insn.ea-1);
|
||||
if ( (code & 0xFC0) == 0x2C0 )
|
||||
return true; // 0010 11df ffff DECFSZ f, d Decrement f, Skip if 0
|
||||
else if ( (code & 0xFC0) == 0x3C0 )
|
||||
return true; // 0011 11df ffff INCFSZ f, d Increment f, Skip if 0
|
||||
else if ( (code & 0xF00) == 0x600 )
|
||||
return true; // 0110 bbbf ffff BTFSC f, b Bit Test f, Skip if Clear
|
||||
else if ( (code & 0xF00) == 0x700 )
|
||||
return true; // 0111 bbbf ffff BTFSS f, b Bit Test f, Skip if Set
|
||||
break;
|
||||
case PIC14:
|
||||
code = get_wide_byte(insn.ea-1);
|
||||
if ( (code & 0x3F00) == 0x0B00 )
|
||||
return true; // 00 1011 dfff ffff DECFSZ f, d Decrement f, Skip if 0
|
||||
else if ( (code & 0x3F00) == 0x0F00 )
|
||||
return true; // 00 1111 dfff ffff INCFSZ f, d Increment f, Skip if 0
|
||||
else if ( (code & 0x3C00) == 0x1800 )
|
||||
return true; // 01 10bb bfff ffff BTFSC f, b Bit Test f, Skip if Clear
|
||||
else if ( (code & 0x3C00) == 0x1C00 )
|
||||
return true; // 01 11bb bfff ffff BTFSS f, b Bit Test f, Skip if Set
|
||||
break;
|
||||
case PIC16:
|
||||
code = get_word(insn.ea-2);
|
||||
code >>= 10;
|
||||
// 1010 bbba ffff ffff BTFSS f, b, a Bit Test f, Skip if Set
|
||||
// 1011 bbba ffff ffff BTFSC f, b, a Bit Test f, Skip if Clear
|
||||
if ( (code & 0x38) == 0x28 )
|
||||
return true;
|
||||
switch ( code )
|
||||
{
|
||||
case 0x0B: // 0010 11da ffff ffff DECFSZ f, d, a Decrement f, Skip if 0
|
||||
case 0x0F: // 0011 11da ffff ffff INCFSZ f, d, a Increment f, Skip if 0
|
||||
case 0x12: // 0100 10da ffff ffff INFSNZ f, d, a Increment f, Skip if not 0
|
||||
case 0x13: // 0100 11da ffff ffff DCFSNZ f, d, a Decrement f, Skip if not 0
|
||||
case 0x18: // 0110 000a ffff ffff CPFSLT f, a Compare f with W, Skip if <
|
||||
// 0110 001a ffff ffff CPFSEQ f, a Compare f with W, Skip if ==
|
||||
case 0x19: // 0110 010a ffff ffff CPFSGT f, a Compare f with W, Skip if >
|
||||
// 0110 011a ffff ffff TSTFSZ f, a Test f, Skip if 0
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void out_pic_t::out_insn(void)
|
||||
{
|
||||
if ( pm().conditional_insn(insn, F) )
|
||||
out_char(' ');
|
||||
out_mnemonic();
|
||||
|
||||
out_one_operand(0);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( insn.Op1.type == o_mem && insn.Op1.addr == PIC16_INDF2 )
|
||||
|| ( insn.Op2.type == o_mem && insn.Op2.addr == PIC16_INDF2 ) )
|
||||
{
|
||||
func_t *pfn = get_func(insn.ea);
|
||||
struc_t *sptr = get_frame(pfn);
|
||||
if ( pfn != NULL && sptr != NULL )
|
||||
{
|
||||
member_t *mptr = get_member(sptr, pfn->frregs + pfn->frsize);
|
||||
if ( mptr != NULL )
|
||||
{
|
||||
qstring name;
|
||||
if ( get_member_name(&name, mptr->id) > 0 )
|
||||
{
|
||||
out_char(' ');
|
||||
out_line(ash.cmnt, COLOR_AUTOCMT);
|
||||
out_char(' ');
|
||||
out_line(name.c_str(), COLOR_LOCNAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out_immchar_cmts();
|
||||
flush_outbuf();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::print_segment_register(outctx_t &ctx, int reg, sel_t value)
|
||||
{
|
||||
if ( reg == ph.reg_data_sreg )
|
||||
return;
|
||||
if ( value != BADSEL )
|
||||
{
|
||||
char buf[MAX_NUMBUF];
|
||||
btoa(buf, sizeof(buf), value);
|
||||
ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.gen_cmt_line("drop %s", ph.reg_names[reg]);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
void pic_t::pic_assumes(outctx_t &ctx) // function to produce assume directives
|
||||
{
|
||||
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;
|
||||
if ( seg_started || sra.start_ea == ea )
|
||||
{
|
||||
sel_t now = get_sreg(ea, i);
|
||||
sreg_range_t prev;
|
||||
bool prev_exists = get_sreg_range(&prev, ea-1, i);
|
||||
if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) )
|
||||
print_segment_register(ctx, i, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//lint -esym(1764, ctx) could be made const
|
||||
//lint -esym(818, Srange) could be made const
|
||||
void pic_t::pic_segstart(outctx_t &ctx, segment_t *Srange) const
|
||||
{
|
||||
if ( is_spec_segm(Srange->type) )
|
||||
return;
|
||||
|
||||
qstring sname;
|
||||
qstring sclas;
|
||||
get_visible_segm_name(&sname, Srange);
|
||||
get_segm_class(&sclas, Srange);
|
||||
|
||||
ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s (%s)", SCOLOR_AUTOCMT),
|
||||
ash.cmnt,
|
||||
sclas == "CODE" ? ".text" :
|
||||
sclas == "BSS" ? ".bss" :
|
||||
".data",
|
||||
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 pic_segend(outctx_t &, segment_t *)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::pic_header(outctx_t &ctx)
|
||||
{
|
||||
ctx.gen_header(GH_PRINT_PROC_AND_ASM);
|
||||
ctx.gen_printf(0, COLSTR("include \"P%s.INC\"", SCOLOR_ASMDIR), ioh.device.c_str());
|
||||
ctx.gen_header_extra();
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::pic_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);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::out_equ(outctx_t &ctx, bool indent, const char *name, uval_t off)
|
||||
{
|
||||
if ( name != NULL && name[0] != '\0' )
|
||||
{
|
||||
if ( indent )
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(name);
|
||||
ctx.out_spaces(inf_get_indent()-1);
|
||||
ctx.out_char(' ');
|
||||
ctx.out_line(ash.a_equ, COLOR_KEYWORD);
|
||||
ctx.out_char(' ');
|
||||
ctx.out_tagon(COLOR_NUMBER);
|
||||
ctx.out_btoa(off);
|
||||
ctx.out_tagoff(COLOR_NUMBER);
|
||||
ctx.set_gen_label();
|
||||
ctx.flush_outbuf(0x80000000);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// output "equ" directive(s) if necessary
|
||||
int pic_t::out_equ(outctx_t &ctx)
|
||||
{
|
||||
ea_t ea = ctx.insn_ea;
|
||||
segment_t *s = getseg(ea);
|
||||
if ( s != NULL && s->type == SEG_IMEM && ash.a_equ != NULL )
|
||||
{
|
||||
qstring name;
|
||||
if ( get_visible_name(&name, ea) > 0 )
|
||||
{
|
||||
ctx.ctxflags |= CTXF_LABEL_OK;
|
||||
uval_t off = ea - get_segm_base(s);
|
||||
out_equ(ctx, false, name.begin(), off);
|
||||
const ioport_bits_t *_bits = find_bits(off);
|
||||
if ( _bits != NULL )
|
||||
{
|
||||
const ioport_bits_t &bits = *_bits;
|
||||
for ( int i=0; i < bits.size(); i++ )
|
||||
out_equ(ctx, true, bits[i].name.c_str(), i);
|
||||
if ( !bits.empty() )
|
||||
ctx.gen_empty_line();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.flush_buf("");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::pic_data(outctx_t &ctx, bool analyze_only)
|
||||
{
|
||||
// the kernel's standard routine which outputs the data knows nothing
|
||||
// about "equ" directives. So we do the following:
|
||||
// - try to output an "equ" directive
|
||||
// - if we succeed, then ok
|
||||
// - otherwise let the standard data output routine, out_data()
|
||||
// do all the job
|
||||
|
||||
if ( !out_equ(ctx) )
|
||||
ctx.out_data(analyze_only);
|
||||
}
|
||||
169
idasdk76/module/pic/pic.hpp
Normal file
169
idasdk76/module/pic/pic.hpp
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PIC_HPP
|
||||
#define _PIC_HPP
|
||||
|
||||
#include "../idaidp.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include "ins.hpp"
|
||||
#include "../iohandler.hpp"
|
||||
#define PROCMOD_NAME pic
|
||||
#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME)
|
||||
|
||||
//------------------------------------------------------------------
|
||||
enum regnum_t ENUM_SIZE(uint16)
|
||||
{
|
||||
W, F,
|
||||
ACCESS, // register for PIC18Cxx
|
||||
BANKED, // register for PIC18Cxx
|
||||
FAST, // register for PIC18Cxx
|
||||
FSR0, // register for PIC18Cxx
|
||||
FSR1, // register for PIC18Cxx
|
||||
FSR2, // register for PIC18Cxx
|
||||
BANK,
|
||||
rVcs, rVds, // virtual registers for code and data segments
|
||||
PCLATH,
|
||||
PCLATU // register for PIC18Cxx
|
||||
};
|
||||
|
||||
#define PIC16_FSR2L 0xFD9
|
||||
#define PIC16_PLUSW2 0xFDB
|
||||
#define PIC16_INDF2 0xFDF
|
||||
#define PIC16_BANK 0xFE0
|
||||
#define PIC16_FSR1L 0xFE1
|
||||
#define PIC16_POSTINC1 0xFE6
|
||||
#define PIC16_PCL 0xFF9
|
||||
#define PIC16_PCLATH 0xFFA
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// processor types
|
||||
|
||||
typedef uchar proctype_t;
|
||||
|
||||
const proctype_t PIC12 = 0;
|
||||
const proctype_t PIC14 = 1;
|
||||
const proctype_t PIC16 = 2;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
inline bool is_bit_insn(const insn_t &insn)
|
||||
{
|
||||
return insn.itype >= PIC_bcf && insn.itype <= PIC_btfss
|
||||
|| insn.itype >= PIC_bcf3 && insn.itype <= PIC_btg3;
|
||||
}
|
||||
|
||||
ea_t calc_code_mem(const insn_t &insn, ea_t ea);
|
||||
int calc_outf(const op_t &x);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void interr(const char *module);
|
||||
|
||||
void idaapi pic_segend(outctx_t &ctx, segment_t *seg);
|
||||
|
||||
int idaapi is_align_insn(ea_t ea);
|
||||
|
||||
int idaapi is_jump_func(const func_t *pfn, ea_t *jump_target);
|
||||
int idaapi is_sane_insn(int nocrefs);
|
||||
int idaapi may_be_func(void); // can a function start here?
|
||||
|
||||
//------------------------------------------------------------------
|
||||
struct pic_iohandler_t : public iohandler_t
|
||||
{
|
||||
struct pic_t ±
|
||||
pic_iohandler_t(pic_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {}
|
||||
virtual void get_cfg_filename(char *buf, size_t bufsize) override;
|
||||
virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override;
|
||||
};
|
||||
|
||||
struct pic_t : public procmod_t
|
||||
{
|
||||
pic_iohandler_t ioh = pic_iohandler_t(*this, helper);
|
||||
|
||||
netnode helper;
|
||||
ea_t dataseg = BADADDR;
|
||||
int sav_respect_info = IORESP_NONE;
|
||||
|
||||
inline void save_idpflags() { helper.altset(-1, idpflags); }
|
||||
inline void save_dataseg() { helper.altset(0, ea2node(dataseg)); }
|
||||
|
||||
#define IDP_SIMPLIFY 0x0001 // simplify instructions
|
||||
ushort idpflags = IDP_SIMPLIFY;
|
||||
inline bool dosimple(void)
|
||||
{ // if macros are enabled, we should simplify insns
|
||||
return inf_macros_enabled() || (idpflags & IDP_SIMPLIFY) != 0;
|
||||
}
|
||||
|
||||
proctype_t ptype = PIC12;
|
||||
const char *cfgname = "pic12.cfg";
|
||||
bool set = false;
|
||||
bool flow = false;
|
||||
|
||||
struct portmap_t
|
||||
{
|
||||
ea_t from;
|
||||
ea_t to;
|
||||
};
|
||||
qvector<portmap_t> map;
|
||||
|
||||
virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override;
|
||||
|
||||
void create_mappings(void);
|
||||
void load_symbols_without_infotype(int _respect_info);
|
||||
void load_symbols(int _respect_info);
|
||||
const char *find_sym(ea_t address);
|
||||
const ioport_bits_t *find_bits(ea_t address);
|
||||
const char *find_bit(ea_t address, int bit);
|
||||
void apply_symbols(void);
|
||||
void setup_device(int lrespect_info);
|
||||
ea_t AdditionalSegment(size_t size, ea_t offset, const char *name) const;
|
||||
const char *set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded);
|
||||
void set_cpu(int n);
|
||||
void free_mappings(void);
|
||||
void add_mapping(ea_t from, ea_t to);
|
||||
ea_t map_port(ea_t from);
|
||||
void check_pclath(segment_t *s) const;
|
||||
|
||||
bool build_macro(insn_t &insn, bool may_go_forward);
|
||||
void simplify(insn_t &insn) const;
|
||||
int basic_ana(insn_t &insn);
|
||||
int ana(insn_t *_insn);
|
||||
|
||||
bool is_banked_reg(ea_t addr, int value) const;
|
||||
bool is_pcl(const insn_t &insn) const;
|
||||
bool is_bank(const insn_t &insn) const;
|
||||
bool is_pclath(const insn_t &insn) const;
|
||||
void process_immediate_number(const insn_t &insn, int n) const;
|
||||
void destroy_if_unnamed_array(ea_t ea) const;
|
||||
void propagate_sreg(const insn_t &insn, ea_t ea, int reg) const;
|
||||
void handle_operand(const insn_t &insn, const op_t &x, int, bool isload);
|
||||
void split(const insn_t &insn, int reg, sel_t v);
|
||||
bool is_load_tris_reg(const insn_t &insn);
|
||||
inline void set_plain_offset(ea_t insn_ea, int n, ea_t base) const;
|
||||
int emu(const insn_t &insn);
|
||||
bool create_func_frame(func_t *pfn) const;
|
||||
|
||||
void pic_header(outctx_t &ctx);
|
||||
int out_equ(outctx_t &ctx);
|
||||
void out_equ(outctx_t &ctx, bool indent, const char *name, uval_t off);
|
||||
void pic_data(outctx_t &ctx, bool analyze_only);
|
||||
ea_t calc_data_mem(ea_t ea);
|
||||
bool conditional_insn(const insn_t &insn, flags_t F) const; // may instruction be skipped?
|
||||
void print_segment_register(outctx_t &ctx, int reg, sel_t value);
|
||||
void pic_assumes(outctx_t &ctx); // function to produce assume directives
|
||||
void pic_segstart(outctx_t &ctx, segment_t *Srange) const;
|
||||
void pic_footer(outctx_t &ctx) const;
|
||||
|
||||
void load_from_idb();
|
||||
};
|
||||
extern int data_id;
|
||||
#endif // _PIC_HPP
|
||||
2353
idasdk76/module/pic/pic12.cfg
Normal file
2353
idasdk76/module/pic/pic12.cfg
Normal file
File diff suppressed because it is too large
Load Diff
334764
idasdk76/module/pic/pic14.cfg
Normal file
334764
idasdk76/module/pic/pic14.cfg
Normal file
File diff suppressed because it is too large
Load Diff
644
idasdk76/module/pic/pic16.cfg
Normal file
644
idasdk76/module/pic/pic16.cfg
Normal file
@@ -0,0 +1,644 @@
|
||||
;
|
||||
; This file defines SFR names and bit names for Microchip's PIC 16 bit processors.
|
||||
;
|
||||
; This file can be configured for different devices.
|
||||
; At the beginning of the file there are definitions common for all devices
|
||||
; Device-specific definitions are introduced by
|
||||
;
|
||||
; .devicename
|
||||
;
|
||||
; line. Also an optional directive
|
||||
;
|
||||
; .default devicename
|
||||
;
|
||||
; designates the default device name.
|
||||
;
|
||||
|
||||
.default 18F2520
|
||||
|
||||
; common FSR definitions
|
||||
|
||||
TOSU 0xFFF
|
||||
TOSH 0xFFE
|
||||
TOSL 0xFFD
|
||||
STKPTR 0xFFC
|
||||
STKPTR.STKFUL 7
|
||||
STKPTR.STKUNF 6
|
||||
STKPTR.SP4 4
|
||||
STKPTR.SP3 3
|
||||
STKPTR.SP2 2
|
||||
STKPTR.SP1 1
|
||||
STKPTR.SP0 0
|
||||
PCLATU 0xFFB
|
||||
PCLATH 0xFFA
|
||||
PCL 0xFF9
|
||||
TBLPTRU 0xFF8
|
||||
TBLPTRH 0xFF7
|
||||
TBLPTRL 0xFF6
|
||||
TABLAT 0xFF5
|
||||
PRODH 0xFF4
|
||||
PRODL 0xFF3
|
||||
INTCON 0xFF2
|
||||
INTCON.GIE_GIEH 7
|
||||
INTCON.PEIE_GIEL 6
|
||||
INTCON.TMR0IE 5
|
||||
INTCON.INT0IE 4
|
||||
INTCON.RBIE 3
|
||||
INTCON.TMR0IF 2
|
||||
INTCON.INT0IF 1
|
||||
INTCON.RBIF 0
|
||||
INTCON2 0xFF1
|
||||
INTCON2.RBPU 7
|
||||
INTCON2.INTEDG0 6
|
||||
INTCON2.INTEDG1 5
|
||||
INTCON2.INTEDG2 4
|
||||
INTCON2.TMR0IP 2
|
||||
INTCON2.RBIP 0
|
||||
INTCON3 0xFF0
|
||||
INTCON3.INT2IP 7
|
||||
INTCON3.INT1IP 6
|
||||
INTCON3.INT2IE 4
|
||||
INTCON3.INT1IE 3
|
||||
INTCON3.INT2IF 1
|
||||
INTCON3.INT1IF 0
|
||||
INDF0 0xFEF
|
||||
POSTINC0 0xFEE
|
||||
POSTDEC0 0xFED
|
||||
PREINC0 0xFEC
|
||||
PLUSW0 0xFEB
|
||||
FSR0H 0xFEA
|
||||
FSR0L 0xFE9
|
||||
WREG 0xFE8
|
||||
INDF1 0xFE7
|
||||
POSTINC1 0xFE6
|
||||
POSTDEC1 0xFE5
|
||||
PREINC1 0xFE4
|
||||
PLUSW1 0xFE3
|
||||
FSR1H 0xFE2
|
||||
FSR1L 0xFE1
|
||||
BSR 0xFE0
|
||||
INDF2 0xFDF
|
||||
POSTINC2 0xFDE
|
||||
POSTDEC2 0xFDD
|
||||
PREINC2 0xFDC
|
||||
PLUSW2 0xFDB
|
||||
FSR2H 0xFDA
|
||||
FSR2L 0xFD9
|
||||
STATUS 0xFD8
|
||||
STATUS.N 4
|
||||
STATUS.OV 3
|
||||
STATUS.Z 2
|
||||
STATUS.DC 1
|
||||
STATUS.C 0
|
||||
TMR0H 0xFD7
|
||||
TMR0L 0xFD6
|
||||
T0CON 0xFD5
|
||||
T0CON.TMR0ON 7
|
||||
T0CON.T08BIT 6
|
||||
T0CON.T0CS 5
|
||||
T0CON.T0SE 4
|
||||
T0CON.PSA 3
|
||||
T0CON.T0PS2 2
|
||||
T0CON.T0PS1 1
|
||||
T0CON.T0PS0 0
|
||||
OSCCON 0xFD3
|
||||
OSCCON.IDLEN 7
|
||||
OSCCON.IRCF2 6
|
||||
OSCCON.IRCF1 5
|
||||
OSCCON.IRCF0 4
|
||||
OSCCON.OSTS 3
|
||||
OSCCON.IOFS 2
|
||||
OSCCON.SCS1 1
|
||||
OSCCON.SCS0 0
|
||||
HLVDCON 0xFD2
|
||||
HLVDCON.VDIRMAG 7
|
||||
HLVDCON.IRVST 5
|
||||
HLVDCON.HLVDEN 4
|
||||
HLVDCON.HLVDL3 3
|
||||
HLVDCON.HLVDL2 2
|
||||
HLVDCON.HLVDL1 1
|
||||
HLVDCON.HLVDL0 0
|
||||
WDTCON 0xFD1
|
||||
WDTCON.SWDTEN 0
|
||||
RCON 0xFD0
|
||||
RCON.IPEN 7
|
||||
RCON.SBOREN 6
|
||||
RCON.RI 4
|
||||
RCON.TO 3
|
||||
RCON.PD 2
|
||||
RCON.POR 1
|
||||
RCON.BOR 0
|
||||
TMR1H 0xFCF
|
||||
TMR1L 0xFCE
|
||||
T1CON 0xFCD
|
||||
T1CON.RD16 7
|
||||
T1CON.T1RUN 6
|
||||
T1CON.T1CKPS1 5
|
||||
T1CON.T1CKPS0 4
|
||||
T1CON.T1OSCEN 3
|
||||
T1CON.T1SYNC 2
|
||||
T1CON.TMR1CS 1
|
||||
T1CON.TMR1ON 0
|
||||
TMR2 0xFCC
|
||||
PR2 0xFCB
|
||||
T2CON 0xFCA
|
||||
T2CON.T2OUTPS3 6
|
||||
T2CON.T2OUTPS2 5
|
||||
T2CON.T2OUTPS1 4
|
||||
T2CON.T2OUTPS0 3
|
||||
T2CON.TMR2ON 2
|
||||
T2CON.T2CKPS1 1
|
||||
T2CON.T2CKPS0 0
|
||||
SSPBUF 0xFC9
|
||||
SSPADD 0xFC8
|
||||
SSPSTAT 0xFC7
|
||||
SSPSTAT.SMP 7
|
||||
SSPSTAT.CKE 6
|
||||
SSPSTAT.D_A 5
|
||||
SSPSTAT.P 4
|
||||
SSPSTAT.S 3
|
||||
SSPSTAT.R_W 2
|
||||
SSPSTAT.UA 1
|
||||
SSPSTAT.BF 0
|
||||
SSPCON1 0xFC6
|
||||
SSPCON1.WCOL 7
|
||||
SSPCON1.SSPOV 6
|
||||
SSPCON1.SSPEN 5
|
||||
SSPCON1.CKP 4
|
||||
SSPCON1.SSPM3 3
|
||||
SSPCON1.SSPM2 2
|
||||
SSPCON1.SSPM1 1
|
||||
SSPCON1.SSPM0 0
|
||||
SSPCON2 0xFC5
|
||||
SSPCON2.GCEN 7
|
||||
SSPCON2.ACKSTAT 6
|
||||
SSPCON2.ACKDT 5
|
||||
SSPCON2.ACKEN 4
|
||||
SSPCON2.RCEN 3
|
||||
SSPCON2.PEN 2
|
||||
SSPCON2.RSEN 1
|
||||
SSPCON2.SEN 0
|
||||
ADRESH 0xFC4
|
||||
ADRESL 0xFC3
|
||||
ADCON0 0xFC2
|
||||
ADCON0.CHS3 5
|
||||
ADCON0.CHS2 4
|
||||
ADCON0.CHS1 3
|
||||
ADCON0.CHS0 2
|
||||
ADCON0.GO_DONE 1
|
||||
ADCON0.ADON 0
|
||||
ADCON1 0xFC1
|
||||
ADCON1.VCFG1 5
|
||||
ADCON1.VCFG0 4
|
||||
ADCON1.PCFG3 3
|
||||
ADCON1.PCFG2 2
|
||||
ADCON1.PCFG1 1
|
||||
ADCON1.PCFG0 0
|
||||
ADCON2 0xFC0
|
||||
ADCON2.ADFM 7
|
||||
ADCON2.ACQT2 5
|
||||
ADCON2.ACQT1 4
|
||||
ADCON2.ACQT0 3
|
||||
ADCON2.ADCS2 2
|
||||
ADCON2.ADCS1 1
|
||||
ADCON2.ADCS0 0
|
||||
CCPR1H 0xFBF
|
||||
CCPR1L 0xFBE
|
||||
CCP1CON 0xFBD
|
||||
CCP1CON.P1M1 7
|
||||
CCP1CON.P1M0 6
|
||||
CCP1CON.DC1B1 5
|
||||
CCP1CON.DC1B0 4
|
||||
CCP1CON.CCP1M3 3
|
||||
CCP1CON.CCP1M2 2
|
||||
CCP1CON.CCP1M1 1
|
||||
CCP1CON.CCP1M0 0
|
||||
CCPR2H 0xFBC
|
||||
CCPR2L 0xFBB
|
||||
CCP2CON 0xFBA
|
||||
CCP2CON.DC2B1 5
|
||||
CCP2CON.DC2B0 4
|
||||
CCP2CON.CCP2M3 3
|
||||
CCP2CON.CCP2M2 2
|
||||
CCP2CON.CCP2M1 1
|
||||
CCP2CON.CCP2M0 0
|
||||
BAUDCON 0xFB8
|
||||
BAUDCON.ABDOVF 7
|
||||
BAUDCON.RCIDL 6
|
||||
BAUDCON.SCKP 4
|
||||
BAUDCON.BRG16 3
|
||||
BAUDCON.WUE 1
|
||||
BAUDCON.ABDEN 0
|
||||
PWM1CON 0xFB7
|
||||
PWM1CON.PRSEN 7
|
||||
PWM1CON.PDC6 6
|
||||
PWM1CON.PDC5 5
|
||||
PWM1CON.PDC4 4
|
||||
PWM1CON.PDC3 3
|
||||
PWM1CON.PDC2 2
|
||||
PWM1CON.PDC1 1
|
||||
PWM1CON.PDC0 0
|
||||
ECCP1AS 0xFB6
|
||||
ECCP1AS.ECCPASE 7
|
||||
ECCP1AS.ECCPAS2 6
|
||||
ECCP1AS.ECCPAS1 5
|
||||
ECCP1AS.ECCPAS0 4
|
||||
ECCP1AS.PSSAC1 3
|
||||
ECCP1AS.PSSAC0 2
|
||||
ECCP1AS.PSSBD1 1
|
||||
ECCP1AS.PSSBD0 0
|
||||
CVRCON 0xFB5
|
||||
CVRCON.CVREN 7
|
||||
CVRCON.CVROE 6
|
||||
CVRCON.CVRR 5
|
||||
CVRCON.CVRSS 4
|
||||
CVRCON.CVR3 3
|
||||
CVRCON.CVR2 2
|
||||
CVRCON.CVR1 1
|
||||
CVRCON.CVR0 0
|
||||
CMCON 0xFB4
|
||||
CMCON.C2OUT 7
|
||||
CMCON.C1OUT 6
|
||||
CMCON.C2INV 5
|
||||
CMCON.C1INV 4
|
||||
CMCON.CIS 3
|
||||
CMCON.CM2 2
|
||||
CMCON.CM1 1
|
||||
CMCON.CM0 0
|
||||
TMR3H 0xFB3
|
||||
TMR3L 0xFB2
|
||||
T3CON 0xFB1
|
||||
T3CON.RD16 7
|
||||
T3CON.T3CCP2 6
|
||||
T3CON.T3CKPS1 5
|
||||
T3CON.T3CKPS0 4
|
||||
T3CON.T3CCP1 3
|
||||
T3CON.T3SYNC 2
|
||||
T3CON.TMR3CS 1
|
||||
T3CON.TMR3ON 0
|
||||
SPBRGH 0xFB0
|
||||
SPBRG 0xFAF
|
||||
RCREG 0xFAE
|
||||
TXREG 0xFAD
|
||||
TXSTA 0xFAC
|
||||
TXSTA.CSRC 7
|
||||
TXSTA.TX9 6
|
||||
TXSTA.TXEN 5
|
||||
TXSTA.SYNC 4
|
||||
TXSTA.SENDB 3
|
||||
TXSTA.BRGH 2
|
||||
TXSTA.TRMT 1
|
||||
TXSTA.TX9D 0
|
||||
RCSTA 0xFAB
|
||||
RCSTA.SPEN 7
|
||||
RCSTA.RX9 6
|
||||
RCSTA.SREN 5
|
||||
RCSTA.CREN 4
|
||||
RCSTA.ADDEN 3
|
||||
RCSTA.FERR 2
|
||||
RCSTA.OERR 1
|
||||
RCSTA.RX9D 0
|
||||
EEADRH 0xFAA
|
||||
EEADR 0xFA9
|
||||
EEDATA 0xFA8
|
||||
EECON2 0xFA7
|
||||
EECON1 0xFA6
|
||||
EECON1.EEPGD 7
|
||||
EECON1.CFGS 6
|
||||
EECON1.FREE 4
|
||||
EECON1.WRERR 3
|
||||
EECON1.WREN 2
|
||||
EECON1.WR 1
|
||||
EECON1.RD 0
|
||||
IPR3 0xFA5
|
||||
PIR3 0xFA4
|
||||
PIE3 0xFA3
|
||||
IPR2 0xFA2
|
||||
IPR2.OSCFIP 7
|
||||
IPR2.CMIP 6
|
||||
IPR2.EEIP 4
|
||||
IPR2.BCLIP 3
|
||||
IPR2.HLVDIP 2
|
||||
IPR2.TMR3IP 1
|
||||
IPR2.CCP2IP 0
|
||||
PIR2 0xFA1
|
||||
PIR2.OSCFIF 7
|
||||
PIR2.CMIF 6
|
||||
PIR2.EEIF 4
|
||||
PIR2.BCLIF 3
|
||||
PIR2.HLVDIF 2
|
||||
PIR2.TMR3IF 1
|
||||
PIR2.CCP2IF 0
|
||||
PIE2 0xFA0
|
||||
PIE2.OSCFIE 7
|
||||
PIE2.CMIE 6
|
||||
PIE2.EEIE 4
|
||||
PIE2.BCLIE 3
|
||||
PIE2.HLVDIE 2
|
||||
PIE2.TMR3IE 1
|
||||
PIE2.CCP2IE 0
|
||||
IPR1 0xF9F
|
||||
IPR1.PSPIP 7
|
||||
IPR1.ADIP 6
|
||||
IPR1.RCIP 5
|
||||
IPR1.TXIP 4
|
||||
IPR1.SSPIP 3
|
||||
IPR1.CCP1IP 2
|
||||
IPR1.TMR2IP 1
|
||||
IPR1.TMR1IP 0
|
||||
PIR1 0xF9E
|
||||
PIR1.PSPIF 7
|
||||
PIR1.ADIF 6
|
||||
PIR1.RCIF 5
|
||||
PIR1.TXIF 4
|
||||
PIR1.SSPIF 3
|
||||
PIR1.CCP1IF 2
|
||||
PIR1.TMR2IF 1
|
||||
PIR1.TMR1IF 0
|
||||
PIE1 0xF9D
|
||||
PIE1.PSPIE 7
|
||||
PIE1.ADIE 6
|
||||
PIE1.RCIE 5
|
||||
PIE1.TXIE 4
|
||||
PIE1.SSPIE 3
|
||||
PIE1.CCP1IE 2
|
||||
PIE1.TMR2IE 1
|
||||
PIE1.TMR1IE 0
|
||||
MEMCON 0xF9C
|
||||
OSCTUNE 0xF9B
|
||||
OSCTUNE.INTSRC 7
|
||||
OSCTUNE.PLLEN 6
|
||||
OSCTUNE.TUN4 4
|
||||
OSCTUNE.TUN3 3
|
||||
OSCTUNE.TUN2 2
|
||||
OSCTUNE.TUN1 1
|
||||
OSCTUNE.TUN0 0
|
||||
TRISJ 0xF9A
|
||||
TRISH 0xF99
|
||||
TRISG 0xF98
|
||||
TRISF 0xF97
|
||||
TRISE 0xF96
|
||||
TRISE.IBF 7
|
||||
TRISE.OBF 6
|
||||
TRISE.IBOV 5
|
||||
TRISE.PSPMODE 4
|
||||
TRISE.TRISE2 2
|
||||
TRISE.TRISE1 1
|
||||
TRISE.TRISE0 0
|
||||
TRISD 0xF95
|
||||
TRISC 0xF94
|
||||
TRISB 0xF93
|
||||
TRISA 0xF92
|
||||
LATJ 0xF91
|
||||
LATH 0xF90
|
||||
LATG 0xF8F
|
||||
LATF 0xF8E
|
||||
LATE 0xF8D
|
||||
LATD 0xF8C
|
||||
LATC 0xF8B
|
||||
LATB 0xF8A
|
||||
LATA 0xF89
|
||||
PORTJ 0xF88
|
||||
PORTH 0xF87
|
||||
PORTG 0xF86
|
||||
PORTF 0xF85
|
||||
PORTE 0xF84
|
||||
PORTE.RE3 3
|
||||
PORTE.RE2 2
|
||||
PORTE.RE1 1
|
||||
PORTE.RE0 0
|
||||
PORTD 0xF83
|
||||
PORTD.RD7 7
|
||||
PORTD.RD6 6
|
||||
PORTD.RD5 5
|
||||
PORTD.RD4 4
|
||||
PORTD.RD3 3
|
||||
PORTD.RD2 2
|
||||
PORTD.RD1 1
|
||||
PORTD.RD0 0
|
||||
PORTC 0xF82
|
||||
PORTC.RC7 7
|
||||
PORTC.RC6 6
|
||||
PORTC.RC5 5
|
||||
PORTC.RC4 4
|
||||
PORTC.RC3 3
|
||||
PORTC.RC2 2
|
||||
PORTC.RC1 1
|
||||
PORTC.RC0 0
|
||||
PORTB 0xF81
|
||||
PORTB.RB7 7
|
||||
PORTB.RB6 6
|
||||
PORTB.RB5 5
|
||||
PORTB.RB4 4
|
||||
PORTB.RB3 3
|
||||
PORTB.RB2 2
|
||||
PORTB.RB1 1
|
||||
PORTB.RB0 0
|
||||
PORTA 0xF80
|
||||
PORTA.RA7 7
|
||||
PORTA.RA6 6
|
||||
PORTA.RA5 5
|
||||
PORTA.RA4 4
|
||||
PORTA.RA3 3
|
||||
PORTA.RA2 2
|
||||
PORTA.RA1 1
|
||||
PORTA.RA0 0
|
||||
|
||||
; Interrupt and reset vector assignments
|
||||
entry RESET 0x0000 RESET
|
||||
entry HI_ISR 0x0008 High-Priority Interrupt
|
||||
entry LO_ISR 0x0018 Low-Priority Interrupt
|
||||
|
||||
; http://ww1.microchip.com/downloads/en/DeviceDoc/39631a.pdf
|
||||
; PIC18F2420/2520/4420/4520
|
||||
|
||||
.18F2520
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x8000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0600 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
; http://ww1.microchip.com/downloads/en/DeviceDoc/39626e.pdf
|
||||
; PIC18F2525/2620/4525/4620
|
||||
|
||||
.18F2525
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x6000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F80 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F4525
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x6000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F80 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F2620
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x8000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F80 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F4620
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x8000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F80 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F2455
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x6000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0800 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F2550
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x8000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0800 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F4455
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x6000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0800 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
.18F4550
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x8000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0800 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F80:0x1000 Function Special Registers
|
||||
|
||||
; http://ww1.microchip.com/downloads/en/DeviceDoc/39761c.pdf
|
||||
; PIC18F2682/2685/4682/4685
|
||||
|
||||
.18F2682
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x14000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA FSR_ 0x0D00:0x1000 Function Special Registers
|
||||
|
||||
.18F2685
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x18000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA FSR_ 0x0D00:0x1000 Function Special Registers
|
||||
|
||||
.18F4682
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x14000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA FSR_ 0x0D00:0x1000 Function Special Registers
|
||||
|
||||
.18F4685
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x18000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA FSR_ 0x0D00:0x1000 Function Special Registers
|
||||
|
||||
; http://ww1.microchip.com/downloads/en/DeviceDoc/39646c.pdf
|
||||
; PIC18F6527/18F6622/18F6627/18F6722/18F8527/18F8622/18F8627/18F8722
|
||||
|
||||
.18F6722
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x200000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8722
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x200000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F6627
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x180000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8627
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x180000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F6622
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x10000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8622
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x10000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F6527
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0xC000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8527
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0xC000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0F60 SRAM Data Memory
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
; http://ww1.microchip.com/downloads/en/DeviceDoc/30491c.pdf
|
||||
; PIC18F6585/8585/6680/8680
|
||||
|
||||
.18F6585
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0xC000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA CANFSR 0x0D00:0x0F60 Function Special Registers
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8585
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0xC000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA CANFSR 0x0D00:0x0F60 Function Special Registers
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F6680
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x10000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA CANFSR 0x0D00:0x0F60 Function Special Registers
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
|
||||
.18F8680
|
||||
|
||||
; MEMORY MAP
|
||||
area CODE ROM 0x0000:0x10000 On-chip Program Memory
|
||||
area DATA RAM 0x0000:0x0D00 SRAM Data Memory
|
||||
area DATA CANFSR 0x0D00:0x0F60 Function Special Registers
|
||||
area DATA FSR_ 0x0F60:0x1000 Function Special Registers
|
||||
747
idasdk76/module/pic/reg.cpp
Normal file
747
idasdk76/module/pic/reg.cpp
Normal file
@@ -0,0 +1,747 @@
|
||||
/*
|
||||
* Interactive disassembler (IDA).
|
||||
* Copyright (c) 1990-99 by Ilfak Guilfanov.
|
||||
* ALL RIGHTS RESERVED.
|
||||
* E-mail: ig@datarescue.com
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include "pic.hpp"
|
||||
#include <diskio.hpp>
|
||||
#include <segregs.hpp>
|
||||
int data_id;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const char *const register_names_pic12[] =
|
||||
{
|
||||
"w", "f",
|
||||
"ACCESS", // register for PIC18Cxx
|
||||
"BANKED", // register for PIC18Cxx
|
||||
"FAST", // register for PIC18Cxx
|
||||
"FSR0", // register for PIC18Cxx
|
||||
"FSR1", // register for PIC18Cxx
|
||||
"FSR2", // register for PIC18Cxx
|
||||
"bank",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"status",
|
||||
"pclatu" // register for PIC18Cxx
|
||||
};
|
||||
|
||||
static const char *const register_names_pic14[] =
|
||||
{
|
||||
"w", "f",
|
||||
"ACCESS", // register for PIC18Cxx
|
||||
"BANKED", // register for PIC18Cxx
|
||||
"FAST", // register for PIC18Cxx
|
||||
"FSR0", // register for PIC18Cxx
|
||||
"FSR1", // register for PIC18Cxx
|
||||
"FSR2", // register for PIC18Cxx
|
||||
"bank",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"pclath",
|
||||
"pclatu" // register for PIC18Cxx
|
||||
};
|
||||
|
||||
static const char *const register_names_pic16[] =
|
||||
{
|
||||
"w", "f",
|
||||
"ACCESS", // register for PIC18Cxx
|
||||
"BANKED", // register for PIC18Cxx
|
||||
"FAST", // register for PIC18Cxx
|
||||
"FSR0", // register for PIC18Cxx
|
||||
"FSR1", // register for PIC18Cxx
|
||||
"FSR2", // register for PIC18Cxx
|
||||
"bsr",
|
||||
"cs","ds", // virtual registers for code and data segments
|
||||
"pclath",
|
||||
"pclatu" // register for PIC18Cxx
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// 11 01xx kkkk kkkk RETLW k Return with literal in W
|
||||
static const uchar retcode_0[] = { 0x08, 0x00 }; // return
|
||||
static const uchar retcode_1[] = { 0x09, 0x00 }; // retfie
|
||||
static const uchar retcode_2[] = { 0x00, 0x34 }; // retlw 0
|
||||
static const uchar retcode_3[] = { 0x01, 0x34 }; // retlw 1
|
||||
|
||||
static const bytes_t retcodes[] =
|
||||
{
|
||||
{ sizeof(retcode_0), retcode_0 },
|
||||
{ sizeof(retcode_1), retcode_1 },
|
||||
{ sizeof(retcode_2), retcode_2 },
|
||||
{ sizeof(retcode_3), retcode_3 },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Microchip's MPALC
|
||||
//-----------------------------------------------------------------------
|
||||
static const asm_t mpalc =
|
||||
{
|
||||
ASH_HEXF2|ASD_DECF3|ASB_BINF5|ASO_OCTF5|AS_N2CHR|AS_NCMAS|AS_ONEDUP,
|
||||
0,
|
||||
"Microchip's MPALC",
|
||||
0,
|
||||
NULL, // header lines
|
||||
"org", // org
|
||||
"end", // end
|
||||
|
||||
";", // comment string
|
||||
'"', // string delimiter
|
||||
'\'', // char delimiter
|
||||
"'\"", // special symbols in char and string constants
|
||||
|
||||
"data", // ascii string directive
|
||||
"byte", // byte directive
|
||||
"data", // word directive
|
||||
NULL, // double words
|
||||
NULL, // qwords
|
||||
NULL, // oword (16 bytes)
|
||||
NULL, // float (4 bytes)
|
||||
NULL, // double (8 bytes)
|
||||
NULL, // tbyte (10/12 bytes)
|
||||
NULL, // packed decimal real
|
||||
NULL, // arrays (#h,#d,#v,#s(...)
|
||||
"res %s", // uninited arrays
|
||||
"equ", // equ
|
||||
NULL, // 'seg' prefix (example: push seg seg001)
|
||||
"$", // current IP (instruction pointer)
|
||||
NULL, // func_header
|
||||
NULL, // func_footer
|
||||
NULL, // "public" name keyword
|
||||
NULL, // "weak" name keyword
|
||||
NULL, // "extrn" name keyword
|
||||
NULL, // "comm" (communal variable)
|
||||
NULL, // get_type_name
|
||||
NULL, // "align" keyword
|
||||
'(', ')', // lbrace, rbrace
|
||||
"%", // mod
|
||||
"&", // and
|
||||
"|", // or
|
||||
"^", // xor
|
||||
"~", // not
|
||||
"<<", // shl
|
||||
">>", // shr
|
||||
NULL, // sizeof
|
||||
};
|
||||
|
||||
static const asm_t *const asms[] = { &mpalc, NULL };
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::free_mappings(void)
|
||||
{
|
||||
map.clear();
|
||||
}
|
||||
|
||||
void pic_t::add_mapping(ea_t from, ea_t to)
|
||||
{
|
||||
if ( from != to )
|
||||
{
|
||||
deb(IDA_DEBUG_IDP, "add_mapping %a -> %a\n", from, to);
|
||||
portmap_t &p = map.push_back();
|
||||
p.from = from;
|
||||
p.to = to;
|
||||
}
|
||||
}
|
||||
|
||||
ea_t pic_t::map_port(ea_t from)
|
||||
{
|
||||
for ( int i=0; i < map.size(); i++ )
|
||||
if ( map[i].from == from )
|
||||
return map[i].to;
|
||||
return from;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_iohandler_t::get_cfg_filename(char *buf, size_t bufsize)
|
||||
{
|
||||
qstrncpy(buf, pm.cfgname, bufsize);
|
||||
}
|
||||
|
||||
// create the mapping table
|
||||
void pic_t::create_mappings(void)
|
||||
{
|
||||
free_mappings();
|
||||
for ( int i=0; i < ioh.ports.size(); i++ )
|
||||
{
|
||||
const char *name = ioh.ports[i].name.c_str();
|
||||
ea_t nameea = get_name_ea(BADADDR, name);
|
||||
if ( nameea != BADADDR && nameea > dataseg )
|
||||
add_mapping(ioh.ports[i].address, nameea-dataseg);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
static ea_t AddSegment(ea_t start, size_t size, ea_t base, const char *name, uchar type)
|
||||
{
|
||||
segment_t s;
|
||||
s.start_ea = start;
|
||||
s.end_ea = start + size;
|
||||
s.sel = allocate_selector(base >> 4);
|
||||
s.type = type;
|
||||
s.align = saRelByte;
|
||||
s.comb = scPub;
|
||||
add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_OR_DIE);
|
||||
return s.start_ea;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// special handling for 16-bit PICs
|
||||
// for CODE segments use addresses as-is
|
||||
// for DATA segments, start from dataseg base
|
||||
bool pic_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass)
|
||||
{
|
||||
if ( pm.ptype != PIC16 )
|
||||
return false;
|
||||
if ( strcmp(aclass, "CODE") == 0 )
|
||||
{
|
||||
AddSegment(start, end-start, 0, name, SEG_CODE);
|
||||
}
|
||||
else if ( strcmp(aclass, "DATA") == 0 )
|
||||
{
|
||||
if ( pm.dataseg == BADADDR )
|
||||
{
|
||||
pm.dataseg = free_chunk(0, 0x1000, -0xF);
|
||||
pm.save_dataseg();
|
||||
}
|
||||
uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA;
|
||||
AddSegment(pm.dataseg + start, end-start, pm.dataseg, name, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void pic_t::load_symbols_without_infotype(int _respect_info)
|
||||
{
|
||||
ioh.ports.clear();
|
||||
ioh.respect_info = _respect_info;
|
||||
iohandler_t::ioports_loader_t ldr(&ioh);
|
||||
read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr);
|
||||
create_mappings();
|
||||
}
|
||||
|
||||
void pic_t::load_symbols(int _respect_info)
|
||||
{
|
||||
if ( ioh.display_infotype_dialog(IORESP_ALL, &_respect_info, cfgname) )
|
||||
load_symbols_without_infotype(_respect_info);
|
||||
}
|
||||
|
||||
const char *pic_t::find_sym(ea_t address)
|
||||
{
|
||||
const ioport_t *port = find_ioport(ioh.ports, address);
|
||||
return port ? port->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
const ioport_bits_t *pic_t::find_bits(ea_t address)
|
||||
{
|
||||
const ioport_t *port = find_ioport(ioh.ports, address);
|
||||
return port ? (&port->bits) : NULL;
|
||||
}
|
||||
|
||||
const char *pic_t::find_bit(ea_t address, int bit)
|
||||
{
|
||||
address = map_port(address);
|
||||
const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit);
|
||||
return b ? b->name.c_str() : NULL;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pic_t::apply_symbols(void)
|
||||
{
|
||||
free_mappings();
|
||||
if ( dataseg != BADADDR )
|
||||
{
|
||||
for ( int i=0; i < ioh.ports.size(); i++ )
|
||||
{
|
||||
ea_t ea = calc_data_mem(ioh.ports[i].address);
|
||||
segment_t *s = getseg(ea);
|
||||
if ( s == NULL || s->type != SEG_IMEM )
|
||||
continue;
|
||||
create_byte(ea, 1);
|
||||
const char *name = ioh.ports[i].name.c_str();
|
||||
if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) )
|
||||
set_cmt(ea, name, 0);
|
||||
}
|
||||
for ( segment_t *d = getseg(dataseg); d != NULL; d = get_next_seg(d->start_ea) )
|
||||
{
|
||||
if ( d->type != SEG_IMEM )
|
||||
continue;
|
||||
ea_t ea = d->start_ea;
|
||||
ea_t dataend = d->end_ea;
|
||||
while ( 1 )
|
||||
{
|
||||
ea = next_unknown(ea, dataend);
|
||||
if ( ea == BADADDR )
|
||||
break;
|
||||
ea_t end = next_that(ea, dataend, f_is_head);
|
||||
if ( end == BADADDR )
|
||||
end = dataend;
|
||||
create_byte(ea, end-ea);
|
||||
}
|
||||
}
|
||||
create_mappings();
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
void pic_t::setup_device(int lrespect_info)
|
||||
{
|
||||
iohandler_t::parse_area_line0_t cb(ioh);
|
||||
if ( choose_ioport_device2(&ioh.device, cfgname, &cb) )
|
||||
{
|
||||
if ( ioh.device != NONEPROC )
|
||||
helper.supset(-1, ioh.device.c_str());
|
||||
// we don't pass IORESP_PORT because that would rename bytes in the code segment
|
||||
// we'll handle port renaming ourselves
|
||||
if ( ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgname) )
|
||||
{
|
||||
ioh.set_device_name(ioh.device.c_str(), lrespect_info & ~IORESP_PORT);
|
||||
if ( (lrespect_info & IORESP_PORT) != 0 )
|
||||
apply_symbols();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ea_t pic_t::AdditionalSegment(size_t size, ea_t offset, const char *name) const
|
||||
{
|
||||
ea_t start = free_chunk(0, size, -0xF);
|
||||
return AddSegment(start, size, start - offset, name, SEG_IMEM) - offset;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const proctype_t ptypes[] =
|
||||
{
|
||||
PIC12,
|
||||
PIC14,
|
||||
PIC16
|
||||
};
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
static const cfgopt_t options[] =
|
||||
{ // name varptr type/bit
|
||||
CFGOPT_B("PIC_SIMPLIFY", pic_t, idpflags, ushort(IDP_SIMPLIFY)),
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static const cfgopt_t *find_option(const char *name)
|
||||
{
|
||||
for ( int i=0; i < qnumber(options); i++ )
|
||||
if ( streq(options[i].name, name) )
|
||||
return &options[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int idaapi optionscb(int field_id, form_actions_t &fa)
|
||||
{
|
||||
// ensure that instruction simplification can't be turned off
|
||||
// if macros are enabled
|
||||
if ( field_id == CB_INIT )
|
||||
fa.enable_field(1, !inf_macros_enabled());
|
||||
return 1;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
static int idaapi choose_device(int, form_actions_t &fa)
|
||||
{
|
||||
pic_t &pm = *(pic_t *)fa.get_ud();
|
||||
if ( choose_ioport_device(&pm.ioh.device, pm.cfgname) )
|
||||
{
|
||||
pm.helper.supset(-1, pm.ioh.device.c_str());
|
||||
pm.load_symbols(IORESP_ALL);
|
||||
pm.apply_symbols();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *pic_t::set_idp_options(
|
||||
const char *keyword,
|
||||
int value_type,
|
||||
const void * value,
|
||||
bool idb_loaded)
|
||||
{
|
||||
if ( keyword == NULL )
|
||||
{
|
||||
if ( ptype != PIC16 )
|
||||
{
|
||||
static const char form[] =
|
||||
"HELP\n"
|
||||
"PIC specific options\n"
|
||||
"\n"
|
||||
" Simplify instructions\n"
|
||||
"\n"
|
||||
" If this option is on, IDA will simplify instructions and replace\n"
|
||||
" them by clearer macro-instructions\n"
|
||||
" For example,\n"
|
||||
"\n"
|
||||
" btfsc 3,0\n"
|
||||
"\n"
|
||||
" will be replaced by\n"
|
||||
"\n"
|
||||
" skpnc\n"
|
||||
"\n"
|
||||
" If macros are enabled, this options should be turned on.\n"
|
||||
"ENDHELP\n"
|
||||
"PIC specific options\n"
|
||||
"%/%*\n"
|
||||
" <~S~implify instructions:C1>>\n"
|
||||
"\n"
|
||||
" <~C~hoose device name:B:0::>\n"
|
||||
"\n"
|
||||
"\n";
|
||||
if ( inf_macros_enabled() )
|
||||
setflag(idpflags, IDP_SIMPLIFY, true);
|
||||
CASSERT(sizeof(idpflags) == sizeof(ushort));
|
||||
if ( ask_form(form, optionscb, this, &idpflags, choose_device) == ASKBTN_YES )
|
||||
{
|
||||
SAVE:
|
||||
if ( idb_loaded )
|
||||
save_idpflags();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
static const char form[] =
|
||||
"PIC specific options\n"
|
||||
"\n"
|
||||
" <~C~hoose device name:B:0::>\n"
|
||||
"\n"
|
||||
"\n";
|
||||
ask_form(form, choose_device);
|
||||
}
|
||||
return IDPOPT_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
const cfgopt_t *opt = find_option(keyword);
|
||||
if ( opt == NULL )
|
||||
return IDPOPT_BADKEY;
|
||||
const char *errmsg = opt->apply(value_type, value, this);
|
||||
if ( errmsg != IDPOPT_OK )
|
||||
return errmsg;
|
||||
// if macros are enabled, we should simplify insns
|
||||
if ( ph.supports_macros() && inf_macros_enabled() )
|
||||
setflag(idpflags, IDP_SIMPLIFY, true);
|
||||
goto SAVE;
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
void pic_t::set_cpu(int n)
|
||||
{
|
||||
if ( ptypes[n] != ptype )
|
||||
{
|
||||
ptype = ptypes[n];
|
||||
ph.cnbits = 12 + 2*n;
|
||||
}
|
||||
switch ( ptype )
|
||||
{
|
||||
case PIC12:
|
||||
ph.reg_names = register_names_pic12;
|
||||
cfgname = "pic12.cfg";
|
||||
break;
|
||||
case PIC14:
|
||||
ph.reg_names = register_names_pic14;
|
||||
cfgname = "pic14.cfg";
|
||||
break;
|
||||
case PIC16:
|
||||
ph.reg_names = register_names_pic16;
|
||||
cfgname = "pic16.cfg";
|
||||
ph.cnbits = 8;
|
||||
ph.reg_last_sreg = PCLATU;
|
||||
break;
|
||||
default:
|
||||
INTERR(10311);
|
||||
}
|
||||
setflag(ph.flag2, PR2_MACRO, ptype != PIC16);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pic_t::check_pclath(segment_t *s) const
|
||||
{
|
||||
if ( s == NULL )
|
||||
return;
|
||||
if ( s->defsr[PCLATH-ph.reg_first_sreg] == BADSEL )
|
||||
s->defsr[PCLATH-ph.reg_first_sreg] = 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
void pic_t::load_from_idb()
|
||||
{
|
||||
idpflags = (ushort)helper.altval(-1);
|
||||
dataseg = node2ea(helper.altval(0));
|
||||
ioh.upgrade_device_index();
|
||||
helper.supstr(&ioh.device, -1);
|
||||
load_symbols_without_infotype(IORESP_PORT);
|
||||
ioh.respect_info = sav_respect_info;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// This old-style callback only returns the processor module object.
|
||||
static ssize_t idaapi notify(void *, int msgid, va_list)
|
||||
{
|
||||
if ( msgid == processor_t::ev_get_procmod )
|
||||
return size_t(SET_MODULE_DATA(pic_t));
|
||||
return 0;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
ssize_t idaapi pic_t::on_event(ssize_t msgid, va_list va)
|
||||
{
|
||||
int code = 0;
|
||||
sav_respect_info = ioh.respect_info;
|
||||
switch ( msgid )
|
||||
{
|
||||
case processor_t::ev_init:
|
||||
helper.create(PROCMOD_NODE_NAME);
|
||||
break;
|
||||
|
||||
case processor_t::ev_term:
|
||||
free_mappings();
|
||||
ioh.ports.clear();
|
||||
clr_module_data(data_id);
|
||||
break;
|
||||
|
||||
case processor_t::ev_newfile: // new file loaded
|
||||
{
|
||||
segment_t *s0 = get_first_seg();
|
||||
if ( s0 != NULL )
|
||||
{
|
||||
ea_t firstEA = s0->start_ea;
|
||||
if ( ptype == PIC12 || ptype == PIC14 )
|
||||
{
|
||||
set_segm_name(s0, "CODE");
|
||||
dataseg = AdditionalSegment(0x200, 0, "DATA");
|
||||
setup_device(IORESP_INT|IORESP_PORT);
|
||||
}
|
||||
else
|
||||
{
|
||||
setup_device(IORESP_ALL);
|
||||
}
|
||||
s0 = getseg(firstEA);
|
||||
if ( s0 != NULL )
|
||||
{
|
||||
set_default_sreg_value(s0, BANK, 0);
|
||||
set_default_sreg_value(s0, PCLATH, 0);
|
||||
set_default_sreg_value(s0, PCLATU, 0);
|
||||
}
|
||||
segment_t *s1 = getseg(dataseg);
|
||||
if ( s1 != NULL )
|
||||
{
|
||||
set_default_sreg_value(s1, BANK, 0);
|
||||
set_default_sreg_value(s1, PCLATH, 0);
|
||||
set_default_sreg_value(s1, PCLATU, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// save info to idb
|
||||
save_dataseg();
|
||||
save_idpflags();
|
||||
break;
|
||||
|
||||
case processor_t::ev_ending_undo:
|
||||
set_cpu(ph.get_proc_index());
|
||||
ioh.respect_info = IORESP_NONE;
|
||||
//fall through
|
||||
case processor_t::ev_oldfile: // old file loaded
|
||||
load_from_idb();
|
||||
// init PCLATH for very old IDBs
|
||||
check_pclath(get_first_seg());
|
||||
check_pclath(getseg(dataseg));
|
||||
break;
|
||||
|
||||
case processor_t::ev_newprc: // new processor type
|
||||
{
|
||||
int n = va_arg(va, int);
|
||||
// bool keep_cfg = va_argi(va, bool);
|
||||
if ( set )
|
||||
return 0;
|
||||
set = true;
|
||||
set_cpu(n);
|
||||
}
|
||||
break;
|
||||
|
||||
case processor_t::ev_out_header:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
pic_header(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_footer:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
pic_footer(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segstart:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
pic_segstart(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_segend:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
segment_t *seg = va_arg(va, segment_t *);
|
||||
pic_segend(*ctx, seg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_assumes:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
pic_assumes(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_ana_insn:
|
||||
{
|
||||
insn_t *out = va_arg(va, insn_t *);
|
||||
return ana(out);
|
||||
}
|
||||
|
||||
case processor_t::ev_emu_insn:
|
||||
{
|
||||
const insn_t *insn = va_arg(va, const insn_t *);
|
||||
return emu(*insn) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_insn:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
out_insn(*ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_operand:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
const op_t *op = va_arg(va, const op_t *);
|
||||
return out_opnd(*ctx, *op) ? 1 : -1;
|
||||
}
|
||||
|
||||
case processor_t::ev_out_data:
|
||||
{
|
||||
outctx_t *ctx = va_arg(va, outctx_t *);
|
||||
bool analyze_only = va_argi(va, bool);
|
||||
pic_data(*ctx, analyze_only);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_is_sp_based:
|
||||
{
|
||||
int *mode = va_arg(va, int *);
|
||||
*mode = OP_SP_ADD | OP_FP_BASED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_create_func_frame:
|
||||
{
|
||||
func_t *pfn = va_arg(va, func_t *);
|
||||
create_func_frame(pfn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_get_frame_retsize:
|
||||
{
|
||||
int *frsize = va_arg(va, int *);
|
||||
*frsize = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
case processor_t::ev_set_idp_options:
|
||||
{
|
||||
const char *keyword = va_arg(va, const char *);
|
||||
int value_type = va_arg(va, int);
|
||||
const char *value = va_arg(va, const char *);
|
||||
const char **errmsg = va_arg(va, const char **);
|
||||
bool idb_loaded = va_argi(va, bool);
|
||||
const char *ret = set_idp_options(keyword, value_type, value, idb_loaded);
|
||||
if ( ret == IDPOPT_OK )
|
||||
return 1;
|
||||
if ( errmsg != NULL )
|
||||
*errmsg = ret;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
#define FAMILY "Microchip PIC:"
|
||||
static const char *const shnames[] =
|
||||
{ "PIC12Cxx",
|
||||
"PIC16Cxx",
|
||||
"PIC18Cxx",
|
||||
NULL
|
||||
};
|
||||
static const char *const lnames[] =
|
||||
{ FAMILY "Microchip PIC12Cxx - 12 bit instructions",
|
||||
"Microchip PIC16Cxx - 14 bit instructions",
|
||||
"Microchip PIC18Cxx - 16 bit instructions",
|
||||
NULL
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// Processor Definition
|
||||
//-----------------------------------------------------------------------
|
||||
processor_t LPH =
|
||||
{
|
||||
IDP_INTERFACE_VERSION, // version
|
||||
PLFM_PIC, // id
|
||||
// flag
|
||||
PRN_HEX
|
||||
| PR_SEGS
|
||||
| PR_SGROTHER
|
||||
| PR_STACK_UP
|
||||
| PR_RNAMESOK,
|
||||
// flag2
|
||||
PR2_IDP_OPTS // the module has processor-specific configuration options
|
||||
| PR2_MACRO, // try to combine several instructions into a macro instruction
|
||||
12, // 12/14/16 bits in a byte for code segments
|
||||
8, // 8 bits in a byte for other segments
|
||||
|
||||
shnames,
|
||||
lnames,
|
||||
|
||||
asms,
|
||||
|
||||
notify,
|
||||
|
||||
register_names_pic14, // Register names
|
||||
qnumber(register_names_pic14), // Number of registers
|
||||
|
||||
BANK, // first
|
||||
PCLATH, // last
|
||||
0, // size of a segment register
|
||||
rVcs, rVds,
|
||||
|
||||
NULL, // No known code start sequences
|
||||
retcodes,
|
||||
|
||||
PIC_null,
|
||||
PIC_last,
|
||||
Instructions, // instruc
|
||||
0, // int tbyte_size; -- doesn't exist
|
||||
{ 0, 0, 0, 0 }, // char real_width[4];
|
||||
// number of symbols after decimal point
|
||||
// 2byte float (0-does not exist)
|
||||
// normal float
|
||||
// normal double
|
||||
// long double
|
||||
PIC_return, // Icode of return instruction. It is ok to give any of possible return instructions
|
||||
};
|
||||
Reference in New Issue
Block a user