rizin/libr/asm/arch/tms320/c55x_plus/c55plus_decode.c
2016-01-03 02:05:26 +01:00

883 lines
20 KiB
C

/* c55plus - LGPL - Copyright 2013 - th0rpe */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <r_types.h>
#include "ins.h"
#include "decode.h"
#include "utils.h"
#include "hashtable.h"
#include "decode_funcs.h"
extern st8 *ins_str[];
extern ut32 ins_buff_len;
static ut32 get_q_bits(ut32 val, st8 *ins, ut32 ins_len, int *err_code) {
ut32 res = 0;
if (!strncasecmp(ins, "q_MMAP", 6)) {
res = val & 1;
} else if (!strncasecmp(ins, "q_LOCK", 6)) {
res = val & 1;
} else if (!strncasecmp(ins, "q_LINR", 6)) {
res = (val >> 2) & 1;
} else if (!strncasecmp(ins, "q_CIRC", 6)) {
res = (val >> 3) & 1;
} else if (!strncasecmp(ins, "q_PORT_READ", 11)) {
res = (val >> 4) & 1;
} else if (!strncasecmp(ins, "q_PORT_WRITE", 12)) {
res = (val >> 5) & 1;
} else if (!strncasecmp(ins, "q_XPORT_READ", 12)) {
res = (val >> 6) & 1;
} else if (!strncasecmp(ins, "q_XPORT_WRITE", 13)) {
res = (val >> 7) & 1;
} else if (!strncasecmp(ins, "q_SAT", 5)) {
res = (val >> 8) & 1;
} else if (!strncasecmp(ins, "q_XC0", 5)) {
res = (val >> 9) & 1;
} else if (!strncasecmp(ins, "q_XC1", 5)) {
res = (val >> 10) & 1;
} else {
/* INVALID CONDITION */
fprintf(stderr, "Invalid token %s\n", ins); *err_code = -1;
}
return res;
}
/*
a2 = 0x223;
0x800 = valor que se crea en sub_40BAE0<) con and 0xfffff800
*/
static ut32 get_ins_bits(ut32 hash_code, ut32 ins_pos, st8 *ins,
ut32 ins_len, ut32 magic_value, int *err_code)
{
ut32 res = 0;
ut8 op_b;
ut32 len, x, i;
st8 *op_str, *aux;
if (ins[0] == 'q')
return get_q_bits(magic_value, ins, ins_len, err_code);
op_str = ins_str[1 + hash_code * 4];
//printf("OPSTR => %s %d\n", ins, ins_len);
x = 0;
for (i = 0; i < ins_len; i++) {
aux = strchr(&op_str[x], ins[i]);
if (!aux) {
aux = strchr(op_str, ins[i]);
if (!aux) {
fprintf(stderr, "Invalid token %s\n", ins); *err_code = -1; return 0;
}
}
len = (unsigned int)(aux - op_str);
//printf("INS_POS: %d POS: %d\n", ins_pos, len / 8);
op_b = get_ins_part(ins_pos + len / 8, 1);
//printf("OPP: %x\n", op_b);
x = len + 1;
res = (res * 2) | ((op_b >> ((1023 - len) % 8)) & 1);
if (!op_str[x])
x = 0;
}
if (C55PLUS_DEBUG) {
printf("INS_BITS => 0x%x\n", res);
getchar();
}
return res;
}
static bool check_arg(ut32 ins_bits, int *err_code) {
bool res = false;
if ((ins_bits <= 31) | (ins_bits >= 128 && ins_bits < 160)) {
res = true;
} else if (ins_bits >= 32 && ins_bits <= 252) {
res = false;
} else {
fprintf(stderr, "Invalid arg: %u\n", ins_bits);
*err_code = -1;
}
return res;
}
static char *decode_regis(st8 *reg_arg, st32 hash_code, ut32 ins_bits,
ut32 *ret_ins_bits, int *err_code)
{
ut8 reg_type;
st8 *res;
reg_type = *reg_arg;
res = NULL;
//printf("REG_TYPE %d %d\n", reg_type, ins_bits);
switch (reg_type) {
case 33:
res = get_reg_name_1((ins_bits >> 1) |
((ins_bits & 1) << 6));
break;
case 100:
if (strncasecmp(reg_arg, "d(ALLx", 6)) {
fprintf(stderr, "invalid register! %s\n", reg_arg);
*err_code = -1;
return NULL;
}
res = (check_arg(ins_bits, err_code) != 0 && *err_code == 0)? strdup("dbl(") : NULL;
if (*err_code < 0) {
return NULL;
}
break;
case 41:
if (strncasecmp(reg_arg, ")ALLx", 5)) {
fprintf(stderr, "invalid register! %s\n", reg_arg);
*err_code = -1;
return NULL;
}
res = (check_arg(ins_bits, err_code) && *err_code == 0)? strdup(")") : NULL;
if (*err_code < 0) {
return NULL;
}
break;
case 65:
if (!strncasecmp(reg_arg, "ACLH", 4)) {
res = get_reg_name_1(ins_bits + 64);
} else if (!strncasecmp(reg_arg, "ACxP", 4)) {
res = get_reg_name_1(ins_bits + 1);
} else if (!strncasecmp(reg_arg, "ACx", 3) ||
!strncasecmp(reg_arg, "ADR", 3) ||
!strncasecmp(reg_arg, "ALL", 3) /* 430ADC */
) {
res = get_reg_name_1(ins_bits);
}
if (hash_code == 0xDF || hash_code == 0xE0) {
*ret_ins_bits = ins_bits;
}
break;
case 68:
res = get_reg_name_1(ins_bits + 32);
break;
case 77:
if (!strncasecmp(reg_arg, "MA", 2) || !strncasecmp(reg_arg, "MR", 2)) {
res = get_reg_name_1(ins_bits);
} else {
res = get_reg_name_2(ins_bits);
}
break;
case 83:
res = get_reg_name_1(ins_bits);
break;
case 82:
if (!strncasecmp(reg_arg, "RA", 2) || !strncasecmp(reg_arg, "RL", 2)) {
res = get_reg_name_1(ins_bits);
} else if (!strncasecmp(reg_arg, "RLP", 3) || !strncasecmp(reg_arg, "RxP", 3)) {
res = get_reg_name_1(ins_bits + 1);
} else if (!strncasecmp(reg_arg, "RX", 2)) {
res = get_reg_name_1(ins_bits);
} else {
res = get_reg_name_2(ins_bits);
}
break;
case 84:
res = get_reg_name_1(ins_bits + 48);
break;
case 87:
if (!strncasecmp(reg_arg, "WD", 2)) {
res = get_reg_name_2(ins_bits);
} else if (!strncasecmp(reg_arg, "WA", 2)) {
res = get_reg_name_1(ins_bits);
} else {
res = NULL;
}
break;
case 88:
if (!strncasecmp(reg_arg, "XR", 2)) {
res = get_reg_name_3(ins_bits);
} else if (!strncasecmp(reg_arg, "XD", 2)) {
res = get_reg_name_2(ins_bits + 32);
} else {
res = NULL;
}
break;
default:
res = NULL;
break;
}
return res;
}
static st8 *decode_ins(st32 hash_code, ut32 ins_pos, ut32 ins_off, ut32 *ins_len_dec,
ut32 *reg_len_dec, ut32 *ret_ins_bits, ut32 magic_value, ut8 two_ins, int *err_code)
{
ut32 ins_len;
st8 *ins, *pos;
st8 token_aux[80];
ut32 i, len;
st8 *reg = NULL;
st8 *res_decode = NULL;
st8 *aux = NULL;
// get instruction length
ins_len = get_ins_len(get_ins_part(ins_pos + ins_off, 1));
// get pseudo instruction
ins = ins_str[1 + 2 + hash_code * 4];
if (ins == NULL /*|| ins_str[4 * hash_code] == 0*/) {
fprintf(stderr, "Invalid instruction %s /hash %x\n", ins, hash_code);
*err_code = -1;
return NULL;
}
if (hash_code == 0x19C) {
res_decode = get_token_decoded(hash_code, "MMMMxxxxmm", 10, NULL, ret_ins_bits,
reg_len_dec, magic_value, ins_pos + ins_off, ins_len, two_ins, err_code);
if (*err_code < 0) {
return NULL;
}
}
if (C55PLUS_DEBUG)
printf("PSEUDO INS %s\n", ins);
pos = ins;
// instruction length
*ins_len_dec = ins_len;
while (*pos) {
if (*pos == '`') {
pos++;
aux = strchr(pos, '`');
if (aux == NULL || pos == aux) {
fprintf(stderr, "Invalid instruction %s\n", ins);
free (res_decode);
*err_code = -1;
return NULL;
}
len = (ut32)(size_t)(aux-pos);
if (len >= 80) {
fprintf(stderr, "Invalid length token %d\n", len);
free (res_decode);
*err_code = -1;
return NULL;
}
memcpy(token_aux, pos, len);
token_aux[len] = '\0';
pos = aux;
if (C55PLUS_DEBUG)
printf("TOKEN AUX: %s\n", token_aux);
reg = NULL;
for (i = 0; i < len; i++) {
if (token_aux[i] == ',') {
len = (unsigned int)(size_t)(&token_aux[i] - token_aux);
reg = &token_aux[i + 1];
if (C55PLUS_DEBUG)
printf("REG : %s\n", reg);
break;
}
}
aux = get_token_decoded(hash_code, token_aux, len, reg, ret_ins_bits,
reg_len_dec, magic_value, ins_pos + ins_off, ins_len, two_ins, err_code);
if (*err_code < 0) {
return NULL;
}
res_decode = strcat_dup(res_decode, aux, 3);
if (C55PLUS_DEBUG) {
printf("RET TOKEN %s\n", res_decode);
}
} else {
token_aux[0] = *pos;
token_aux[1] = '\0';
res_decode = strcat_dup(res_decode, token_aux, 1);
}
pos++;
}
if (C55PLUS_DEBUG)
printf("RESULT DECODE: %s\n", res_decode);
return res_decode;
}
static bool is_hash(st32 hash_code)
{
bool ret;
switch(hash_code) {
case 0xE8:
case 0xE9:
case 0xEA:
case 0xEC:
case 0x1A8:
case 0x1DC:
case 0x1E1:
case 0x1E2:
case 0x1E3:
case 0x1E4:
ret = 1;
break;
default:
ret = 0;
}
return ret;
}
void set_magic_value(ut32 *magic_value, st32 hash_code, int *err_code)
{
switch(hash_code) {
case 232:
*magic_value |= 1;
break;
case 424:
*magic_value |= 2;
break;
case 236:
*magic_value |= 4;
break;
case 233:
*magic_value |= 0x10;
break;
case 234:
*magic_value |= 0x20;
break;
case 483:
*magic_value |= 0x40;
break;
case 484:
*magic_value |= 0x80;
break;
case 476:
*magic_value |= 0x100;
break;
case 481:
*magic_value |= 0x200;
break;
case 482:
*magic_value |= 0x400;
break;
default:
fprintf(stderr, "invalid hash code 0x%x for magic value 0x%x\n", hash_code, *magic_value);
*err_code = -1;
}
}
static st8 *do_decode(ut32 ins_off, ut32 ins_pos, ut32 two_ins, ut32 *next_ins_pos,
st32 *ins_hash_code, int *err_code)
{
st32 hash_code, hash_aux;
ut32 reg_len_dec, ins_len_dec, ret_ins_bits;
st8 *ins_res = NULL, *ins_aux = NULL;
ut32 magic_value = 0x800;
*next_ins_pos = 0;
reg_len_dec = 0;
ret_ins_bits = 0;
ins_len_dec = 0;
hash_code = get_hash_code(ins_pos + ins_off);
if (is_hash(hash_code)) {
hash_aux = hash_code;
ins_off++;
set_magic_value(&magic_value, hash_code, err_code);
if (*err_code < 0) {
return NULL;
}
hash_code = get_hash_code(ins_pos + ins_off);
*next_ins_pos = 1;
} else {
hash_aux = 0x223;
}
if (ins_hash_code != NULL) {
*ins_hash_code = hash_code;
}
if (C55PLUS_DEBUG) {
printf("MAGIC VALUE 0x%x\n", 0x800);
}
if (hash_aux == 0x1E1 || hash_aux == 0x1E2) {
ins_aux = decode_ins(hash_aux, ins_pos, ins_off, &ins_len_dec, &reg_len_dec,
&ret_ins_bits, magic_value, two_ins, err_code);
if(*err_code < 0) {
return NULL;
}
ins_aux = strcat_dup(ins_aux, " ", 1);
}
if (hash_code == 0x223) {
ins_res = strcat_dup(ins_aux, ".byte 0x", 1);
ins_aux = get_hex_str(get_ins_part(ins_pos, 1));
ins_res = strcat_dup(ins_res, ins_aux, 2);
*next_ins_pos = *next_ins_pos + 1;
} else {
free (ins_aux);
ins_aux = decode_ins(hash_code, ins_pos, ins_off, &ins_len_dec,
&reg_len_dec, &ret_ins_bits, magic_value, two_ins, err_code);
if (*err_code < 0) {
free (ins_aux);
return NULL;
}
ins_res = strcat_dup(ins_aux, ins_res, 1);
//printf("NEXT POS %d %d\n", ins_len_dec, reg_len_dec);
//getchar();
*next_ins_pos += ins_len_dec; // reg_len_dec;
}
return ins_res;
}
st8 *c55plus_decode(ut32 ins_pos, ut32 *next_ins_pos) {
ut8 opcode, two_ins = 0;
ut32 next_ins1_pos, next_ins2_pos;
st32 hash_code;
st8 *ins1, *ins2, *aux, *ins_res;
int err_code;
if (ins_pos >= ins_buff_len) {
return NULL;
}
ins_res = NULL;
err_code = 0;
opcode = get_ins_part(ins_pos, 1);
if ((opcode & 0xF0) == 0x30) {
two_ins = opcode & 0x0F;
if(two_ins < 4) {
two_ins += 0xF;
}
} else {
two_ins = 0;
}
// two instruction execution?
if (two_ins) {
ins1 = do_decode(1, ins_pos, two_ins, &next_ins1_pos, &hash_code, &err_code);
if (err_code < 0) {
free (ins1);
return NULL;
}
ins2 = do_decode(next_ins1_pos + 1, ins_pos, two_ins, &next_ins2_pos, NULL, &err_code);
if (err_code < 0) {
free (ins1);
free (ins2);
return NULL;
}
*next_ins_pos = next_ins2_pos;
if (hash_code == 0xF0 || hash_code == 0xF1) {
aux = strcat_dup(ins2, " || ", 1);
ins_res = strcat_dup(aux, ins1, 1);
free(ins1);
} else {
aux = strcat_dup(ins1, " || ", 1);
ins_res = strcat_dup(aux, ins2, 1);
free(ins2);
}
*next_ins_pos = next_ins1_pos + next_ins2_pos + 1;
if(*next_ins_pos != two_ins) {
//ins_res = strcat_dup(ins_res, " P-tag problem", 1);
err_code = -1;
free (ins_res);
return NULL;
}
} else {
ins_res = do_decode(0, ins_pos, two_ins, &next_ins1_pos, &hash_code, &err_code);
if (err_code < 0) {
free (ins_res);
return NULL;
}
*next_ins_pos = next_ins1_pos;
}
return ins_res;
}
static bool is_linear_circular(ut32 ins_bits) {
ut8 op, op2, op3;
op = (ins_bits >> 6) | 16 * (ins_bits & 3);
op2 = (ins_bits >> 2) & 0xF;
op3 = op2 & 0xF;
return (op == 26 || op == 30 || (op3 > 7 && op3 != 15));
}
static st8* get_token_decoded(st32 hash_code, st8 *ins_token, ut32 ins_token_len,
st8 *reg_arg, ut32 *ret_ins_bits, ut32 *ret_reg_len, ut32 magic_value,
ut32 ins_pos, ut32 ins_len, ut8 two_ins, int *err_code)
{
ut32 tok_op, ins_bits;
st8 *res = NULL;
st8 buff_aux[512];
st8 *aux = NULL;
ut32 ret_len = 0, flag;
*ret_ins_bits = 0;
*ret_reg_len = 0;
ins_bits = get_ins_bits(hash_code, ins_pos, ins_token, ins_token_len, magic_value, err_code);
if (*err_code < 0) {
return NULL;
}
tok_op = *ins_token - 0x23;
if (C55PLUS_DEBUG) {
printf("WAY ins_bits: OP = %d 0x%x %s %d %d\n", tok_op, ins_bits, ins_token, ins_token_len, ins_pos);
getchar();
}
switch (tok_op) {
case 30:
case 31:
case 32:
case 33:
case 43:
case 62:
case 63:
case 64:
case 65:
if (reg_arg == NULL || *reg_arg == '\0') {
res = strdup("<register>");
goto ret_decode;
}
res = decode_regis(reg_arg, hash_code, ins_bits, ret_ins_bits, err_code);
if (*err_code < 0) {
return NULL;
}
break;
case 35: res = ins_bits? strdup(" || far()") : NULL; break;
case 36: res = ins_bits? strdup(" || local()") : NULL; break;
case 37: res = get_opers(ins_bits); break;
case 38:
res = ins_bits? "lo" : "hi";
res = strdup(res);
break;
case 39: res = get_cmp_op(ins_bits); break;
case 40:
case 48:
sprintf(buff_aux, "#0x%x", (ins_bits << (32 - ins_token_len) >> (32 - ins_token_len)));
res = strdup(buff_aux);
break;
case 70:
case 72:
case 80:
if (reg_arg) {
if (*reg_arg == '!') {
res = get_reg_pair(ins_bits);
break;
} else if (!strncasecmp(reg_arg, "ST", 2)) {
res = get_status_regs_and_bits(reg_arg, ins_bits);
break;
}
}
if (hash_code == 0xDF || hash_code == 0xE0) {
*ret_ins_bits = ins_bits;
}
if (!reg_arg || *reg_arg != '-') {
sprintf(buff_aux, "#0x%lx", (long unsigned int)ins_bits);
} else {
sprintf(buff_aux, "-#0x%lx", (long unsigned int)ins_bits);
}
res = strdup(buff_aux);
if (!reg_arg || *reg_arg != 'm')
break;
res = strcat_dup(res, ")", 1);
res = strcat_dup("*(", res, 2);
if (magic_value & 0xC0) {
res = strcat_dup(res, ")", 1);
res = strcat_dup("volatile(", res, 2);
} else if (magic_value & 0x30) {
res = strcat_dup(res, ")", 1);
res = strcat_dup("port(", res, 2);
}
break;
case 41:
case 73:
if ((reg_arg && *reg_arg == 'L') || hash_code == 105 || hash_code == 7) {
if (C55PLUS_DEBUG) {
fprintf (stderr, "Ooops!!! look up address in sections!! %d", hash_code);
}
#if 0
if(two_ins) {
;//sections(ins_pos + two_ins);
} else {
;//sections(ins_pos + *ret_reg_len+ *ret_ins_bits);
}
#endif
}
if (reg_arg && *reg_arg == 'L') {
ins_bits = ins_bits << (32 - ins_token_len) >> (32 - ins_token_len);
}
if (reg_arg && *reg_arg == 'i') {
res = strdup ("");
} else {
sprintf(buff_aux, "#0x%06lx", (long unsigned int)ins_bits);
res = strdup(buff_aux);
}
break;
case 42:
flag = 0;
if (reg_arg && *reg_arg == '3') {
flag = ins_bits & 1;
ins_bits = ins_bits >> 1;
reg_arg++;
}
if (magic_value & 1) {
aux = get_sim_reg(reg_arg, ins_bits);
} else if (reg_arg) {
switch (*reg_arg) {
case 'b':
case 'd':
reg_arg++;
break;
case '!':
//strncpy(buff_aux, reg_arg + 1, 8);
reg_arg+=10;
//ins_bits2 = get_ins_bits(hash_code, ins_pos, buff_aux, 8);
break;
}
aux = get_AR_regs_class2(ins_bits, &ret_len, ins_len + ins_pos, 1);
}
if (magic_value & 1) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("mmap(", aux, 2);
} else if ((magic_value & 4) && is_linear_circular(ins_bits)) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("linear(", aux, 2);
} else if ((magic_value & 8) && is_linear_circular(ins_bits)) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("circular(", aux, 2);
} else if (magic_value & 2) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("lock(", aux, 2);
} else if (reg_arg) {
if (((magic_value & 0x10) && strchr(reg_arg, 'r')) ||
((magic_value & 0x20) && strchr(reg_arg, 'w'))) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("port(", aux, 2);
} else if (
((magic_value & 0x40) && strchr(reg_arg, 'r')) ||
((magic_value & 0x80000000) && strchr(reg_arg, 'w'))) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("volatile(", aux, 2);
}
}
if (flag) {
res = strcat_dup("t3 = ", aux, 2);
} else {
res = aux;
*ret_reg_len = ret_len;
}
break;
case 79:
res = get_trans_reg(ins_bits);
if (res == NULL) {
*err_code = -1;
}
break;
case 49:
if (reg_arg) {
if (*reg_arg == '1') {
res = get_tc2_tc1(ins_bits >> 1);
} else if (*reg_arg == '2')
res = get_tc2_tc1(ins_bits & 1);
} else res = get_tc2_tc1(ins_bits);
if (res == NULL) {
*err_code = -1;
return NULL;
}
break;
case 52:
if (ins_bits == 0)
break;
if (reg_arg) {
if (*reg_arg == 'H') {
res = "hi(";
} else if (*reg_arg == 'L') {
res = "lo(";
} else if (*reg_arg == 'd') {
res = "dbl(";
} else if (*reg_arg == ')') {
res = ")";
} else {
res = "<W>";
}
} else {
res = "<W !flags>";
}
res = strdup(res);
break;
case 53:
case 54:
case 55:
flag = 0;
if (reg_arg && *reg_arg == '3') {
flag = ins_bits & 1;
ins_bits = ins_bits >> 1;
reg_arg++;
}
aux = get_AR_regs_class1(ins_bits);
tok_op = ins_bits & 0xF;
if (magic_value & 4) {
if (tok_op <= 7 || tok_op == 0xF) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("linear(", aux, 2);
}
} else if (magic_value & 8) {
if (tok_op <= 7 || tok_op == 0xF) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("circular(", aux, 2);
}
} else if (magic_value & 2) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("lock(", aux, 2);
} else if (reg_arg) {
if (
((magic_value & 0x10) && *ins_token == 'X' && strchr(reg_arg, 'r'))
||
((magic_value & 0x20) && *ins_token == 'Y' && strchr(reg_arg, 'w'))
) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("port(", aux, 2);
} else if (
((magic_value & 0x40) && *ins_token == 'X' && strchr(reg_arg, 'r'))
||
((magic_value & 0x80000000) && *ins_token == 'Y' && strchr(reg_arg, 'w'))
) {
aux = strcat_dup(aux, ")", 1);
aux = strcat_dup("volatile(", aux, 2);
}
}
res = flag? strcat_dup ("t3 = ", aux, 2): aux;
break;
case 0:
case 1:
if (!ins_bits)
break;
if (!reg_arg) {
res = "U";
} else {
if (*reg_arg == '(') {
res = "uns(";
} else if (*reg_arg == ')') {
res = ")";
} else res = "<$/#>";
}
res = strdup(res);
break;
case 2:
if (!ins_bits)
break;
if (!reg_arg) {
res = "R";
} else {
if (*reg_arg == '(') {
res = "rnd(";
} else if (*reg_arg == ')') {
res = ")";
} else res = "<%>";
}
res = strdup(res);
break;
case 12:
if (!ins_bits)
break;
if(!reg_arg) {
res = "F";
} else {
if (*reg_arg == '(') {
res = "frct(";
} else if (*reg_arg == ')') {
res = ")";
} else if (*reg_arg == 'a') {
res = "<%>";
} else {
res = "</>";
}
}
res = strdup(res);
break;
case 29:
if (!ins_bits)
break;
if (!reg_arg) {
res = "saturate";
} else {
if (*reg_arg == '(') {
res = "saturate(";
} else if (*reg_arg == ')') {
res = ")";
} else {
res = "<saturate>";
}
}
res = strdup(res);
break;
case 16:
res = (ins_bits != 0)? strdup("t3 = ") : NULL;
break;
case 17:
if (!ins_bits)
break;
if (!reg_arg) {
res = "40";
} else {
if (*reg_arg == '(') {
res = "m40(";
} else if (*reg_arg == ')') {
res = ")";
} else {
res = "<4>";
}
}
res = strdup(res);
break;
case 78:
if (!strncasecmp(ins_token, "q_SAT", 5)) {
res = ins_bits? "s": NULL;
} else if (!strncasecmp(ins_token, "q_CIRC", 6)) {
res = ins_bits? ".cr": NULL;
} else if (!strncasecmp(ins_token, "q_LINR", 6)) {
res = ins_bits? ".lr": NULL;
} else {
fprintf (stderr, "Invalid instruction %s\n!", ins_token);
*err_code = -1;
return NULL;
}
if (res != NULL) {
if (C55PLUS_DEBUG) {
printf("OP(78): TOKEN=%s\n", res);
}
res = strdup(res);
}
break;
}
ret_decode:
if (C55PLUS_DEBUG) {
printf("RES = %s\n", (res) ? res :"NULL");
}
return res;
}