From 523fcdb50c556fc679eb6ba0da60e8cc21b38bfe Mon Sep 17 00:00:00 2001 From: billow Date: Sun, 28 Apr 2024 03:42:02 +0800 Subject: [PATCH] PIC: fix pic18 asm --- librz/arch/isa/pic/pic18_il.inc | 117 +--------- librz/arch/isa/pic/pic_pic18.c | 364 ++++++++++++++++++++++++++++---- librz/arch/isa/pic/pic_pic18.h | 5 +- 3 files changed, 329 insertions(+), 157 deletions(-) diff --git a/librz/arch/isa/pic/pic18_il.inc b/librz/arch/isa/pic/pic18_il.inc index c1541a11699..4a13730b771 100644 --- a/librz/arch/isa/pic/pic18_il.inc +++ b/librz/arch/isa/pic/pic18_il.inc @@ -3,121 +3,6 @@ #include -static const char *pic18_regnames[] = { - "pcl", - "pclath", - "pclatu", - "bsr", - "tos", - "tosl", - "tosh", - "tosu", - "indf0", - "fsr0", - "fsr0l", - "fsr0h", - "indf1", - "fsr1", - "fsr1l", - "fsr1h", - "indf2", - "fsr2", - "frs2l", - "fsr2h", - "tblptr", - "tblptrl", - "tblptrh", - "tblptru", - "rcon", - "memcon", - "intcon", - "intcon2", - "intcon3", - "pie1", - "porta", - "trisa", - "portb", - "tisb", - "latb", - "portc", - "trisc", - "latc", - "portd", - "trisd", - "latd", - "pspcon", - "porte", - "trise", - "late", - "t0con", - "t1con", - "t2con", - "tmr1h", - "tmr0h", - "tmr1l", - "tmr2", - "pr2", - "ccpr1h", - "postinc2", - "ccpr1l", - "postdec2", - "ccp1con", - "preinc2", - "ccpr2h", - "plusw2", - "ccpr2l", - "ccp2con", - "status", - "c .", - "dc .", - "z .", - "ov .", - "n .", - "prod", - "prodl", - "prodh", - "osccon", - "tmr3h", - "lvdcon", - "tmr3l", - "wdtcon", - "t3con", - "spbrg", - "postinc0", - "rcreg", - "postdec0", - "txreg", - "preinc0", - "txsta", - "plusw0", - "rcsta", - "sspbuf", - "wreg", - "sspadd", - "sspstat", - "postinc1", - "sspcon1", - "postdec1", - "sspcon2", - "preinc1", - "adresh", - "plusw1", - "adresl", - "adcon0", - "stkptr", - "tblat", - "_sram", - "_stack" -}; - -static const char *pic18_regname(size_t index) { - if (index >= RZ_ARRAY_SIZE(pic18_regnames)) { - rz_warn_if_reached(); - return NULL; - } - return pic18_regnames[index]; -} - #define K (op->k) #define D (op->d) #define F (op->f) @@ -510,6 +395,6 @@ static RzILOpEffect *pic18_il(Pic18Op *op) { static RzAnalysisILConfig *pic18_il_config( RZ_NONNULL RzAnalysis *analysis) { RzAnalysisILConfig *cfg = rz_analysis_il_config_new(32, false, 16); - cfg->reg_bindings = pic18_regnames; + cfg->reg_bindings = pic18_reg_bindings(); return cfg; } diff --git a/librz/arch/isa/pic/pic_pic18.c b/librz/arch/isa/pic/pic_pic18.c index ed240d246fc..ea19512d9cb 100644 --- a/librz/arch/isa/pic/pic_pic18.c +++ b/librz/arch/isa/pic/pic_pic18.c @@ -37,11 +37,11 @@ static const Pic18OpDesc ops[] = { { PIC18_OPCODE_RCALL, 0xd800, 0xdfff, "rcall", N11_T }, { PIC18_OPCODE_BRA, 0xd000, 0xd7ff, "bra", N11_T }, { PIC18_OPCODE_MOVFF, 0xc000, 0xcfff, "movff", SD_T }, - { PIC18_OPCODE_BTFSC, 0xb000, 0xbfff, "btfsc", BAF_T }, - { PIC18_OPCODE_BTFSS, 0xa000, 0xafff, "btfss", BAF_T }, - { PIC18_OPCODE_BCF, 0x9000, 0x9fff, "bcf", BAF_T }, - { PIC18_OPCODE_BSF, 0x8000, 0x8fff, "bsf", BAF_T }, - { PIC18_OPCODE_BTG, 0x7000, 0x7fff, "btg", BAF_T }, + { PIC18_OPCODE_BTFSC, 0xb000, 0xbfff, "btfsc", FBA_T }, + { PIC18_OPCODE_BTFSS, 0xa000, 0xafff, "btfss", FBA_T }, + { PIC18_OPCODE_BCF, 0x9000, 0x9fff, "bcf", FBA_T }, + { PIC18_OPCODE_BSF, 0x8000, 0x8fff, "bsf", FBA_T }, + { PIC18_OPCODE_BTG, 0x7000, 0x7fff, "btg", FBA_T }, { PIC18_OPCODE_MOVWF, 0x6e00, 0x6fff, "movwf", FA_T }, { PIC18_OPCODE_NEGF, 0x6c00, 0x6dff, "negf", FA_T }, { PIC18_OPCODE_CLRF, 0x6a00, 0x6bff, "clrf", FA_T }, @@ -100,6 +100,288 @@ static const Pic18OpDesc ops[] = { { PIC18_OPCODE_NOP, 0x0, 0x0, "nop", NO_ARG }, }; +static const char *pic18_SFRs[] = { + [0xFFF - 0xF80] = "tosu", + [0xFFE - 0xF80] = "tosh", + [0xFFD - 0xF80] = "tosl", + [0xFFC - 0xF80] = "stkptr", + [0xFFB - 0xF80] = "pclatu", + [0xFFA - 0xF80] = "pclath", + [0xFF9 - 0xF80] = "pcl", + [0xFF8 - 0xF80] = "tblptru", + [0xFF7 - 0xF80] = "tblptrh", + [0xFF6 - 0xF80] = "tblptrl", + [0xFF5 - 0xF80] = "tablat", + [0xFF4 - 0xF80] = "prodh", + [0xFF3 - 0xF80] = "prodl", + [0xFF2 - 0xF80] = "intcon", + [0xFF1 - 0xF80] = "intcon2", + [0xFF0 - 0xF80] = "intcon3", + [0xFEF - 0xF80] = "indf0", + [0xFEE - 0xF80] = "postinc0", + [0xFED - 0xF80] = "postdec0", + [0xFEC - 0xF80] = "preinc0", + [0xFEB - 0xF80] = "plusw0", + [0xFEA - 0xF80] = "fsr0h", + [0xFE9 - 0xF80] = "fsr0l", + [0xFE8 - 0xF80] = "wreg", + [0xFE7 - 0xF80] = "indf1", + [0xFE6 - 0xF80] = "postinc1", + [0xFE5 - 0xF80] = "postdec1", + [0xFE4 - 0xF80] = "preinc1", + [0xFE3 - 0xF80] = "plusw1", + [0xFE2 - 0xF80] = "fsr1h", + [0xFE1 - 0xF80] = "fsr1l", + [0xFE0 - 0xF80] = "bsr", + [0xFDF - 0xF80] = "indf2", + [0xFDE - 0xF80] = "postinc2", + [0xFDD - 0xF80] = "postdec2", + [0xFDC - 0xF80] = "preinc2", + [0xFDB - 0xF80] = "plusw2", + [0xFDA - 0xF80] = "fsr2h", + [0xFD9 - 0xF80] = "fsr2l", + [0xFD8 - 0xF80] = "status", + [0xFD7 - 0xF80] = "tmr0h", + [0xFD6 - 0xF80] = "tmr0l", + [0xFD5 - 0xF80] = "t0con", + [0xFD4 - 0xF80] = "—", + [0xFD3 - 0xF80] = "osccon", + [0xFD2 - 0xF80] = "lvdcon", + [0xFD1 - 0xF80] = "wdtcon", + [0xFD0 - 0xF80] = "rcon", + [0xFCF - 0xF80] = "tmr1h", + [0xFCE - 0xF80] = "tmr1l", + [0xFCD - 0xF80] = "t1con", + [0xFCC - 0xF80] = "tmr2", + [0xFCB - 0xF80] = "pr2", + [0xFCA - 0xF80] = "t2con", + [0xFC9 - 0xF80] = "sspbuf", + [0xFC8 - 0xF80] = "sspadd", + [0xFC7 - 0xF80] = "sspstat", + [0xFC6 - 0xF80] = "sspcon1", + [0xFC5 - 0xF80] = "sspcon2", + [0xFC4 - 0xF80] = "adresh", + [0xFC3 - 0xF80] = "adresl", + [0xFC2 - 0xF80] = "adcon0", + [0xFC1 - 0xF80] = "adcon1", + [0xFC0 - 0xF80] = "—", + [0xFBF - 0xF80] = "ccpr1h", + [0xFBE - 0xF80] = "ccpr1l", + [0xFBD - 0xF80] = "ccp1con", + [0xFBC - 0xF80] = "ccpr2h", + [0xFBB - 0xF80] = "ccpr2l", + [0xFBA - 0xF80] = "ccp2con", + [0xFB9 - 0xF80] = "—", + [0xFB8 - 0xF80] = "—", + [0xFB7 - 0xF80] = "—", + [0xFB6 - 0xF80] = "—", + [0xFB5 - 0xF80] = "—", + [0xFB4 - 0xF80] = "—", + [0xFB3 - 0xF80] = "tmr3h", + [0xFB2 - 0xF80] = "tmr3l", + [0xFB1 - 0xF80] = "t3con", + [0xFB0 - 0xF80] = "—", + [0xFAF - 0xF80] = "spbrg", + [0xFAE - 0xF80] = "rcreg", + [0xFAD - 0xF80] = "txreg", + [0xFAC - 0xF80] = "txsta", + [0xFAB - 0xF80] = "rcsta", + [0xFAA - 0xF80] = "—", + [0xFA9 - 0xF80] = "—", + [0xFA8 - 0xF80] = "—", + [0xFA7 - 0xF80] = "—", + [0xFA6 - 0xF80] = "—", + [0xFA5 - 0xF80] = "—", + [0xFA4 - 0xF80] = "—", + [0xFA3 - 0xF80] = "—", + [0xFA2 - 0xF80] = "ipr2", + [0xFA1 - 0xF80] = "pir2", + [0xFA0 - 0xF80] = "pie2", + [0xF9F - 0xF80] = "ipr1", + [0xF9E - 0xF80] = "pir1", + [0xF9D - 0xF80] = "pie1", + [0xF9C - 0xF80] = "—", + [0xF9B - 0xF80] = "—", + [0xF9A - 0xF80] = "—", + [0xF99 - 0xF80] = "—", + [0xF98 - 0xF80] = "—", + [0xF97 - 0xF80] = "—", + [0xF96 - 0xF80] = "trise", + [0xF95 - 0xF80] = "trisd", + [0xF94 - 0xF80] = "trisc", + [0xF93 - 0xF80] = "trisb", + [0xF92 - 0xF80] = "trisa", + [0xF91 - 0xF80] = "—", + [0xF90 - 0xF80] = "—", + [0xF8F - 0xF80] = "—", + [0xF8E - 0xF80] = "—", + [0xF8D - 0xF80] = "late", + [0xF8C - 0xF80] = "latd", + [0xF8B - 0xF80] = "latc", + [0xF8A - 0xF80] = "latb", + [0xF89 - 0xF80] = "lata", + [0xF88 - 0xF80] = "—", + [0xF87 - 0xF80] = "—", + [0xF86 - 0xF80] = "—", + [0xF85 - 0xF80] = "—", + [0xF84 - 0xF80] = "porte", + [0xF83 - 0xF80] = "portd", + [0xF82 - 0xF80] = "portc", + [0xF81 - 0xF80] = "portb", + [0xF80 - 0xF80] = "porta", + "_sram", + "_stack" +}; + +static const char *pic18_GPRs[] = { + "0x00", + "0x01", + "0x02", + "0x03", + "0x04", + "0x05", + "0x06", + "0x07", + "0x08", + "0x09", + "0x0a", + "0x0b", + "0x0c", + "0x0d", + "0x0e", + "0x0f", + "0x10", + "0x11", + "0x12", + "0x13", + "0x14", + "0x15", + "0x16", + "0x17", + "0x18", + "0x19", + "0x1a", + "0x1b", + "0x1c", + "0x1d", + "0x1e", + "0x1f", + "0x20", + "0x21", + "0x22", + "0x23", + "0x24", + "0x25", + "0x26", + "0x27", + "0x28", + "0x29", + "0x2a", + "0x2b", + "0x2c", + "0x2d", + "0x2e", + "0x2f", + "0x30", + "0x31", + "0x32", + "0x33", + "0x34", + "0x35", + "0x36", + "0x37", + "0x38", + "0x39", + "0x3a", + "0x3b", + "0x3c", + "0x3d", + "0x3e", + "0x3f", + "0x40", + "0x41", + "0x42", + "0x43", + "0x44", + "0x45", + "0x46", + "0x47", + "0x48", + "0x49", + "0x4a", + "0x4b", + "0x4c", + "0x4d", + "0x4e", + "0x4f", + "0x50", + "0x51", + "0x52", + "0x53", + "0x54", + "0x55", + "0x56", + "0x57", + "0x58", + "0x59", + "0x5a", + "0x5b", + "0x5c", + "0x5d", + "0x5e", + "0x5f", + "0x60", + "0x61", + "0x62", + "0x63", + "0x64", + "0x65", + "0x66", + "0x67", + "0x68", + "0x69", + "0x6a", + "0x6b", + "0x6c", + "0x6d", + "0x6e", + "0x6f", + "0x70", + "0x71", + "0x72", + "0x73", + "0x74", + "0x75", + "0x76", + "0x77", + "0x78", + "0x79", + "0x7a", + "0x7b", + "0x7c", + "0x7d", + "0x7e", + "0x7f" +}; + +const char *pic18_regname(size_t index) { + if (index > 0xff && index <= 0xfff) { + return pic18_regname(index % 0x100); + } + if (index <= 0xff && index >= 0x80) { + return pic18_SFRs[index - 0x80]; + } + if (index < 0x80) { + return pic18_GPRs[index]; + } + rz_warn_if_reached(); + return NULL; +} + +const char **pic18_reg_bindings() { + return pic18_SFRs; +} + bool pic18_disasm_op(Pic18Op *op, ut64 addr, const ut8 *buff, ut64 len) { #define check_len(x) \ if (len < x) { \ @@ -136,7 +418,7 @@ bool pic18_disasm_op(Pic18Op *op, ut64 addr, const ut8 *buff, ut64 len) { op->f = word & 0xff; op->a = (word >> 8) & 1; break; - case BAF_T: + case FBA_T: op->f = word & 0xff; op->a = (word >> 8) & 1; op->b = (word >> 9) & 0x7; @@ -156,6 +438,7 @@ bool pic18_disasm_op(Pic18Op *op, ut64 addr, const ut8 *buff, ut64 len) { if (dword >> 28 != 0xf) { \ return false; \ } + case K20S_T: { check_dword_inst; op->k = (dword & 0xff) | ((dword >> 16 & 0xfff) << 8); @@ -182,61 +465,62 @@ bool pic18_disasm_op(Pic18Op *op, ut64 addr, const ut8 *buff, ut64 len) { default: break; } - return true; -} -int pic_pic18_disassemble(RzAsm *a, RzAsmOp *asm_op, const ut8 *b, int blen) { - asm_op->size = 2; - Pic18Op op = { 0 }; - if (!pic18_disasm_op(&op, a->pc, b, blen) || - op.code == PIC18_OPCODE_INVALID) { - rz_asm_op_set_asm(asm_op, "invalid"); - return -1; - } - asm_op->size = op.size; - switch (op.args_kind) { + switch (op->args_kind) { case NO_ARG: - rz_asm_op_set_asm(asm_op, op.mnemonic); + default: break; case N8_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x", op.mnemonic, op.n); + case N11_T: + rz_strf(op->operands, "0x%x", op->n); break; + case K4_T: case K8_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x", op.mnemonic, op.k); + rz_strf(op->operands, "0x%x", op->k); + break; + case K20_T: + rz_strf(op->operands, "0x%x", op->k << 1); break; case FDA_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x, %d, %d", op.mnemonic, op.f, op.d, op.a); + rz_strf(op->operands, "%s, %d, %d", pic18_regname(op->f), op->d, op->a); break; case FA_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x, %d", op.mnemonic, op.f, op.a); + rz_strf(op->operands, "%s, %d", pic18_regname(op->f), op->a); break; - case BAF_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x, %d, %d", op.mnemonic, op.f, op.b, op.a); - break; - case N11_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x", op.mnemonic, op.n); + case FBA_T: + rz_strf(op->operands, "%s, %d, %d", pic18_regname(op->f), op->b, op->a); break; case K20S_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x, %d", op.mnemonic, op.k << 1, op.s); - break; - case K20_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x", op.mnemonic, op.k << 1); + rz_strf(op->operands, "0x%x, %d", op->k << 1, op->s); break; case SD_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x, 0x%x", op.mnemonic, op.s, op.d); - break; - case K4_T: - rz_asm_op_setf_asm(asm_op, "%s 0x%x", op.mnemonic, op.k); + rz_strf(op->operands, "%s, %s", pic18_regname(op->s), pic18_regname(op->d)); break; case S_T: - rz_asm_op_setf_asm(asm_op, "%s %d", op.mnemonic, op.s); + rz_strf(op->operands, "%d", op->s); break; case FK_T: { - rz_asm_op_setf_asm(asm_op, "%s %s, %d", op.mnemonic, fsr[op.f], op.k); + rz_strf(op->operands, "%s, %d", fsr[op->f], op->k); break; } - default: - rz_asm_op_set_asm(asm_op, "unknown args"); + } + + return true; +} + +int pic_pic18_disassemble(RzAsm *a, RzAsmOp *asm_op, const ut8 *b, int blen) { + asm_op->size = 2; + Pic18Op op = { 0 }; + if (!pic18_disasm_op(&op, a->pc, b, blen) || + op.code == PIC18_OPCODE_INVALID) { + rz_asm_op_set_asm(asm_op, "invalid"); + return -1; + } + asm_op->size = op.size; + if (RZ_STR_ISEMPTY(op.operands)) { + rz_asm_op_set_asm(asm_op, op.mnemonic); + } else { + rz_asm_op_setf_asm(asm_op, "%s %s", op.mnemonic, op.operands); } return asm_op->size; } diff --git a/librz/arch/isa/pic/pic_pic18.h b/librz/arch/isa/pic/pic_pic18.h index 1b6b0717594..633b9063244 100644 --- a/librz/arch/isa/pic/pic_pic18.h +++ b/librz/arch/isa/pic/pic_pic18.h @@ -104,7 +104,7 @@ typedef enum { NO_ARG, FDA_T, SD_T, - BAF_T, + FBA_T, K4_T, K8_T, K20_T, @@ -120,6 +120,7 @@ typedef struct { ut64 addr; Pic18Opcode code; const char *mnemonic; + char operands[32]; ut8 size; Pic18ArgsKind args_kind; struct { @@ -133,6 +134,8 @@ typedef struct { }; } Pic18Op; +const char *pic18_regname(size_t index); +const char **pic18_reg_bindings(); bool pic18_disasm_op(Pic18Op *op, ut64 addr, const ut8 *buff, ut64 len); int pic_pic18_disassemble(RzAsm *a, RzAsmOp *asm_op, const ut8 *b, int l);