Skip to content

Commit

Permalink
PIC: fix
Browse files Browse the repository at this point in the history
  • Loading branch information
imbillow committed May 18, 2024
1 parent 23d7afb commit 1a3b73b
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 65 deletions.
2 changes: 2 additions & 0 deletions librz/arch/isa/pic/pic.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ typedef struct {
HtSU *pic18_mm;
} PicContext;

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

#endif // RIZIN_PIC_H
27 changes: 14 additions & 13 deletions librz/arch/isa/pic/pic16.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2018 courk <[email protected]>
// SPDX-License-Identifier: LGPL-3.0-only

#include "pic.h"
#include "pic16.h"

static const char *pic16_regname(ut32 reg) {
Expand Down Expand Up @@ -118,6 +119,7 @@ Pic16Opcode pic16_get_opcode(ut16 instr) {
case 0x5: return PIC16_OPCODE_BSF;
case 0x6: return PIC16_OPCODE_BTFSC;
case 0x7: return PIC16_OPCODE_BTFSS;
case 0xd: return PIC16_OPCODE_RETLW;
}

switch (instr >> 9) { // 5 first MSB bits
Expand All @@ -143,7 +145,6 @@ Pic16Opcode pic16_get_opcode(ut16 instr) {
case 0x39: return PIC16_OPCODE_ANDLW;
case 0x3a: return PIC16_OPCODE_XORLW;
case 0x30: return PIC16_OPCODE_MOVLW;
case 0x34: return PIC16_OPCODE_RETLW;
case 0x3c: return PIC16_OPCODE_SUBLW;
case 0x3e: return PIC16_OPCODE_ADDLW;
case 0x35: return PIC16_OPCODE_LSLF;
Expand Down Expand Up @@ -211,10 +212,12 @@ static void analysis_pic16_extract_args(
args_val->d =
(instr & PIC16_OP_ARGS_1D_7F_MASK_D) >> 7;
return;
case PIC16_OP_ARGS_1N_6K:
case PIC16_OP_ARGS_1N_6K: {
args_val->n = (instr & PIC16_OP_ARGS_1N_6K_MASK_N) >> 6;
args_val->k = instr & PIC16_OP_ARGS_1N_6K_MASK_K;
ut16 k = instr & PIC16_OP_ARGS_1N_6K_MASK_K;
args_val->k = SEXT(16, k, 6);
return;
}
case PIC16_OP_ARGS_3B_7F:
args_val->b = (instr & PIC16_OP_ARGS_3B_7F_MASK_B) >> 7;
args_val->f = instr & PIC16_OP_ARGS_3B_7F_MASK_F;
Expand All @@ -225,9 +228,11 @@ static void analysis_pic16_extract_args(
case PIC16_OP_ARGS_8K:
args_val->k = instr & PIC16_OP_ARGS_8K_MASK_K;
return;
case PIC16_OP_ARGS_9K:
args_val->k = instr & PIC16_OP_ARGS_9K_MASK_K;
case PIC16_OP_ARGS_9K: {
ut16 k = instr & PIC16_OP_ARGS_9K_MASK_K;
args_val->k = SEXT(16, k, 9);
return;
}
case PIC16_OP_ARGS_11K:
args_val->k = instr & PIC16_OP_ARGS_11K_MASK_K;
return;
Expand All @@ -253,6 +258,7 @@ const Pic16OpAsmInfo *pic16_get_op_info(Pic16Opcode opcode) {
}

#define F pic16_regname(op->args.f)
#define K (op->args.k)

bool pic16_disasm_op(Pic16Op *op, ut64 addr, const ut8 *b, ut64 l) {
if (!b || l < 2) {
Expand All @@ -276,7 +282,6 @@ bool pic16_disasm_op(Pic16Op *op, ut64 addr, const ut8 *b, ut64 l) {
op->args_tag = op_info->args;
analysis_pic16_extract_args(op->instr, op_info->args, &op->args);

st16 branch;
switch (op_info->args) {
case PIC16_OP_ARGS_NONE:
break;
Expand All @@ -297,9 +302,9 @@ bool pic16_disasm_op(Pic16Op *op, ut64 addr, const ut8 *b, ut64 l) {
break;
case PIC16_OP_ARGS_1N_6K:
if (opcode == PIC16_OPCODE_ADDFSR) {
rz_strf(op->operands, "FSR%d, 0x%x", op->args.n, op->args.k);
rz_strf(op->operands, "FSR%d, %s%#x", op->args.n, K < 0 ? "-" : "", (unsigned)abs(K));
} else {
rz_strf(op->operands, "0x%x[FSR%d]", op->args.k, op->args.n);
rz_strf(op->operands, "%s%#x[FSR%d]", K < 0 ? "-" : "", (unsigned)abs(K), op->args.n);
}
break;
case PIC16_OP_ARGS_3B_7F:
Expand All @@ -315,11 +320,7 @@ bool pic16_disasm_op(Pic16Op *op, ut64 addr, const ut8 *b, ut64 l) {
rz_strf(op->operands, "0x%x", op->args.k);
break;
case PIC16_OP_ARGS_9K:
branch = op->args.k;
branch |= ((branch & 0x100) ? 0xfe00 : 0);
rz_strf(op->operands, "%s0x%x",
branch < 0 ? "-" : "",
(branch < 0 ? -branch : branch));
rz_strf(op->operands, "%s%#x", K < 0 ? "-" : "", (unsigned)abs(K));
break;
case PIC16_OP_ARGS_1N_2M:
rz_strf(op->operands, Pic16FsrOps[op->args.m], op->args.n);
Expand Down
2 changes: 1 addition & 1 deletion librz/arch/isa/pic/pic16.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ typedef enum {

typedef struct _pic16_op_args_val {
ut16 f;
ut16 k;
st16 k;
ut8 d;
ut8 m;
ut8 n;
Expand Down
109 changes: 60 additions & 49 deletions librz/arch/isa/pic/pic16_il.inc
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,16 @@ static RzILOpEffect *set_register_WF(Pic16ILContext *ctx, RzILOpPure *x) {

typedef RzILOpEffect *(*pic16_il_handler)(Pic16ILContext *, ut16);

RzILOpEffect *reset() {
return NOP();
}

RzILOpEffect *set_z(Pic16ILContext *ctx, RzILOpPure *x) {
return SETGb(STATUS, Z, IS_ZERO(x));
}

#define SETZ(x) set_z(ctx, x)

// HELPER DEFINES & TYPEDEFS

#define IL_LIFTER(op) pic16_##op##_il_lifter
Expand Down Expand Up @@ -164,20 +174,28 @@ RzILOpEffect *pic16_il_set_arithmetic_flags(Pic16ILContext *ctx,
cf = CHECK_CARRY(VARL("status_x"), VARL("status_y"), VARL("status_res"));
dcf = CHECK_DIGIT_CARRY(VARL("status_x"), VARL("status_y"), VARL("status_res"));
} else { // sub
cf = CHECK_BORROW(VARL("status_x"), VARL("status_y"), VARL("status_res"));
dcf = CHECK_DIGIT_BORROW(VARL("status_x"), VARL("status_y"), VARL("status_res"));
cf = CHECK_CARRY(VARL("status_x"), NEG(VARL("status_y")), VARL("status_res"));
dcf = CHECK_DIGIT_CARRY(VARL("status_x"), NEG(VARL("status_y")), VARL("status_res"));
}

// get zero flag
RzILOpBool *zf = IS_ZERO(VARL("status_res"));

return SEQ6(
return SEQ8(
SETL("status_x", x),
SETL("status_y", y),
SETL("status_res", res),
SETGb(STATUS, C, cf),
SETGb(STATUS, DC, dcf),
SETGb(STATUS, Z, zf));
SETL("_c", cf),
SETL("_dc", dcf),
SETL("_z", zf),
SETL("_status", register_i(STATUS)),
SETGi(STATUS,
bit_set1(
bit_set1(
bit_set1(VARL("_status"), C, VARL("_c")),
DC,
VARL("_dc")),
Z, VARL("_z"))));
}

#define SET_STATUS_ADD(ctx, x, y, r) pic16_il_set_arithmetic_flags(ctx, x, y, r, true)
Expand All @@ -200,12 +218,11 @@ IL_LIFTER_IMPL(NOP) {
* Status affected : C, DC, Z
* */
IL_LIFTER_IMPL(ADDLW) {
RzILOpEffect *add_op = SET_W(ADD(VRW, U8(K)));
RzILOpEffect *set_status_op =
SET_STATUS_ADD(ctx, VARL("_1"), U8(K), VRW);
return SEQ3(SETL("_1", VRW),
add_op,
set_status_op);
return SEQ4(
SETL("_w", VRW),
SETL("_res", ADD(VARL("_w"), U8(K))),
SET_W(VARL("_res")),
SET_STATUS_ADD(ctx, VARL("_w"), U8(K), VARL("_res")));
}

/**
Expand All @@ -215,17 +232,18 @@ IL_LIFTER_IMPL(ADDLW) {
* Status affected : C, DC, Z
* */
IL_LIFTER_IMPL(ADDWF) {
RzILOpEffect *add_op = SET_WF(ADD(VRW, VRF));
RzILOpEffect *set_status_op =
SET_STATUS_ADD(ctx, VARL("_1"), VRWF, VRF);
return SEQ3(SETL("_1", VRW),
add_op,
set_status_op);
return SEQ5(
SETL("_w", VRW),
SETL("_f", VRF),
SETL("_res", ADD(VARL("_w"), VARL("_f"))),
SET_WF(VARL("_res")),
SET_STATUS_ADD(ctx, VARL("_w"), VARL("_f"), VARL("_res")));
}

IL_LIFTER_IMPL(ANDLW) {
// TODO: set status Z
return SET_W(LOGAND(VRW, U8(K)));
return SEQ2(
SET_W(LOGAND(VRW, U8(K))),
SETZ(VRW));
}

/**
Expand All @@ -235,8 +253,9 @@ IL_LIFTER_IMPL(ANDLW) {
* Status affected : Z
* */
IL_LIFTER_IMPL(ANDWF) {
// TODO: set status Z
return SET_WF(LOGAND(VRW, U8(K)));
return SEQ2(
SET_WF(LOGAND(VRW, VRF)),
SETZ(VRWF));
}

IL_LIFTER_IMPL(BCF) {
Expand Down Expand Up @@ -298,7 +317,7 @@ IL_LIFTER_IMPL(DECFSZ) {
}

IL_LIFTER_IMPL(GOTO) {
return JMP(LOGOR(U16(K), SHIFTL0(UNSIGNED(16, pure_slice(register_i(PCLATH), 3, 4)), U16(11))));
return JMP(LOGOR(U16(K), SHIFTL0(UNSIGNED(16, pure_slice(register_i(PCLATH), 3, 5)), U16(11))));
}

IL_LIFTER_IMPL(INCF) {
Expand Down Expand Up @@ -379,17 +398,20 @@ IL_LIFTER_IMPL(SLEEP) {
}

IL_LIFTER_IMPL(SUBLW) {
return SEQ3(
return SEQ4(
SETL("_w", VRW),
SET_W(SUB(U8(K), VARL("_w"))),
SET_STATUS_SUB(ctx, VARL("_w"), U8(K), VRW));
SETL("_res", SUB(U8(K), VARL("_w"))),
SET_W(VARL("_res")),
SET_STATUS_SUB(ctx, U8(K), VARL("_w"), VARL("_res")));
}

IL_LIFTER_IMPL(SUBWF) {
return SEQ3(
SETL("_res", SUB(VRF, VRW)),
SET_STATUS_SUB(ctx, VRF, VRW, VARL("_res")),
SET_WF(VARL("_res")));
return SEQ5(
SETL("_f", VRF),
SETL("_w", VRW),
SETL("_res", SUB(VARL("_f"), VARL("_w"))),
SET_WF(VARL("_res")),
SET_STATUS_SUB(ctx, VARL("_f"), VARL("_w"), VARL("_res")));
}

IL_LIFTER_IMPL(SWAPF) {
Expand Down Expand Up @@ -420,23 +442,12 @@ IL_LIFTER_IMPL(XORLW) {
* Status affected : Z
* */
IL_LIFTER_IMPL(XORWF) {
return SEQ2(
SET_WF(LOGXOR(VRW, VRF)),
SETGb(STATUS, Z, IS_ZERO(VRWF)));
}

// 14-bit enhanced PIC additional instructions

RzILOpEffect *reset() {
return NOP();
}

RzILOpEffect *set_z(Pic16ILContext *ctx, RzILOpPure *x) {
return SETGb(STATUS, Z, IS_ZERO(x));
return SEQ3(
SETL("_res", LOGXOR(VRW, VRF)),
SET_WF(VARL("_res")),
SETZ(VARL("_res")));
}

#define SETZ(x) set_z(ctx, x)

IL_LIFTER_IMPL(RESET) {
return SEQ2(
reset(),
Expand Down Expand Up @@ -474,15 +485,15 @@ IL_LIFTER_IMPL(MOVIW_1) {
}
IL_LIFTER_IMPL(MOVIW_2) {
return SEQ2(
SET_W(LOAD(ADD(val_fsrn(N), S16(SEXT(16, K, 6))))),
SET_W(LOAD(ADD(val_fsrn(N), S16(K)))),
SETZ(VRW));
}

IL_LIFTER_IMPL(MOVWI_1) {
return STORE(val_fsrn(N), VRW);
}
IL_LIFTER_IMPL(MOVWI_2) {
return STORE(ADD(val_fsrn(N), S16(SEXT(16, K, 6))), VRW);
return STORE(ADD(val_fsrn(N), S16(K)), VRW);
}

IL_LIFTER_IMPL(MOVLB) {
Expand Down Expand Up @@ -525,10 +536,10 @@ IL_LIFTER_IMPL(ADDWFC) {
SET_WF(VARL("_res")));
}
IL_LIFTER_IMPL(ADDFSR) {
return set_fsrn(N, ADD(val_fsrn(N), S16(SEXT(8, K, 6))));
return set_fsrn(N, ADD(val_fsrn(N), S16(K)));
}
IL_LIFTER_IMPL(BRA) {
return JMP(U16(PC + SEXT(16, K, 9)));
return JMP(U16(PC + K));
}

#undef K
Expand Down
2 changes: 0 additions & 2 deletions librz/arch/isa/pic/pic_il.inc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ static inline RzILOpPure *pure_slice(RzILOpPure *x, ut8 l, ut8 r) {
return UNSIGNED(r - l, SHIFTR0(x, U16(l)));
}

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

#define BITN(x, n) IS_ZERO(UNSIGNED(1, SHIFTR0(x, U32(n))))
// overflow is not used in status register but just keeping this for future "maybe" use
#define CHECK_OVERFLOW(x, y, res) AND(XOR(MSB(x), MSB(res)), XOR(MSB(y), MSB(DUP(res))))
Expand Down

0 comments on commit 1a3b73b

Please sign in to comment.