update to ida 7.6, add builds

This commit is contained in:
2021-10-31 21:20:46 +02:00
parent e0e0f2be99
commit b1809fe2d9
1408 changed files with 279193 additions and 302468 deletions

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
View 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
View 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
View 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

View 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
View 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
View 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 &pm;
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

File diff suppressed because it is too large Load Diff

334764
idasdk76/module/pic/pic14.cfg Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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
};