static void opex(RStrBuf *buf, csh handle, cs_insn *insn) { int i; r_strbuf_init (buf); r_strbuf_append (buf, "{"); cs_xcore *x = &insn->detail->xcore; r_strbuf_append (buf, "\"operands\":["); for (i = 0; i < x->op_count; i++) { cs_xcore_op *op = &x->operands[i]; if (i > 0) { r_strbuf_append (buf, ","); } r_strbuf_append (buf, "{"); switch (op->type) { case XCORE_OP_REG: r_strbuf_append (buf, "\"type\":\"reg\""); r_strbuf_appendf (buf, ",\"value\":\"%s\"", cs_reg_name (handle, op->reg)); break; case XCORE_OP_IMM: r_strbuf_append (buf, "\"type\":\"imm\""); r_strbuf_appendf (buf, ",\"value\":%"PFMT64d, op->imm); break; case XCORE_OP_MEM: r_strbuf_append (buf, "\"type\":\"mem\""); if (op->mem.base != XCORE_REG_INVALID) { r_strbuf_appendf (buf, ",\"base\":\"%s\"", cs_reg_name (handle, op->mem.base)); } r_strbuf_appendf (buf, ",\"disp\":%"PFMT64d"", op->mem.disp); break; default: r_strbuf_append (buf, "\"type\":\"invalid\""); break; } r_strbuf_append (buf, "}"); } r_strbuf_append (buf, "]"); r_strbuf_append (buf, "}"); }
// TODO: move into r_util/str R_API char *r_cons_html_filter(const char *ptr, int *newlen) { const char *str = ptr; int esc = 0; int len = 0; int inv = 0; int tmp; bool tag_font = false; if (!ptr) { return NULL; } RStrBuf *res = r_strbuf_new (""); if (!res) { return NULL; } for (; ptr[0]; ptr = ptr + 1) { if (ptr[0] == '\n') { tmp = (int) (size_t) (ptr - str); r_strbuf_append_n (res, str, tmp); if (!ptr[1]) { // write new line if it's the end of the output r_strbuf_append (res, "\n"); } else { r_strbuf_append (res, "<br />"); } str = ptr + 1; continue; } else if (ptr[0] == '<') { tmp = (int) (size_t) (ptr - str); r_strbuf_append_n (res, str, tmp); r_strbuf_append (res, "<"); str = ptr + 1; continue; } else if (ptr[0] == '>') { tmp = (int) (size_t) (ptr - str); r_strbuf_append_n (res, str, tmp); r_strbuf_append (res, ">"); str = ptr + 1; continue; } else if (ptr[0] == ' ') { tmp = (int) (size_t) (ptr - str); r_strbuf_append_n (res, str, tmp); r_strbuf_append (res, " "); str = ptr + 1; continue; } if (ptr[0] == 0x1b) { esc = 1; tmp = (int) (size_t) (ptr - str); r_strbuf_append_n (res, str, tmp); if (tag_font) { r_strbuf_append (res, "</font>"); tag_font = false; } str = ptr + 1; continue; } if (esc == 1) { // \x1b[2J if (ptr[0] != '[') { eprintf ("Oops invalid escape char\n"); esc = 0; str = ptr + 1; continue; } esc = 2; continue; } else if (esc == 2) { // TODO: use dword comparison here if (ptr[0] == '2' && ptr[1] == 'J') { r_strbuf_append (res, "<hr />"); ptr++; esc = 0; str = ptr; continue; } else if (!strncmp (ptr, "48;5;", 5) || !strncmp (ptr, "48;2;", 5)) { char *end = strchr (ptr, 'm'); r_strbuf_appendf (res, "<font style='background-color:%s'>", gethtmlrgb (ptr)); tag_font = true; ptr = end; str = ptr + 1; esc = 0; } else if (!strncmp (ptr, "38;5;", 5) || !strncmp (ptr, "38;2;", 5)) { char *end = strchr (ptr, 'm'); r_strbuf_appendf (res, "<font color='%s'>", gethtmlrgb (ptr)); tag_font = true; ptr = end; str = ptr + 1; esc = 0; } else if (ptr[0] == '0' && ptr[1] == ';' && ptr[2] == '0') { // wtf ? r_cons_gotoxy (0, 0); ptr += 4; esc = 0; str = ptr; continue; } else if (ptr[0] == '0' && ptr[1] == 'm') { str = (++ptr) + 1; esc = inv = 0; continue; // reset color } else if (ptr[0] == '7' && ptr[1] == 'm') { str = (++ptr) + 1; inv = 128; esc = 0; continue; // reset color } else if (ptr[0] == '3' && ptr[2] == 'm') { r_strbuf_appendf (res, "<font color='%s'>", gethtmlcolor (ptr[1], inv? "#fff": "#000")); tag_font = true; ptr = ptr + 1; str = ptr + 2; esc = 0; continue; } else if (ptr[0] == '4' && ptr[2] == 'm') { r_strbuf_appendf (res, "<font style='background-color:%s'>", gethtmlcolor (ptr[1], inv? "#000": "#fff")); tag_font = true; ptr = ptr + 1; str = ptr + 2; esc = 0; continue; } } len++; } if (tag_font) { r_strbuf_append (res, "</font>"); tag_font = false; } r_strbuf_append_n (res, str, ptr - str); if (newlen) { *newlen = res->len; } return r_strbuf_drain (res); }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { char str[8][32]; int i; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); if (insn) { // caching operands for (i=0; i<insn->detail->mips.op_count && i<8; i++) { *str[i]=0; ARG (i); } } if (insn) switch (insn->id) { case MIPS_INS_NOP: r_strbuf_setf (&op->esil, ","); break; case MIPS_INS_BREAK: r_strbuf_setf (&op->esil, "%s,%s,TRAP", ARG (0), ARG (0)); break; case MIPS_INS_SW: case MIPS_INS_SWL: case MIPS_INS_SWR: r_strbuf_appendf (&op->esil, "%s,%s,=[4]", ARG (0), ARG (1)); break; case MIPS_INS_SH: r_strbuf_appendf (&op->esil, "%s,%s,=[2]", ARG (0), ARG (1)); break; case MIPS_INS_SWC1: case MIPS_INS_SWC2: r_strbuf_setf (&op->esil, "%s,$", ARG (1)); break; case MIPS_INS_SB: r_strbuf_appendf (&op->esil, "%s,%s,=[1]", ARG (0), ARG (1)); break; case MIPS_INS_CMP: case MIPS_INS_CMPU: case MIPS_INS_CMPGU: case MIPS_INS_CMPGDU: case MIPS_INS_CMPI: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG (1), ARG (0)); break; case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: case MIPS_INS_SRA: r_strbuf_appendf (&op->esil, "%s,%s,>>,31,%s,>>,?{,32,%s,-,%s,1,<<,1,-,<<,}{,0,},|,%s,=,", ARG (2), ARG (1), ARG (1), ARG (2), ARG (2), ARG (0)); break; case MIPS_INS_SHRL: // suffix 'S' forces conditional flag to be updated case MIPS_INS_SRLV: case MIPS_INS_SRL: r_strbuf_appendf (&op->esil, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0)); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: r_strbuf_appendf (&op->esil, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0)); break; case MIPS_INS_BAL: case MIPS_INS_JAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_D ("%s"), ARG (0)); break; case MIPS_INS_JALR: case MIPS_INS_JALRS: if (OPCOUNT () < 2) { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_D ("%s"), ARG (0)); } else { PROTECT_ZERO () { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_DR ("%s","%s"), ARG (0), ARG (1)); } } break; case MIPS_INS_JALRC: // no delay if (OPCOUNT () < 2) { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_ND ("%s"), ARG (0)); } else { PROTECT_ZERO () { r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_CALL_NDR ("%s","%s"), ARG (0), ARG (1)); } } break; case MIPS_INS_JRADDIUSP: // increment stackpointer in X and jump to %ra r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%d,sp,+=,"ES_J ("ra"), ARG (0)); break; case MIPS_INS_JR: case MIPS_INS_JRC: case MIPS_INS_J: case MIPS_INS_B: // ??? // jump to address with conditional r_strbuf_appendf (&op->esil, ES_TRAP_DS () "," ES_J ("%s"), ARG (0)); break; case MIPS_INS_BNE: // bne $s, $t, offset r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,%s,==,$z,!,?{,"ES_J ("%s")",}", ARG (0), ARG (1), ARG (2)); break; case MIPS_INS_BEQ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,%s,==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1), ARG (2)); break; case MIPS_INS_BZ: case MIPS_INS_BEQZ: case MIPS_INS_BEQZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BNEZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,!,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BEQZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",%s,0,==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BLEZ: case MIPS_INS_BLEZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,"ES_J ("%s")",BREAK,},", ARG (0), ARG (1)); r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZ: case MIPS_INS_BGEZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_D ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGEZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGTZALC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,BREAK,},", ARG(0)); r_strbuf_appendf (&op->esil, "0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_ND ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BLTZAL: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_CALL_D ("%s")",}", ARG(0), ARG(1)); break; case MIPS_INS_BLTZ: case MIPS_INS_BLTZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",1,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J ("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BGTZ: case MIPS_INS_BGTZC: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,%s,==,$z,?{,BREAK,},", ARG (0)); r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,"ES_IS_NEGATIVE ("%s")",==,$z,?{,"ES_J("%s")",}", ARG (0), ARG (1)); break; case MIPS_INS_BTEQZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,t,==,$z,?{,"ES_J ("%s")",}", ARG (0)); break; case MIPS_INS_BTNEZ: r_strbuf_appendf (&op->esil, ES_TRAP_DS () ",0,t,==,$z,!,?{,"ES_J ("%s")",}", ARG (0)); break; case MIPS_INS_MOV: case MIPS_INS_MOVE: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,=", ARG (1), REG (0)); } break; case MIPS_INS_MOVZ: case MIPS_INS_MOVF: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "0,%s,==,$z,?{,%s,%s,=,}", ARG (2), ARG (1), REG (0)); } break; case MIPS_INS_MOVT: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "1,%s,==,$z,?{,%s,%s,=,}", ARG (2), ARG (1), REG (0)); } break; case MIPS_INS_FSUB: case MIPS_INS_SUB: PROTECT_ZERO () { r_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0)); //r_strbuf_appendf(&op->esil, "%s,%s,>,?{,1,TRAP,}{,%s,%s,-,%s,=", // ARG (1), ARG (2), ARG (1), ARG (2), ARG (0)); } break; case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_DSUBU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=", arg2, arg1, arg0); } break; case MIPS_INS_NEG: case MIPS_INS_NEGU: r_strbuf_appendf (&op->esil, "%s,0,-,%s,=,", ARG (1), ARG (0)); break; /** signed -- sets overflow flag */ case MIPS_INS_ADD: { PROTECT_ZERO () { r_strbuf_appendf(&op->esil, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0)); #if 0 r_strbuf_appendf (&op->esil, "0,32,%s,%s,+,>>,>,?{,1,TRAP,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); #endif } } break; case MIPS_INS_ADDI: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "0,32,%s,0xffffffff,&,%s,+,>>,>,?{,1,TRAP,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); } break; case MIPS_INS_DADD: case MIPS_INS_DADDI: /** unsigned */ case MIPS_INS_ADDU: case MIPS_INS_ADDIU: case MIPS_INS_DADDIU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { if (*arg2 == '-') { r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=", arg2+1, arg1, arg0); } else { r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", arg2, arg1, arg0); } } } break; case MIPS_INS_LI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x",%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LUI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x"0000,%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LB: case MIPS_INS_LBU: //one of these is wrong ESIL_LOAD ("1"); break; case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWU: case MIPS_INS_LL: case MIPS_INS_LLD: case MIPS_INS_LD: case MIPS_INS_LDI: case MIPS_INS_LDL: case MIPS_INS_LDC1: case MIPS_INS_LDC2: ESIL_LOAD ("4"); break; case MIPS_INS_LWX: case MIPS_INS_LH: case MIPS_INS_LHU: case MIPS_INS_LHX: ESIL_LOAD ("2"); break; case MIPS_INS_AND: case MIPS_INS_ANDI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0); } break; case MIPS_INS_OR: case MIPS_INS_ORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,|,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_XOR: case MIPS_INS_XORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,^,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_NOR: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "%s,%s,|,0xffffffff,^,%s,=", arg2, arg1, arg0); } } break; case MIPS_INS_SLT: case MIPS_INS_SLTI: if (OPCOUNT () < 3) { r_strbuf_appendf (&op->esil, ES_IS_NEGATIVE ("%s")"," ES_IS_NEGATIVE ("%s")"," "==,$z,?{," "%s,%s,<,t,=," "}{," "%s,%s,>=,t,=," "}", ARG (1), ARG (0), ARG (1), ARG (0), ARG (1), ARG (0)); } else { r_strbuf_appendf (&op->esil, ES_IS_NEGATIVE ("%s")"," ES_IS_NEGATIVE ("%s")"," "==,$z,?{," "%s,%s,<,%s,=," "}{," "%s,%s,>=,%s,=," "}", ARG (2), ARG (1), ARG (2), ARG (1), ARG (0), ARG (2), ARG (1), ARG (0)); } break; case MIPS_INS_SLTU: case MIPS_INS_SLTIU: if (OPCOUNT () < 3) { r_strbuf_appendf (&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,t,=", ARG (1), ARG (0)); } else { r_strbuf_appendf (&op->esil, "%s,0xffffffff,&,%s,0xffffffff,&,<,%s,=", ARG (2), ARG (1), ARG (0)); } break; case MIPS_INS_MULT: case MIPS_INS_MULTU: r_strbuf_appendf (&op->esil, "%s,%s,*,0xffffffff,&,lo,=," ES_SIGN_EXT64 ("lo") ",32,%s,%s,*,>>,0xffffffff,&,hi,=," ES_SIGN_EXT64 ("hi"), ARG (0), ARG (1), ARG (0), ARG (1)); break; case MIPS_INS_MFLO: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "lo,%s,=", REG (0)); } break; case MIPS_INS_MFHI: PROTECT_ZERO () { r_strbuf_appendf (&op->esil, "hi,%s,=", REG (0)); } break; case MIPS_INS_MTLO: r_strbuf_appendf (&op->esil, "%s,lo,=,"ES_SIGN_EXT64 ("lo"), REG (0)); break; case MIPS_INS_MTHI: r_strbuf_appendf (&op->esil, "%s,hi,=,"ES_SIGN_EXT64 ("hi"), REG (0)); break; #if 0 // could not test div case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: PROTECT_ZERO () { // 32 bit needs sign extend r_strbuf_appendf (&op->esil, "%s,%s,/,lo,=,%s,%s,%%,hi,=", REG(1), REG(0), REG(1), REG(0)); } break; #endif default: return -1; } return 0; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf) { int ret = -1; ut8 opcode = buf[0]; if (!op) { return 2; } r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (opcode >> 4) { case H8300_CMP_4BIT: //acc. to manual this is how it's done, could use == in esil r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,-", imm, rdB(0)); //setZ setV("%o"); setN; setHb_B; setCb_B; maskB(0); setZ; return 0; case H8300_OR_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,|=", imm, rdB(0)); //setZ setV("0"); setN; maskB(0); setZ; return 0; case H8300_XOR_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,^=", imm, rdB(0)); //setZ setN; setV("0"); maskB(0); setZ; return 0; case H8300_AND_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,&=", imm, rdB(0)); //setZ setN; setV("0"); maskB(0); setZ; return 0; case H8300_ADD_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,+=", imm, rdB(0)); //setZ setV("%o"); setN; setH_B; setC_B; maskB(0); setZ; return 0; case H8300_ADDX_4BIT: r_strbuf_appendf(&op->esil, "0x%02x,C,+,r%u%c,+= ", imm, rdB(0), rdB(0)); //setZ setV("%o"); setN; setH_B; setC_B; maskB(0); setZ; return 0; case H8300_SUBX_4BIT: //Rd – imm – C → Rd r_strbuf_appendf(&op->esil, "0x%02x,r%u%c,-=,C,r%u%c,-=", imm, rdB(0), rdB(0)); //setZ setV("%o"); setN; setHb_B; setCb_B; maskB(0); setZ; return 0; case H8300_MOV_4BIT_2: /*TODO*/ case H8300_MOV_4BIT_3: /*TODO*/ case H8300_MOV_4BIT: /*TODO*/ return 0; default: break; }; switch (opcode) { case H8300_NOP: r_strbuf_set (&op->esil, ","); return 0; case H8300_SLEEP: /* TODO */ return 0; case H8300_STC: r_strbuf_appendf(&op->esil, "ccr,r%u%c,=", rdB(1)); return 0; case H8300_LDC: r_strbuf_appendf(&op->esil, "r%u%c,ccr,=", rdB(1)); return 0; case H8300_ORC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,|=", imm); return 0; case H8300_XORC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,^=", imm); return 0; case H8300_ANDC: r_strbuf_appendf(&op->esil, "0x%02x,ccr,&=", imm); return 0; case H8300_LDC_2: r_strbuf_appendf(&op->esil, "0x%02x,ccr,=", imm); return 0; case H8300_ADDB_DIRECT: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,+=", rsB(), rdB(1)); setH_B; setV("%o"); setC_B ; setN; //setZ; maskB(1); setZ; return 0; case H8300_ADDW_DIRECT: r_strbuf_appendf (&op->esil, "r%u,r%u,+=", rs(), rd()); setH_W; setV("%o"); setC_W; setN; mask(); setZ; return 0; case H8300_INC: r_strbuf_appendf(&op->esil, "1,r%u%c,+=", rdB(1)); //setZ setV("%o") ; setN; maskB(1); setZ; return 0; case H8300_ADDS: r_strbuf_appendf (&op->esil, "%d,r%u,+=", ((buf[1] & 0xf0) == 0x80) ? 2 : 1, rd()); return 0; case H8300_MOV_1: /*TODO check if flags are set internally or not*/ r_strbuf_appendf (&op->esil, "r%u%c,r%u%c,=", rsB(), rdB(1)); //setZ setN; maskB(1); setZ; return 0; case H8300_MOV_2: r_strbuf_appendf(&op->esil, "r%u,r%u,=", rs(), rd()); //setZ setN; mask(); setZ; return 0; case H8300_ADDX: //Rd + (Rs) + C → Rd r_strbuf_appendf (&op->esil, "r%u%c,C,+,r%u%c,+=", rsB(), rdB(1), rdB(1)); //setZ setV("%o"); setN; setH_B ; setC_B; maskB(1); setZ; return 0; case H8300_DAA: /*TODO*/ return 0; case H8300_SHL: /*TODO*/ return 0; case H8300_SHR: /*TODO*/ return 0; case H8300_ROTL: /*TODO*/ return 0; case H8300_ROTR: /*TODO*/ return 0; case H8300_OR: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,|=", rsB(), rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; return 0; case H8300_XOR: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,^=", rsB(), rdB(1)); //setZ setV("0") ; setN; maskB(1); setZ; return 0; case H8300_AND: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,&=", rsB(), rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; return 0; case H8300_NOT_NEG: if ((buf[1] & 0xf0) == 0x80) { //NEG r_strbuf_appendf(&op->esil, "r%u%c,0,-,r%u%c,=", rdB(1), rdB(1)); //setZ setHb_B; setV("%o") ; setCb_B ; setN; maskB(1); setZ; } else if ((buf[1] & 0xf0) == 0x00) { //NOT r_strbuf_appendf(&op->esil, "r%u%c,!=", rdB(1)); //setZ setV("0"); setN; maskB(1); setZ; } return 0; case H8300_SUB_1: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-=", rsB(), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_SUBW: r_strbuf_appendf (&op->esil, "r%u,r%u,-=", rs(), rd()); setHb_W; setV ("%o"); setCb_W; setN; mask(); setZ; return 0; case H8300_DEC: r_strbuf_appendf (&op->esil, "1,r%u%c,-=", rdB(1)); //setZ setV("%o"); setN; maskB(1); setZ; return 0; case H8300_SUBS: r_strbuf_appendf(&op->esil, "%d,r%u,-=", ( (buf[1] & 0xf0) == 0x80) ? 2 : 1, rd()); return 0; case H8300_CMP_1: r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-", rsB(), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_CMP_2: r_strbuf_appendf(&op->esil, "r%u,r%u,-", rs(), rd()); //setZ setHb_W; setV("%o"); setCb_W; setN; mask(); setZ; return 0; case H8300_SUBX: //Rd – (Rs) – C → Rd r_strbuf_appendf(&op->esil, "r%u%c,r%u%c,-=,C,r%u%c,-=", rsB(), rdB(1), rdB(1)); //setZ setHb_B; setV("%o"); setCb_B; setN; maskB(1); setZ; return 0; case H8300_DAS: /*TODO*/ return 0; case H8300_BRA: r_strbuf_appendf(&op->esil, "0x%02x,pc,+=", buf[1]); return 0; case H8300_BRN: r_strbuf_appendf(&op->esil,","); return 0; case H8300_BHI: r_strbuf_appendf(&op->esil, "C,Z,|,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLS: r_strbuf_appendf(&op->esil, "C,Z,|,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BCC: r_strbuf_appendf(&op->esil, "C,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BCS: r_strbuf_appendf(&op->esil, "C,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BNE: r_strbuf_appendf(&op->esil, "Z,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BEQ: r_strbuf_appendf(&op->esil, "Z,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BVC: r_strbuf_appendf(&op->esil, "V,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BVS: r_strbuf_appendf(&op->esil, "V,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BPL: r_strbuf_appendf(&op->esil, "N,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BMI: r_strbuf_appendf(&op->esil, "N,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BGE: r_strbuf_appendf(&op->esil, "N,V,^,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLT: r_strbuf_appendf(&op->esil, "N,V,^,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BGT: r_strbuf_appendf(&op->esil, "Z,N,V,^,|,!,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_BLE: r_strbuf_appendf(&op->esil, "Z,N,V,^,|,?{0x%02x,pc,+=}", buf[1]); return 0; case H8300_MULXU: //Refer to pg. 100 of the manual linked at the beginning r_strbuf_appendf(&op->esil, "r%u%c,r%ul,*,r%u,=", rsB(), rd(), rd()); return 0; case H8300_DIVXU: /*TODO*/ return 0; case H8300_RTS: /*TODO*/ return 0; case H8300_BSR: /*TODO*/ return 0; case H8300_RTE: /*TODO*/ return 0; case H8300_JMP_1: /*TODO*/ return 0; case H8300_JMP_2: /*TODO*/ return 0; case H8300_JMP_3: /*TODO*/ return 0; case H8300_JSR_1: /*TODO*/ return 0; case H8300_JSR_2: /*TODO*/ return 0; case H8300_JSR_3: /*TODO*/ return 0; //NOTE - cases marked with TODO have mem. access also(not impl.) case H8300_BSET_1: /*TODO*/ //set rs&0x7th bit of rd. expr.- rd|= 1<<(rs&0x07) r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,1,<<,r%u%c,|=", rsB(), rdB(1)); return 0; case H8300_BNOT_1: /*TODO*/ //invert rs&0x7th bit of rd. expr.- rd^= 1<<(rs&0x07) r_strbuf_appendf(&op->esil,"0x07,r%u%c,&,1,<<,r%u%c,^=", rsB(), rdB(1)); return 0; case H8300_BCLR_R2R8: /*TODO*/ //clear rs&0x7th bit of rd. expr.- rd&= !(1<<(rs&0x07)) r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,1,<<,!,r%u%c,&=", rsB(), rdB(1)); return 0; case H8300_BTST_R2R8: /*TODO*/ //¬ (<Bit No.> of <EAd>) → Z, extract bit value and shift it back r_strbuf_appendf(&op->esil, "0x7,r%u%c,&,0x7,r%u%c,&,1,<<,r%u%c,&,>>,!,Z,=", rsB(), rsB(), rdB(1)); return 0; case H8300_BST_BIST: /*TODO*/ if (!(buf[1] & 0x80)) { //BST r_strbuf_appendf(&op->esil,"%d,C,<<,r%u%c,|=",rs(),rdB(1)); } else { //BIST r_strbuf_appendf (&op->esil, "%d,C,!,<<,r%u%c,|=", rs (), rdB (1)); } return 0; case H8300_MOV_R82IND16: /*TODO*/ return 0; case H8300_MOV_IND162R16: /*TODO*/ return 0; case H8300_MOV_R82ABS16: /*TODO*/ return 0; case H8300_MOV_ABS162R16: /*TODO*/ return 0; case H8300_MOV_R82RDEC16: /*TODO*/ return 0; case H8300_MOV_INDINC162R16: /*TODO*/ return 0; case H8300_MOV_R82DISPR16: /*TODO*/ return 0; case H8300_MOV_DISP162R16: /*TODO*/ return 0; case H8300_BSET_2: /*TODO*/ //set imm bit of rd. expr.- rd|= (1<<imm) r_strbuf_appendf(&op->esil, "%d,1,<<,r%u%c,|=", rs(), rdB(1)); return 0; case H8300_BNOT_2: /*TODO*/ //inv. imm bit of rd. expr.- rd^= (1<<imm) r_strbuf_appendf(&op->esil,"%d,1,<<,r%u%c,^=",rs(),rdB(1)); return 0; case H8300_BCLR_IMM2R8: //clear imm bit of rd. expr.- rd&= !(1<<imm) r_strbuf_appendf(&op->esil, "%d,1,<<,!,r%u%c,&=", rs(), rdB(1)); return 0; case H8300_BTST: /*TODO*/ //see BTST above r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,Z,=", rs(), rs(), rdB(1)); return 0; case H8300_BOR_BIOR: /*TODO*/ if (!(buf[1] & 0x80)) { //BOR //C|=(rd&(1<<imm))>>imm r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,|=", rs(), rs(), rdB(1)); } else { //BIOR //C|=!(rd&(1<<imm))>>imm r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,|=", rs (), rs (), rdB (1)); } return 0; case H8300_BXOR_BIXOR: /*TODO*/ if (!(buf[1] & 0x80)) { //BXOR //C^=(rd&(1<<imm))>>imm r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,^=", rs(), rs(), rdB(1)); } else { //BIXOR r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,^=", rs (), rs (), rdB (1)); } return 0; case H8300_BAND_BIAND: /*TODO check functionality*/ //C&=(rd&(1<<imm))>>imm if (!(buf[1] & 0x80)) { //BAND r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,&=", rs(), rs(), rdB(1)); } else { //BIAND r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,&=", rs (), rs (), rdB (1)); } return 0; case H8300_BILD_IMM2R8: /*TODO*/ if (!(buf[1] & 0x80)) { //BLD r_strbuf_appendf(&op->esil, "%d,%d,1,<<,r%u%c,&,>>,C,=", rs(), rs(), rdB(1)); } else { //BILD r_strbuf_appendf (&op->esil, "%d,%d,1,<<,r%u%c,&,>>,!,C,=", rs (), rs (), rdB (1)); } return 0; case H8300_MOV_IMM162R16: /*TODO*/ return 0; case H8300_EEPMOV: /*TODO*/ return 0; case H8300_BIAND_IMM2IND16: /*TODO*/ return 0; case H8300_BCLR_R2IND16: /*TODO*/ return 0; case H8300_BIAND_IMM2ABS8: /*TODO*/ return 0; case H8300_BCLR_R2ABS8: /*TODO*/ return 0; default: break; }; return ret; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { int i; char str[32][32]; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (insn->detail->arm.cc) { case ARM_CC_AL: // no condition break; case ARM_CC_EQ: r_strbuf_setf (&op->esil, "zf,0,?,"); break; case ARM_CC_NE: r_strbuf_setf (&op->esil, "zf,!,0,?,"); break; case ARM_CC_GT: case ARM_CC_LE: break; } // TODO: PREFIX CONDITIONAL switch (insn->id) { case ARM_INS_PUSH: // TODO: increment stack case ARM_INS_STM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4],", REG (i), ARG (0), i*4); } break; case ARM_INS_POP: // TODO: decrement stack case ARM_INS_LDM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", ARG (0), i*4, REG (i)); } break; case ARM_INS_CMP: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG(1), ARG(0)); break; case ARM_INS_LSL: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,<<=", ARG(1), ARG(0)); break; case ARM_INS_LSR: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,>>=", ARG(1), ARG(0)); break; case ARM_INS_B: case ARM_INS_BL: case ARM_INS_BLX: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case ARM_INS_MOV: case ARM_INS_MOVS: r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), REG(0)); break; case ARM_INS_SSUB16: case ARM_INS_SSUB8: case ARM_INS_SUB: r_strbuf_appendf (&op->esil, "%s,%s,-=", ARG(1), ARG(0)); break; case ARM_INS_SADD16: case ARM_INS_SADD8: case ARM_INS_ADD: r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(1), ARG(0)); break; case ARM_INS_LDR: r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; case ARM_INS_LDRB: r_strbuf_appendf (&op->esil, "%s,%d,+,[1],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; } return 0; }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { char str[32][32]; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); if (insn) switch (insn->id) { case MIPS_INS_NOP: r_strbuf_setf (&op->esil, ","); break; case MIPS_INS_SW: r_strbuf_appendf (&op->esil, "%s,%s,=[4]", ARG(0), ARG(1)); break; case MIPS_INS_SWC1: case MIPS_INS_SWC2: r_strbuf_setf (&op->esil, "%s,$", ARG(1)); break; case MIPS_INS_SB: r_strbuf_appendf (&op->esil, "%s,%s,=[1]", ARG(0), ARG(1)); break; case MIPS_INS_CMP: case MIPS_INS_CMPU: case MIPS_INS_CMPGU: case MIPS_INS_CMPGDU: case MIPS_INS_CMPI: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG(1), ARG(0)); break; case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: case MIPS_INS_SRA: r_strbuf_appendf (&op->esil, "%s,%s,>>,31,%s,>>,?{,32,%s,-,%s,1,<<,1,-,<<,}{,0,},|,%s,=,", ARG(2), ARG(1), ARG(1), ARG(2), ARG(2), ARG(0)); break; case MIPS_INS_SHRL: // suffix 'S' forces conditional flag to be updated case MIPS_INS_SRLV: case MIPS_INS_SRL: r_strbuf_appendf (&op->esil, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0)); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: r_strbuf_appendf (&op->esil, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0)); break; case MIPS_INS_BAL: case MIPS_INS_JAL: case MIPS_INS_JALR: case MIPS_INS_JALRS: case MIPS_INS_JALRC: case MIPS_INS_BLTZAL: // Branch on less than zero and link r_strbuf_appendf (&op->esil, "pc,8,+,ra,=,%s,pc,=", ARG(0)); break; case MIPS_INS_JR: case MIPS_INS_JRC: case MIPS_INS_J: // jump to address with conditional r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case MIPS_INS_B: // ??? case MIPS_INS_BZ: case MIPS_INS_BGTZ: case MIPS_INS_BGTZC: case MIPS_INS_BGTZALC: case MIPS_INS_BGEZ: case MIPS_INS_BGEZC: case MIPS_INS_BGEZAL: // Branch on less than zero and link case MIPS_INS_BGEZALC: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case MIPS_INS_BNE: // bne $s, $t, offset case MIPS_INS_BNEZ: r_strbuf_appendf (&op->esil, "%s,%s,==,!,?{,%s,pc,=,}", ARG(0), ARG(1), ARG(2)); break; case MIPS_INS_BEQ: case MIPS_INS_BEQZ: case MIPS_INS_BEQZC: case MIPS_INS_BEQZALC: r_strbuf_appendf (&op->esil, "%s,%s,==,?{,%s,pc,=,}", ARG(0), ARG(1), ARG(2)); break; case MIPS_INS_BTEQZ: case MIPS_INS_BTNEZ: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case MIPS_INS_MOV: case MIPS_INS_MOVE: case MIPS_INS_MOVF: case MIPS_INS_MOVT: case MIPS_INS_MOVZ: if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), REG(0)); } else { r_strbuf_appendf (&op->esil, ","); } break; case MIPS_INS_FSUB: case MIPS_INS_SUB: if (REG(0)[0]!='z'){ r_strbuf_appendf(&op->esil, "%s,%s,>,?{,$$,}{,%s,%s,-,%s,=",ARG(2), ARG(1), ARG(1), ARG(2), ARG(0)); } else { r_strbuf_appendf (&op->esil, ","); } break; case MIPS_INS_SUBU: case MIPS_INS_NEGU: case MIPS_INS_DSUB: case MIPS_INS_DSUBU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,-,%s,=", arg1, arg2, arg0); } break; /** signed -- sets overflow flag */ case MIPS_INS_ADD: { if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "32,%s,%s,+,>>,0,>,?{,$$,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); } else { r_strbuf_appendf (&op->esil, ","); } } break; case MIPS_INS_ADDI: if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "32,%s,0xffffffff,&,%s,+,>>,0,>,?{,$$,}{,%s,%s,+,%s,=,}", ARG(2), ARG(1), ARG(2), ARG(1), ARG(0)); } else { r_strbuf_appendf (&op->esil, ","); } break; case MIPS_INS_DADD: case MIPS_INS_DADDI: /** unsigned */ case MIPS_INS_ADDU: case MIPS_INS_ADDIU: case MIPS_INS_DADDIU: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", arg2, arg1, arg0); } else { r_strbuf_appendf (&op->esil, ","); } } break; case MIPS_INS_LI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x",%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LUI: r_strbuf_appendf (&op->esil, "0x%"PFMT64x"0000,%s,=", IMM(1), ARG(0)); break; case MIPS_INS_LB: case MIPS_INS_LBU: //one of these is wrong r_strbuf_appendf (&op->esil, "%s,[1],%s,=", ARG(1), REG(0)); break; case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWU: case MIPS_INS_LWX: case MIPS_INS_LH: case MIPS_INS_LHX: case MIPS_INS_LL: case MIPS_INS_LLD: case MIPS_INS_LD: case MIPS_INS_LDI: case MIPS_INS_LDL: case MIPS_INS_LDC1: case MIPS_INS_LDC2: r_strbuf_appendf (&op->esil, "%s,[4],%s,=", ARG(1), REG(0)); break; case MIPS_INS_AND: case MIPS_INS_ANDI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); r_strbuf_appendf (&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0); } break; case MIPS_INS_OR: case MIPS_INS_ORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "%s,%s,|,%s,=", arg2, arg1, arg0); } else { r_strbuf_appendf (&op->esil, ","); } } break; case MIPS_INS_XOR: case MIPS_INS_XORI: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "%s,%s,^,%s,=", arg2, arg1, arg0); } else { r_strbuf_appendf (&op->esil, ","); } } break; case MIPS_INS_NOR: { const char *arg0 = ARG(0); const char *arg1 = ARG(1); const char *arg2 = ARG(2); if (REG(0)[0]!='z'){ r_strbuf_appendf (&op->esil, "%s,%s,|,0xffffffff,^,%s,=", arg2, arg1, arg0); } else { r_strbuf_appendf (&op->esil, ","); } } break; case MIPS_INS_SLTU: r_strbuf_appendf (&op->esil, "%s,%s,<,%s,=", ARG(1), ARG(2), ARG(0)); break; case MIPS_INS_SLTIU: { r_strbuf_appendf (&op->esil, "%s,0xffffffff,&,%s,0xffffffff,<,?{%s,1,=,}{,%s,0,=,}", ARG(1), ARG(2), ARG(0), ARG(0)); } break; } return 0; }
static void opex(RStrBuf *buf, csh handle, cs_insn *insn) { int i; r_strbuf_init (buf); r_strbuf_append (buf, "{"); cs_m68k *x = &insn->detail->m68k; r_strbuf_append (buf, "\"operands\":["); for (i = 0; i < x->op_count; i++) { cs_m68k_op *op = &x->operands[i]; if (i > 0) { r_strbuf_append (buf, ","); } r_strbuf_append (buf, "{"); switch (op->type) { case M68K_OP_REG: r_strbuf_append (buf, "\"type\":\"reg\""); r_strbuf_appendf (buf, ",\"value\":\"%s\"", cs_reg_name (handle, op->reg)); break; case M68K_OP_IMM: r_strbuf_append (buf, "\"type\":\"imm\""); r_strbuf_appendf (buf, ",\"value\":%"PFMT64d, op->imm); break; case M68K_OP_MEM: r_strbuf_append (buf, "\"type\":\"mem\""); if (op->mem.base_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.base_reg)); } if (op->mem.index_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.index_reg)); } if (op->mem.in_base_reg != M68K_REG_INVALID) { r_strbuf_appendf (buf, ",\"base_reg\":\"%s\"", cs_reg_name (handle, op->mem.in_base_reg)); } r_strbuf_appendf (buf, ",\"in_disp\":%"PFMT64d"", op->mem.in_disp); r_strbuf_appendf (buf, ",\"out_disp\":%"PFMT64d"", op->mem.out_disp); r_strbuf_appendf (buf, ",\"disp\":%"PFMT64d"", (st64)op->mem.disp); r_strbuf_appendf (buf, ",\"scale\":%"PFMT64d"", (st64)op->mem.scale); r_strbuf_appendf (buf, ",\"bitfield\":%"PFMT64d"", (st64)op->mem.bitfield); r_strbuf_appendf (buf, ",\"width\":%"PFMT64d"", (st64)op->mem.width); r_strbuf_appendf (buf, ",\"offset\":%"PFMT64d"", (st64)op->mem.offset); r_strbuf_appendf (buf, ",\"index_size\":%"PFMT64d"", (st64)op->mem.index_size); break; default: r_strbuf_append (buf, "\"type\":\"invalid\""); break; } r_strbuf_append (buf, "}"); } r_strbuf_append (buf, "]}"); }
static int analop_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) { int i; char str[32][32]; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); switch (insn->detail->arm.cc) { case ARM_CC_AL: // no condition break; case ARM_CC_EQ: r_strbuf_setf (&op->esil, "zf,0,?,"); break; case ARM_CC_NE: r_strbuf_setf (&op->esil, "zf,!,0,?,"); break; case ARM_CC_GT: case ARM_CC_LE: break; default: break; } // TODO: PREFIX CONDITIONAL switch (insn->id) { case ARM_INS_PUSH: // TODO: increment stack case ARM_INS_STM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4],", REG (i), ARG (0), i*4); } break; case ARM_INS_POP: // TODO: decrement stack case ARM_INS_LDM: for (i=1; i<insn->detail->arm.op_count; i++) { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", ARG (0), i*4, REG (i)); } break; case ARM_INS_CMP: r_strbuf_appendf (&op->esil, "%s,%s,==", ARG(1), ARG(0)); break; case ARM_INS_LSL: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,<<=", ARG(1), ARG(0)); break; case ARM_INS_LSR: // suffix 'S' forces conditional flag to be updated r_strbuf_appendf (&op->esil, "%s,%s,>>=", ARG(1), ARG(0)); break; case ARM_INS_B: r_strbuf_appendf (&op->esil, "%s,pc,=", ARG(0)); break; case ARM_INS_BL: case ARM_INS_BLX: r_strbuf_appendf (&op->esil, "4,pc,+,lr,=,%s,pc,=", ARG(0)); break; case ARM_INS_MOV: case ARM_INS_MOVS: r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), REG(0)); break; case ARM_INS_SSUB16: case ARM_INS_SSUB8: case ARM_INS_SUB: r_strbuf_appendf (&op->esil, "%s,%s,-=", ARG(1), ARG(0)); break; case ARM_INS_SADD16: case ARM_INS_SADD8: case ARM_INS_ADD: if (!strcmp (ARG(0),ARG(1))) { r_strbuf_appendf (&op->esil, "%s,%s,+=", ARG(2), ARG(0)); } else if (!strcmp (ARG(2),"0")) { r_strbuf_appendf (&op->esil, "%s,%s,=", ARG(1), ARG(0)); } else { r_strbuf_appendf (&op->esil, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0)); } break; case ARM_INS_STR: r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[4]", REG(0), MEMBASE(1), MEMDISP(1)); break; case ARM_INS_STRB: r_strbuf_appendf (&op->esil, "%s,%s,%d,+,=[1]", REG(0), MEMBASE(1), MEMDISP(1)); break; case ARM_INS_LDR: if (MEMDISP(1)<0) { if (REGBASE(1) == ARM_REG_PC) { r_strbuf_appendf (&op->esil, "8,%s,+,%d,-,[4],%s,=", MEMBASE(1), -MEMDISP(1), REG(0)); switch (a->bits) { case 32: op->ptr = addr + 8 - MEMDISP(1); op->refptr = 4; break; case 16: if ( (addr % 4) == 0 ) { op->ptr = addr + 4 - MEMDISP(1); op->refptr = 4; } else { op->ptr = addr + 2 - MEMDISP(1); op->refptr = 4; } break; } } else { r_strbuf_appendf (&op->esil, "%s,%d,-,[4],%s,=", MEMBASE(1), -MEMDISP(1), REG(0)); } } else { if (REGBASE(1) == ARM_REG_PC) { r_strbuf_appendf (&op->esil, "8,%s,+,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); if (a->bits==32) { op->ptr = addr + 8 + MEMDISP(1); op->refptr = 4; } else if (a->bits==16) { if ( (addr % 4) == 0 ) { op->ptr = addr + 4 + MEMDISP(1); op->refptr = 4; } else { op->ptr = addr + 2 + MEMDISP(1); op->refptr = 4; } } } else { r_strbuf_appendf (&op->esil, "%s,%d,+,[4],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); } op->refptr = 4; } break; case ARM_INS_LDRD: case ARM_INS_LDRB: r_strbuf_appendf (&op->esil, "%s,%d,+,[1],%s,=", MEMBASE(1), MEMDISP(1), REG(0)); break; default: break; } return 0; }