Skip to content

Commit

Permalink
pic: add RzIL uplifting (#4322)
Browse files Browse the repository at this point in the history
- Add uplifters
- Add memory maps for different devices in PIC16F family
- Fix pic18 register mapping
- Fix pic18 asm
- Detect pic arch
- Add pic_archinfo
- Extract ESIL uplifting to a separate file
- Support RZ_ANALYSIS_OP_MASK_DISASM
- Add pic18 emulateme test
- Add pic16 emulateme test

---------

Co-authored-by: brightprogrammer <[email protected]>
  • Loading branch information
imbillow and brightprogrammer authored May 19, 2024
1 parent d9a10a9 commit 14e9787
Show file tree
Hide file tree
Showing 31 changed files with 5,222 additions and 2,128 deletions.
4 changes: 2 additions & 2 deletions librz/arch/il/analysis_il.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,6 @@ static RzAnalysisILStepResult analysis_il_vm_step_while(
ut64 addr = rz_bv_to_ut64(vm->vm->pc);
ut8 code[32] = { 0 };
analysis->read_at(analysis, addr, code, sizeof(code));
rz_analysis_op_init(&op);
int r = rz_analysis_op(analysis, &op, addr, code, sizeof(code), RZ_ANALYSIS_OP_MASK_IL | RZ_ANALYSIS_OP_MASK_HINT | RZ_ANALYSIS_OP_MASK_DISASM);

if (r < 0 || !op.il_op) {
Expand All @@ -275,7 +274,7 @@ static RzAnalysisILStepResult analysis_il_vm_step_while(

RzStrBuf sb = { 0 };
rz_strbuf_init(&sb);
rz_il_op_effect_stringify(op.il_op, &sb, true);
rz_il_op_effect_stringify(op.il_op, &sb, false);
rz_strbuf_append(&sb, "\n");
il_events(vm->vm, &sb);

Expand All @@ -284,6 +283,7 @@ static RzAnalysisILStepResult analysis_il_vm_step_while(
rz_cons_printf("%x", code[i]);
}
rz_cons_printf("] %s\n%s\n", op.mnemonic, rz_strbuf_get(&sb));
rz_cons_flush();
rz_strbuf_fini(&sb);
rz_analysis_op_fini(&op);
}
Expand Down
18 changes: 18 additions & 0 deletions librz/arch/isa/pic/pic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// SPDX-FileCopyrightText: 2024 billow <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only//

#ifndef RIZIN_PIC_H
#define RIZIN_PIC_H

#include <rz_io.h>

typedef struct {
RzIODesc *mem_sram;
RzIODesc *mem_stack;
bool init_done;
HtSU *pic18_mm;
} PicContext;

#define SEXT(B, x, b) ((st##B)(x << (B - b)) >> (B - b))

#endif // RIZIN_PIC_H
261 changes: 261 additions & 0 deletions librz/arch/isa/pic/pic14.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
// SPDX-FileCopyrightText: 2018 thestr4ng3r <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

#include "pic14.h"

static const Pic14OpInfo pic14_op_info[PIC14_OPCODE_INVALID] = {
{ "nop", PIC14_OP_ARGS_NONE },
{ "option", PIC14_OP_ARGS_NONE },
{ "sleep", PIC14_OP_ARGS_NONE },
{ "clrwdt", PIC14_OP_ARGS_NONE },
{ "tris", PIC14_OP_ARGS_3F },
{ "movlb", PIC14_OP_ARGS_3K },
{ "return", PIC14_OP_ARGS_NONE },
{ "retfie", PIC14_OP_ARGS_NONE },
{ "movwf", PIC14_OP_ARGS_5F },
{ "clrf", PIC14_OP_ARGS_5F },
{ "clrw", PIC14_OP_ARGS_NONE },
{ "subwf", PIC14_OP_ARGS_1D_5F },
{ "decf", PIC14_OP_ARGS_1D_5F },
{ "iorwf", PIC14_OP_ARGS_1D_5F },
{ "andwf", PIC14_OP_ARGS_1D_5F },
{ "xorwf", PIC14_OP_ARGS_1D_5F },
{ "andwf", PIC14_OP_ARGS_1D_5F },
{ "movf", PIC14_OP_ARGS_1D_5F },
{ "comf", PIC14_OP_ARGS_1D_5F },
{ "incf", PIC14_OP_ARGS_1D_5F },
{ "decfsz", PIC14_OP_ARGS_1D_5F },
{ "rrf", PIC14_OP_ARGS_1D_5F },
{ "rlf", PIC14_OP_ARGS_1D_5F },
{ "swapf", PIC14_OP_ARGS_1D_5F },
{ "incfsz", PIC14_OP_ARGS_1D_5F },
{ "bcf", PIC14_OP_ARGS_3B_5F },
{ "bsf", PIC14_OP_ARGS_3B_5F },
{ "btfsc", PIC14_OP_ARGS_3B_5F },
{ "btfss", PIC14_OP_ARGS_3B_5F },
{ "retlw", PIC14_OP_ARGS_8K },
{ "call", PIC14_OP_ARGS_8K },
{ "goto", PIC14_OP_ARGS_9K },
{ "movlw", PIC14_OP_ARGS_8K },
{ "iorlw", PIC14_OP_ARGS_8K },
{ "andlw", PIC14_OP_ARGS_8K },
{ "xorlw", PIC14_OP_ARGS_8K }
};

Pic14Opcode pic14_get_opcode(ut16 instr) {
if (instr & 0xf000) {
return PIC14_OPCODE_INVALID;
}

switch ((instr >> 6) & 0x3f) { // first 6 bits
case 0x7: // 0b000111
return PIC14_OPCODE_ADDWF;
case 0x5: // 0b000101
return PIC14_OPCODE_ANDWF;
case 0x1: // 0b000001
if (instr & (1 << 5)) {
return PIC14_OPCODE_CLRF;
}
if ((instr & 0x1f) == 0) { // last 5 bits
return PIC14_OPCODE_CLRW;
}
return PIC14_OPCODE_INVALID;
case 0x9: // 0b001001
return PIC14_OPCODE_COMF;
case 0x3: // 0b000011
return PIC14_OPCODE_DECF;
case 0xb: // 0b001011
return PIC14_OPCODE_DECFSZ;
case 0xa: // 0b001010
return PIC14_OPCODE_INCF;
case 0xf: // 0b001111
return PIC14_OPCODE_INCFSZ;
case 0x4: // 0b000100
return PIC14_OPCODE_IORWF;
case 0x8: // 0b001000
return PIC14_OPCODE_MOVF;
case 0x0:
if (instr & (1 << 5)) {
return PIC14_OPCODE_MOVWF;
} else {
switch (instr & 0x1f) { // last 5 bits
case 0x0: // 0b00000
return PIC14_OPCODE_NOP;
case 0x4: // 0b00100
return PIC14_OPCODE_CLRWDT;
case 0x2: // 0b00010
return PIC14_OPCODE_OPTION;
case 0x3: // 0b00011
return PIC14_OPCODE_SLEEP;
case 0x1: // 0b00001
case 0x5: // 0b00101
case 0x6: // 0b00110
case 0x7: // 0b00111
return PIC14_OPCODE_TRIS;
case 0x10: // 0b10000
case 0x11: // 0b10001
case 0x12: // 0b10010
case 0x13: // 0b10011
case 0x14: // 0b10100
case 0x15: // 0b10101
case 0x16: // 0b10110
case 0x17: // 0b10111
return PIC14_OPCODE_MOVLB;
case 0x1e: // 0b11110
return PIC14_OPCODE_RETURN;
case 0x1f: // 0b11111
return PIC14_OPCODE_RETFIE;
default:
return PIC14_OPCODE_INVALID;
}
}
case 0xd: // 0b001101
return PIC14_OPCODE_RLF;
case 0xc: // 0b001100
return PIC14_OPCODE_RRF;
case 0x2: // 0b000010
return PIC14_OPCODE_SUBWF;
case 0xe: // 0b001110
return PIC14_OPCODE_SWAPF;
case 0x6: // 0b000110
return PIC14_OPCODE_XORWF;
case 0x10: // 0b010000
case 0x11: // 0b010001
case 0x12: // 0b010010
case 0x13: // 0b010011
return PIC14_OPCODE_BCF;
case 0x14: // 0b010100
case 0x15: // 0b010101
case 0x16: // 0b010110
case 0x17: // 0b010111
return PIC14_OPCODE_BSF;
case 0x18: // 0b011000
case 0x19: // 0b011001
case 0x1a: // 0b011010
case 0x1b: // 0b011011
return PIC14_OPCODE_BTFSC;
case 0x1c: // 0b011100
case 0x1d: // 0b011101
case 0x1e: // 0b011110
case 0x1f: // 0b011111
return PIC14_OPCODE_BTFSS;
case 0x38: // 0b111000
case 0x39: // 0b111001
case 0x3a: // 0b111010
case 0x3b: // 0b111011
return PIC14_OPCODE_ANDLW;
case 0x24: // 0b100100
case 0x25: // 0b100101
case 0x26: // 0b100110
case 0x27: // 0b100111
return PIC14_OPCODE_CALL;
case 0x28: // 0b101000
case 0x29: // 0b101001
case 0x2a: // 0b101010
case 0x2b: // 0b101011
case 0x2c: // 0b101100
case 0x2d: // 0b101101
case 0x2e: // 0b101110
case 0x2f: // 0b101111
return PIC14_OPCODE_GOTO;
case 0x34: // 0b110100
case 0x35: // 0b110101
case 0x36: // 0b110110
case 0x37: // 0b110111
return PIC14_OPCODE_IORLW;
case 0x30: // 0b110000
case 0x31: // 0b110001
case 0x32: // 0b110010
case 0x33: // 0b110011
return PIC14_OPCODE_MOVLW;
case 0x20: // 0b100000
case 0x21: // 0b100001
case 0x22: // 0b100010
case 0x23: // 0b100011
return PIC14_OPCODE_RETLW;
case 0x3c: // 0b111100
case 0x3d: // 0b111101
case 0x3e: // 0b111110
case 0x3f: // 0b111111
return PIC14_OPCODE_XORLW;
default:
return PIC14_OPCODE_INVALID;
}
}

Pic14OpArgs pic14_get_opargs(Pic14Opcode opcode) {
if (opcode >= PIC14_OPCODE_INVALID) {
return -1;
}
return pic14_op_info[opcode].args;
}

const Pic14OpInfo *pic14_get_op_info(Pic14Opcode opcode) {
if (opcode >= PIC14_OPCODE_INVALID) {
return NULL;
}
return &pic14_op_info[opcode];
}

int pic14_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *b, int l) {
#define EMIT_INVALID \
{ \
op->size = 1; \
rz_asm_op_set_asm(op, "invalid"); \
return 1; \
}
if (!b || l < 2) {
EMIT_INVALID
}

ut16 instr = rz_read_le16(b);
Pic14Opcode opcode = pic14_get_opcode(instr);
if (opcode == PIC14_OPCODE_INVALID) {
EMIT_INVALID
}

const Pic14OpInfo *op_info = pic14_get_op_info(opcode);
if (!op_info) {
EMIT_INVALID
}

#undef EMIT_INVALID

op->size = 2;
switch (op_info->args) {
case PIC14_OP_ARGS_NONE:
rz_asm_op_set_asm(op, op_info->mnemonic);
break;
case PIC14_OP_ARGS_2F:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_2F_MASK_F);
break;
case PIC14_OP_ARGS_3F:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_3F_MASK_F);
break;
case PIC14_OP_ARGS_3K:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_3K_MASK_K);
break;
case PIC14_OP_ARGS_1D_5F:
rz_asm_op_setf_asm(op, "%s 0x%x, %c", op_info->mnemonic, instr & PIC14_OP_ARGS_1D_5F_MASK_F,
(instr & PIC14_OP_ARGS_1D_5F_MASK_D) >> 5 ? 'f' : 'w');
break;
case PIC14_OP_ARGS_5F:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_5F_MASK_F);
break;
case PIC14_OP_ARGS_3B_5F:
rz_asm_op_setf_asm(op, "%s 0x%x, 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_3B_5F_MASK_F,
(instr & PIC14_OP_ARGS_3B_5F_MASK_B) >> 5);
break;
case PIC14_OP_ARGS_8K:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_8K_MASK_K);
break;
case PIC14_OP_ARGS_9K:
rz_asm_op_setf_asm(op, "%s 0x%x", op_info->mnemonic, instr & PIC14_OP_ARGS_9K_MASK_K);
break;
default:
rz_asm_op_set_asm(op, "invalid");
break;
}

return op->size;
}
88 changes: 88 additions & 0 deletions librz/arch/isa/pic/pic14.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// SPDX-FileCopyrightText: 2018 thestr4ng3r <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

#ifndef PIC14_H
#define PIC14_H

#include <rz_types.h>
#include <rz_asm.h>

static inline bool is_pic14(const char *x) {
return RZ_STR_EQ(x, "baseline") ||
RZ_STR_EQ(x, "pic14");
}

typedef enum {
PIC14_OP_ARGS_NONE = 0,
PIC14_OP_ARGS_2F,
PIC14_OP_ARGS_3F,
PIC14_OP_ARGS_3K,
PIC14_OP_ARGS_1D_5F,
PIC14_OP_ARGS_5F,
PIC14_OP_ARGS_3B_5F,
PIC14_OP_ARGS_8K,
PIC14_OP_ARGS_9K
} Pic14OpArgs;

#define PIC14_OP_ARGS_2F_MASK_F 0x3
#define PIC14_OP_ARGS_3F_MASK_F 0x7
#define PIC14_OP_ARGS_3K_MASK_K 0x7
#define PIC14_OP_ARGS_1D_5F_MASK_D (1 << 5)
#define PIC14_OP_ARGS_1D_5F_MASK_F 0x1f
#define PIC14_OP_ARGS_5F_MASK_F 0x1f
#define PIC14_OP_ARGS_3B_5F_MASK_B (0x7 << 5)
#define PIC14_OP_ARGS_3B_5F_MASK_F 0x1f
#define PIC14_OP_ARGS_8K_MASK_K 0xff
#define PIC14_OP_ARGS_9K_MASK_K 0x1ff

typedef struct _pic14_op {
const char *mnemonic;
Pic14OpArgs args;
} Pic14OpInfo;

typedef enum {
PIC14_OPCODE_NOP = 0,
PIC14_OPCODE_OPTION,
PIC14_OPCODE_SLEEP,
PIC14_OPCODE_CLRWDT,
PIC14_OPCODE_TRIS,
PIC14_OPCODE_MOVLB,
PIC14_OPCODE_RETURN,
PIC14_OPCODE_RETFIE,
PIC14_OPCODE_MOVWF,
PIC14_OPCODE_CLRF,
PIC14_OPCODE_CLRW,
PIC14_OPCODE_SUBWF,
PIC14_OPCODE_DECF,
PIC14_OPCODE_IORWF,
PIC14_OPCODE_ANDWF,
PIC14_OPCODE_XORWF,
PIC14_OPCODE_ADDWF,
PIC14_OPCODE_MOVF,
PIC14_OPCODE_COMF,
PIC14_OPCODE_INCF,
PIC14_OPCODE_DECFSZ,
PIC14_OPCODE_RRF,
PIC14_OPCODE_RLF,
PIC14_OPCODE_SWAPF,
PIC14_OPCODE_INCFSZ,
PIC14_OPCODE_BCF,
PIC14_OPCODE_BSF,
PIC14_OPCODE_BTFSC,
PIC14_OPCODE_BTFSS,
PIC14_OPCODE_RETLW,
PIC14_OPCODE_CALL,
PIC14_OPCODE_GOTO,
PIC14_OPCODE_MOVLW,
PIC14_OPCODE_IORLW,
PIC14_OPCODE_ANDLW,
PIC14_OPCODE_XORLW,
PIC14_OPCODE_INVALID
} Pic14Opcode;

Pic14Opcode pic14_get_opcode(ut16 instr);
Pic14OpArgs pic14_get_opargs(Pic14Opcode opcode);
const Pic14OpInfo *pic14_get_op_info(Pic14Opcode opcode);
int pic14_disassemble(RzAsm *a, RzAsmOp *op, const ut8 *b, int l);

#endif // PIC14_H
Loading

0 comments on commit 14e9787

Please sign in to comment.