- Adds endian aware functions - Removes references to host endian - Uses binary detected endianness else tries LE and restricts by RAsmPlugin - Fixes gdb debugger endianness when debugging BE qemu gdbserver Signed-off-by: Damien Zammit <damien@zamaudio.com>
347 lines
7.5 KiB
C
347 lines
7.5 KiB
C
#include <r_types.h>
|
|
#include <r_util.h>
|
|
|
|
#include "propeller_disas.h"
|
|
|
|
static const char *instrs[] = {
|
|
[PROP_ABS] = "abs",
|
|
[PROP_ABSNEG] = "absneg",
|
|
[PROP_ADD] = "add",
|
|
[PROP_ADDABS] = "addabs",
|
|
[PROP_ADDS] = "adds",
|
|
[PROP_ADDSX] = "addsx",
|
|
[PROP_ADDX] = "addx",
|
|
[PROP_AND] = "and",
|
|
[PROP_ANDN] = "andn",
|
|
[PROP_CALL] = "call",
|
|
[PROP_CMP] = "cmp",
|
|
[PROP_CMPS] = "cmps",
|
|
[PROP_CMPSUB] = "cmpsub",
|
|
[PROP_CMPSX] = "cmpsx",
|
|
[PROP_CMPX] = "cmpx",
|
|
[PROP_DJNZ] = "djnz",
|
|
[PROP_HUBOP] = "hubop",
|
|
[PROP_MOV] = "mov",
|
|
[PROP_MAX] = "max",
|
|
[PROP_MAXS] = "maxs",
|
|
[PROP_MIN] = "min",
|
|
[PROP_MINS] = "mins",
|
|
[PROP_MOVD] = "movd",
|
|
[PROP_MOVI] = "movi",
|
|
[PROP_MOVS] = "movs",
|
|
[PROP_MUXC] = "muxc",
|
|
[PROP_MUXNC] = "muxnc",
|
|
[PROP_MUXNZ] = "muxnz",
|
|
[PROP_MUXZ] = "muxz",
|
|
[PROP_NEG] = "neg",
|
|
[PROP_NEGC] = "negc",
|
|
[PROP_NEGNC] = "negnc",
|
|
[PROP_NEGNZ] = "negnz",
|
|
[PROP_NEGZ] = "negz",
|
|
[PROP_OR] = "or",
|
|
[PROP_RCL] = "rcl",
|
|
[PROP_RCR] = "rcr",
|
|
[PROP_RDBYTE] = "rdbyte",
|
|
[PROP_RDLONG] = "rdlong",
|
|
[PROP_RDWORD] = "rdword",
|
|
[PROP_RET] = "ret",
|
|
[PROP_REV] = "rev",
|
|
[PROP_ROL] = "rol",
|
|
[PROP_ROR] = "ror",
|
|
[PROP_SAR] = "sar",
|
|
[PROP_SHL] = "shl",
|
|
[PROP_SHR] = "shr",
|
|
[PROP_SUBABS] = "subabs",
|
|
[PROP_SUBS] = "subs",
|
|
[PROP_SUBSX] = "subsx",
|
|
[PROP_SUMC] = "sumc",
|
|
[PROP_SUMNC] = "sumnc",
|
|
[PROP_SUMNZ] = "sumnz",
|
|
[PROP_SUMZ] = "sumz",
|
|
[PROP_TEST] = "test",
|
|
[PROP_TESTN] = "testn",
|
|
[PROP_TJZ] = "tjz",
|
|
[PROP_WAITCNT] = "waitcnt",
|
|
[PROP_WAITVID] = "waitvid",
|
|
[PROP_XOR] = "xor",
|
|
};
|
|
|
|
static const char *ext_instrs[] = {
|
|
[PROP_CLKSET] = "clkset",
|
|
[PROP_COGID] = "cogid",
|
|
[PROP_COGINIT] = "coginit",
|
|
[PROP_COGSTOP] = "cogstop",
|
|
[PROP_LOCKCLR] = "lockclr",
|
|
[PROP_LOCKNEW] = "locknew",
|
|
[PROP_LOCKRET] = "lockret",
|
|
[PROP_LOCKSET] = "lockset",
|
|
};
|
|
|
|
static const char *conditions[] = {
|
|
[PROP_IF_ALWAYS] = "",
|
|
[PROP_IF_NEVER] = "",
|
|
[PROP_IF_E] = "if_e",
|
|
[PROP_IF_NE] = "if_ne",
|
|
[PROP_IF_A] = "if_a",
|
|
[PROP_IF_B] = "if_b",
|
|
[PROP_IF_AE] = "if_ae",
|
|
[PROP_IF_BE] = "if_be",
|
|
[PROP_IF_C_EQ_Z] = "if_c_eq_z",
|
|
[PROP_IF_C_NE_Z] = "if_c_ne_z",
|
|
[PROP_IF_C_AND_Z] = "if_c_and_z",
|
|
[PROP_IF_C_AND_NZ] = "if_c_and_nz",
|
|
[PROP_IF_NC_AND_Z] = "if_nc_and_z",
|
|
[PROP_IF_NZ_OR_NC] = "if_nc_or_nz",
|
|
[PROP_IF_NZ_OR_C] = "if_nz_or_c",
|
|
[PROP_IF_Z_OR_NC] = "if_z_or_c",
|
|
};
|
|
|
|
static ut16 get_opcode (ut32 instr) {
|
|
return instr >> 26;
|
|
}
|
|
|
|
static ut16 get_opcode_ext (ut32 instr) {
|
|
return (instr & 0x7) | (instr >> 23);
|
|
}
|
|
|
|
static ut16 get_src (ut32 instr) {
|
|
return instr & 0x1FF;
|
|
}
|
|
|
|
static ut16 get_dst (ut32 instr) {
|
|
return ((instr >> 9) & 0x1FF) << 2;
|
|
}
|
|
|
|
static int is_immediate (ut32 instr) {
|
|
return instr & 0x00400000;
|
|
}
|
|
|
|
static int decode_ext_cmd (struct propeller_cmd *cmd, ut32 instr) {
|
|
ut16 opcode;
|
|
|
|
opcode = get_opcode_ext (instr);
|
|
|
|
switch (opcode) {
|
|
case PROP_CLKSET:
|
|
case PROP_COGID:
|
|
case PROP_COGINIT:
|
|
case PROP_COGSTOP:
|
|
case PROP_LOCKCLR:
|
|
case PROP_LOCKNEW:
|
|
case PROP_LOCKRET:
|
|
case PROP_LOCKSET:
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1,
|
|
"%s", ext_instrs[PROP_CLKSET]);
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1,
|
|
"%d", get_dst (instr));
|
|
return 4;
|
|
break;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static ut8 get_zcri (ut32 instr) {
|
|
return (instr >> 22) & 0xf;
|
|
}
|
|
|
|
static ut8 get_con (ut32 instr) {
|
|
return (instr >> 18) & 0xf;
|
|
}
|
|
|
|
static void decode_prefix (struct propeller_cmd *cmd, ut32 instr) {
|
|
ut8 prefix = (instr >> 18) & 0xF;
|
|
|
|
snprintf (cmd->prefix, 15, "%s", conditions[prefix]);
|
|
cmd->prefix[15] = '\0';
|
|
}
|
|
|
|
static int decode_jmp (struct propeller_cmd *cmd, ut32 instr) {
|
|
ut16 opcode;
|
|
ut8 zcri;
|
|
int ret = 1;
|
|
opcode = get_opcode (instr);
|
|
switch (opcode) {
|
|
case PROP_JMP:
|
|
zcri = get_zcri (instr);
|
|
if (zcri & 0x2) {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1,
|
|
"%s", "jmpret");
|
|
if (zcri & 1) {
|
|
cmd->dst = get_dst (instr) << 2;
|
|
cmd->src = get_src (instr) << 2;
|
|
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1,
|
|
"0x%x, #0x%x", get_dst (instr), get_src (instr) << 2);
|
|
} else {
|
|
cmd->src = get_src (instr) << 2;
|
|
cmd->dst = get_dst (instr) << 2;
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1,
|
|
"0x%x, 0x%x", get_dst (instr), get_src (instr) << 2);
|
|
}
|
|
} else {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1,
|
|
"%s", "jmp");
|
|
if (zcri & 1) {
|
|
cmd->src = get_src (instr) << 2;
|
|
cmd->immed = 1;
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1,
|
|
"#0x%x", get_src (instr) << 2);
|
|
} else {
|
|
cmd->immed = 0;
|
|
cmd->src = get_src (instr) << 2;
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1,
|
|
"0x%x", get_src (instr) << 2);
|
|
}
|
|
}
|
|
|
|
ret = 4;
|
|
break;
|
|
}
|
|
|
|
|
|
return ret;
|
|
}
|
|
|
|
int propeller_decode_command(const ut8 *instr, struct propeller_cmd *cmd)
|
|
{
|
|
int ret = -1;
|
|
ut32 in;
|
|
ut16 opcode;
|
|
|
|
in = r_read_be32 (instr);
|
|
|
|
opcode = get_opcode (in);
|
|
|
|
if (!get_con (in)) {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN, "nop");
|
|
cmd->operands[0] = '\0';
|
|
return 4;
|
|
}
|
|
|
|
switch (opcode) {
|
|
case PROP_ABS:
|
|
case PROP_ABSNEG:
|
|
case PROP_ADD:
|
|
case PROP_ADDABS:
|
|
case PROP_ADDS:
|
|
case PROP_ADDSX:
|
|
case PROP_ADDX:
|
|
case PROP_AND:
|
|
case PROP_ANDN:
|
|
case PROP_CMP:
|
|
case PROP_CMPS:
|
|
case PROP_CMPSUB:
|
|
case PROP_CMPSX:
|
|
case PROP_CMPX:
|
|
case PROP_DJNZ:
|
|
case PROP_MAX:
|
|
case PROP_MAXS:
|
|
case PROP_MIN:
|
|
case PROP_MINS:
|
|
case PROP_MOV:
|
|
case PROP_MOVD:
|
|
case PROP_MOVI:
|
|
case PROP_MOVS:
|
|
case PROP_MUXC:
|
|
case PROP_MUXNC:
|
|
case PROP_MUXNZ:
|
|
case PROP_MUXZ:
|
|
case PROP_NEG:
|
|
case PROP_NEGC:
|
|
case PROP_NEGNC:
|
|
case PROP_NEGNZ:
|
|
case PROP_NEGZ:
|
|
case PROP_OR:
|
|
case PROP_RCL:
|
|
case PROP_RCR:
|
|
case PROP_RDBYTE:
|
|
case PROP_RDLONG:
|
|
case PROP_RDWORD:
|
|
//case PROP_RET:
|
|
case PROP_REV:
|
|
case PROP_ROL:
|
|
case PROP_ROR:
|
|
case PROP_SAR:
|
|
case PROP_SHL:
|
|
case PROP_SHR:
|
|
case PROP_SUBABS:
|
|
case PROP_SUBS:
|
|
case PROP_SUBSX:
|
|
//case PROP_SUBX:
|
|
case PROP_SUMC:
|
|
case PROP_SUMNC:
|
|
case PROP_SUMNZ:
|
|
case PROP_SUMZ:
|
|
//case PROP_TEST:
|
|
case PROP_TJZ:
|
|
case PROP_WAITCNT:
|
|
case PROP_WAITPEQ:
|
|
case PROP_WAITPNE:
|
|
case PROP_WAITVID:
|
|
case PROP_XOR:
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1, "%s",
|
|
instrs[opcode]);
|
|
|
|
if ((opcode == PROP_RDBYTE || opcode == PROP_RDLONG ||
|
|
opcode == PROP_RDWORD) && (!(get_zcri (in) & 0x2))) {
|
|
cmd->instr[0] = 'w';
|
|
cmd->instr[1] = 'r';
|
|
}
|
|
|
|
if (opcode == PROP_SUB && in & 0x08000000) {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1, "sub");
|
|
} else if (opcode == PROP_SUBX && in & 0x08000000) {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1, "subx");
|
|
}
|
|
|
|
if (is_immediate (in)) {
|
|
cmd->src = get_src (in);
|
|
cmd->dst = get_dst (in);
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, #%d",
|
|
get_dst (in), get_src (in));
|
|
} else {
|
|
cmd->src = get_src (in) << 2;
|
|
cmd->dst = get_dst (in);
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, 0x%x",
|
|
get_dst (in), get_src (in) << 2);
|
|
}
|
|
|
|
ret = 4;
|
|
break;
|
|
case PROP_HUBOP:
|
|
ret = decode_ext_cmd (cmd, in);
|
|
if (ret == -1) {
|
|
snprintf (cmd->instr, PROP_INSTR_MAXLEN - 1, "%s",
|
|
instrs[opcode]);
|
|
|
|
if (is_immediate (in)) {
|
|
cmd->src = get_src (in);
|
|
cmd->dst = get_dst (in);
|
|
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, #%d",
|
|
get_dst (in) << 2, get_src (in));
|
|
} else {
|
|
cmd->src = get_src (in);
|
|
cmd->dst = get_dst (in);
|
|
|
|
snprintf (cmd->operands, PROP_INSTR_MAXLEN - 1, "0x%x, 0x%x",
|
|
get_dst (in), get_src (in));
|
|
}
|
|
|
|
ret = 4;
|
|
}
|
|
break;
|
|
case PROP_JMP:
|
|
ret = decode_jmp (cmd, in);
|
|
break;
|
|
}
|
|
|
|
cmd->opcode = opcode;
|
|
|
|
if (ret > 0) {
|
|
decode_prefix (cmd, in);
|
|
}
|
|
|
|
return ret;
|
|
}
|