int print_insn_pj (bfd_vma addr, struct disassemble_info *info) { fprintf_ftype fprintf_fn = info->fprintf_func; void *stream = info->stream; unsigned char opcode; int status; if ((status = info->read_memory_func (addr, &opcode, 1, info))) goto fail; if (opcode == 0xff) { unsigned char byte_2; if ((status = info->read_memory_func (addr + 1, &byte_2, 1, info))) goto fail; fprintf_fn (stream, "%s\t", pj_opc_info[opcode + byte_2].u.name); return 2; } else { char *sep = "\t"; int insn_start = addr; const pj_opc_info_t *op = &pj_opc_info[opcode]; int a; addr++; fprintf_fn (stream, "%s", op->u.name); /* The tableswitch instruction is followed by the default address, low value, high value and the destinations. */ if (strcmp (op->u.name, "tableswitch") == 0) { int lowval; int highval; int val; addr = (addr + 3) & ~3; if ((status = get_int (addr, &val, info))) goto fail; fprintf_fn (stream, " default: "); (*info->print_address_func) (val + insn_start, info); addr += 4; if ((status = get_int (addr, &lowval, info))) goto fail; addr += 4; if ((status = get_int (addr, &highval, info))) goto fail; addr += 4; while (lowval <= highval) { if ((status = get_int (addr, &val, info))) goto fail; fprintf_fn (stream, " %d:[", lowval); (*info->print_address_func) (val + insn_start, info); fprintf_fn (stream, " ]"); addr += 4; lowval++; } return addr - insn_start; } /* The lookupswitch instruction is followed by the default address, element count and pairs of values and addresses. */ if (strcmp (op->u.name, "lookupswitch") == 0) { int count; int val; addr = (addr + 3) & ~3; if ((status = get_int (addr, &val, info))) goto fail; addr += 4; fprintf_fn (stream, " default: "); (*info->print_address_func) (val + insn_start, info); if ((status = get_int (addr, &count, info))) goto fail; addr += 4; while (count--) { if ((status = get_int (addr, &val, info))) goto fail; addr += 4; fprintf_fn (stream, " %d:[", val); if ((status = get_int (addr, &val, info))) goto fail; addr += 4; (*info->print_address_func) (val + insn_start, info); fprintf_fn (stream, " ]"); } return addr - insn_start; } for (a = 0; op->arg[a]; a++) { unsigned char data[4]; int val = 0; int i; int size = ASIZE (op->arg[a]); if ((status = info->read_memory_func (addr, data, size, info))) goto fail; val = (UNS (op->arg[0]) || ((data[0] & 0x80) == 0)) ? 0 : -1; for (i = 0; i < size; i++) val = (val << 8) | (data[i] & 0xff); if (PCREL (op->arg[a])) (*info->print_address_func) (val + insn_start, info); else fprintf_fn (stream, "%s%d", sep, val); sep = ","; addr += size; } return op->len; } fail: info->memory_error_func (status, addr, info); return -1; }
const struct mips_operand * decode_mips16_operand (char type, bfd_boolean extended_p) { switch (type) { case '0': MAPPED_REG (0, 0, GP, reg_0_map); case 'L': SPECIAL (6, 5, ENTRY_EXIT_LIST); case 'M': SPECIAL (7, 0, SAVE_RESTORE_LIST); case 'P': SPECIAL (0, 0, PC); case 'R': MAPPED_REG (0, 0, GP, reg_31_map); case 'S': MAPPED_REG (0, 0, GP, reg_29_map); case 'X': REG (5, 0, GP); case 'Y': MAPPED_REG (5, 3, GP, reg32r_map); case 'Z': MAPPED_REG (3, 0, GP, reg_m16_map); case 'a': JUMP (26, 0, 2); case 'e': UINT (11, 0); case 'i': JALX (26, 0, 2); case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST); case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST); case 'v': MAPPED_REG (3, 8, GP, reg_m16_map); case 'w': MAPPED_REG (3, 5, GP, reg_m16_map); case 'x': MAPPED_REG (3, 8, GP, reg_m16_map); case 'y': MAPPED_REG (3, 5, GP, reg_m16_map); case 'z': MAPPED_REG (3, 2, GP, reg_m16_map); } if (extended_p) switch (type) { case '<': UINT (5, 0); case '>': UINT (5, 0); case '[': UINT (6, 0); case ']': UINT (6, 0); case '4': SINT (15, 0); case '5': SINT (16, 0); case '6': SINT (16, 0); case '8': SINT (16, 0); case 'A': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE); case 'B': PCREL (16, 0, TRUE, 0, 3, FALSE, FALSE); case 'C': SINT (16, 0); case 'D': SINT (16, 0); case 'E': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE); case 'H': SINT (16, 0); case 'K': SINT (16, 0); case 'U': UINT (16, 0); case 'V': SINT (16, 0); case 'W': SINT (16, 0); case 'j': SINT (16, 0); case 'k': SINT (16, 0); case 'p': BRANCH (16, 0, 1); case 'q': BRANCH (16, 0, 1); } else switch (type) { case '<': INT_ADJ (3, 2, 8, 0, FALSE); case '>': INT_ADJ (3, 8, 8, 0, FALSE); case '[': INT_ADJ (3, 2, 8, 0, FALSE); case ']': INT_ADJ (3, 8, 8, 0, FALSE); case '4': SINT (4, 0); case '5': UINT (5, 0); case '6': UINT (6, 5); case '8': UINT (8, 0); case 'A': PCREL (8, 0, FALSE, 2, 2, FALSE, FALSE); case 'B': PCREL (5, 0, FALSE, 3, 3, FALSE, FALSE); case 'C': INT_ADJ (8, 0, 255, 3, FALSE); /* (0 .. 255) << 3 */ case 'D': INT_ADJ (5, 0, 31, 3, FALSE); /* (0 .. 31) << 3 */ case 'E': PCREL (5, 0, FALSE, 2, 2, FALSE, FALSE); case 'H': INT_ADJ (5, 0, 31, 1, FALSE); /* (0 .. 31) << 1 */ case 'K': INT_ADJ (8, 0, 127, 3, FALSE); /* (-128 .. 127) << 3 */ case 'U': UINT (8, 0); case 'V': INT_ADJ (8, 0, 255, 2, FALSE); /* (0 .. 255) << 2 */ case 'W': INT_ADJ (5, 0, 31, 2, FALSE); /* (0 .. 31) << 2 */ case 'j': SINT (5, 0); case 'k': SINT (8, 0); case 'p': BRANCH (8, 0, 1); case 'q': BRANCH (11, 0, 1); } return 0; }
const struct mips_operand * decode_mips16_operand (char type, bfd_boolean extended_p) { switch (type) { case '.': MAPPED_REG (0, 0, GP, reg_0_map); case '>': HINT (5, 22); case '0': HINT (5, 0); case '1': HINT (3, 5); case '2': HINT (3, 8); case '3': HINT (5, 16); case '4': HINT (3, 21); case '6': HINT (6, 5); case '9': SINT (9, 0); case 'G': SPECIAL (0, 0, REG28); case 'L': SPECIAL (6, 5, ENTRY_EXIT_LIST); case 'N': REG (5, 0, COPRO); case 'O': UINT (3, 21); case 'Q': REG (5, 16, HW); case 'P': SPECIAL (0, 0, PC); case 'R': MAPPED_REG (0, 0, GP, reg_31_map); case 'S': MAPPED_REG (0, 0, GP, reg_29_map); case 'T': HINT (5, 16); case 'X': REG (5, 0, GP); case 'Y': MAPPED_REG (5, 3, GP, reg32r_map); case 'Z': MAPPED_REG (3, 0, GP, reg_m16_map); case 'a': JUMP (26, 0, 2); case 'b': BIT (5, 22, 0); /* (0 .. 31) */ case 'c': MSB (5, 16, 1, TRUE, 32); /* (1 .. 32) */ case 'd': MSB (5, 16, 1, FALSE, 32); /* (1 .. 32) */ case 'e': HINT (11, 0); case 'i': JALX (26, 0, 2); case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST); case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST); case 'n': INT_BIAS (2, 0, 3, 1, 0, FALSE); /* (1 .. 4) */ case 'o': INT_ADJ (5, 16, 31, 4, FALSE); /* (0 .. 31) << 4 */ case 'r': MAPPED_REG (3, 16, GP, reg_m16_map); case 's': HINT (3, 24); case 'u': HINT (16, 0); case 'v': OPTIONAL_MAPPED_REG (3, 8, GP, reg_m16_map); case 'w': OPTIONAL_MAPPED_REG (3, 5, GP, reg_m16_map); case 'x': MAPPED_REG (3, 8, GP, reg_m16_map); case 'y': MAPPED_REG (3, 5, GP, reg_m16_map); case 'z': MAPPED_REG (3, 2, GP, reg_m16_map); } if (extended_p) switch (type) { case '<': UINT (5, 22); case '[': UINT (6, 0); case ']': UINT (6, 0); case '5': SINT (16, 0); case '8': SINT (16, 0); case 'A': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE); case 'B': PCREL (16, 0, TRUE, 0, 3, FALSE, FALSE); case 'C': SINT (16, 0); case 'D': SINT (16, 0); case 'E': PCREL (16, 0, TRUE, 0, 2, FALSE, FALSE); case 'F': SINT (15, 0); case 'H': SINT (16, 0); case 'K': SINT (16, 0); case 'U': UINT (16, 0); case 'V': SINT (16, 0); case 'W': SINT (16, 0); case 'j': SINT (16, 0); case 'k': SINT (16, 0); case 'p': BRANCH (16, 0, 1); case 'q': BRANCH (16, 0, 1); } else switch (type) { case '<': INT_ADJ (3, 2, 8, 0, FALSE); case '[': INT_ADJ (3, 2, 8, 0, FALSE); case ']': INT_ADJ (3, 8, 8, 0, FALSE); case '5': UINT (5, 0); case '8': UINT (8, 0); case 'A': PCREL (8, 0, FALSE, 2, 2, FALSE, FALSE); case 'B': PCREL (5, 0, FALSE, 3, 3, FALSE, FALSE); case 'C': INT_ADJ (8, 0, 255, 3, FALSE); /* (0 .. 255) << 3 */ case 'D': INT_ADJ (5, 0, 31, 3, FALSE); /* (0 .. 31) << 3 */ case 'E': PCREL (5, 0, FALSE, 2, 2, FALSE, FALSE); case 'F': SINT (4, 0); case 'H': INT_ADJ (5, 0, 31, 1, FALSE); /* (0 .. 31) << 1 */ case 'K': INT_ADJ (8, 0, 127, 3, FALSE); /* (-128 .. 127) << 3 */ case 'U': UINT (8, 0); case 'V': INT_ADJ (8, 0, 255, 2, FALSE); /* (0 .. 255) << 2 */ case 'W': INT_ADJ (5, 0, 31, 2, FALSE); /* (0 .. 31) << 2 */ case 'j': SINT (5, 0); case 'k': SINT (8, 0); case 'p': BRANCH (8, 0, 1); case 'q': BRANCH (11, 0, 1); } return 0; }