X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Farm-tdep.c;h=278f639fe8d8d1ee3e15eeb7c2affb2d433bf190;hb=a3405d124e1388b613a35af49f19f0cc1b8d959d;hp=1a3a209901b092bdf19a3cd46b324db19da24820;hpb=01e57735b0e8e6a613c58c271350dac2c416bb03;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1a3a209901..278f639fe8 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -2669,6 +2669,108 @@ struct frame_unwind arm_exidx_unwind = { arm_exidx_unwind_sniffer }; +static struct arm_prologue_cache * +arm_make_epilogue_frame_cache (struct frame_info *this_frame) +{ + struct arm_prologue_cache *cache; + int reg; + + cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache); + cache->saved_regs = trad_frame_alloc_saved_regs (this_frame); + + /* Still rely on the offset calculated from prologue. */ + arm_scan_prologue (this_frame, cache); + + /* Since we are in epilogue, the SP has been restored. */ + cache->prev_sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM); + + /* Calculate actual addresses of saved registers using offsets + determined by arm_scan_prologue. */ + for (reg = 0; reg < gdbarch_num_regs (get_frame_arch (this_frame)); reg++) + if (trad_frame_addr_p (cache->saved_regs, reg)) + cache->saved_regs[reg].addr += cache->prev_sp; + + return cache; +} + +/* Implementation of function hook 'this_id' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static void +arm_epilogue_frame_this_id (struct frame_info *this_frame, + void **this_cache, + struct frame_id *this_id) +{ + struct arm_prologue_cache *cache; + CORE_ADDR pc, func; + + if (*this_cache == NULL) + *this_cache = arm_make_epilogue_frame_cache (this_frame); + cache = (struct arm_prologue_cache *) *this_cache; + + /* Use function start address as part of the frame ID. If we cannot + identify the start address (due to missing symbol information), + fall back to just using the current PC. */ + pc = get_frame_pc (this_frame); + func = get_frame_func (this_frame); + if (func == 0) + func = pc; + + (*this_id) = frame_id_build (cache->prev_sp, pc); +} + +/* Implementation of function hook 'prev_register' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static struct value * +arm_epilogue_frame_prev_register (struct frame_info *this_frame, + void **this_cache, int regnum) +{ + if (*this_cache == NULL) + *this_cache = arm_make_epilogue_frame_cache (this_frame); + + return arm_prologue_prev_register (this_frame, this_cache, regnum); +} + +static int arm_stack_frame_destroyed_p_1 (struct gdbarch *gdbarch, + CORE_ADDR pc); +static int thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, + CORE_ADDR pc); + +/* Implementation of function hook 'sniffer' in + 'struct frame_uwnind' for epilogue unwinder. */ + +static int +arm_epilogue_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + { + struct gdbarch *gdbarch = get_frame_arch (this_frame); + CORE_ADDR pc = get_frame_pc (this_frame); + + if (arm_frame_is_thumb (this_frame)) + return thumb_stack_frame_destroyed_p (gdbarch, pc); + else + return arm_stack_frame_destroyed_p_1 (gdbarch, pc); + } + else + return 0; +} + +/* Frame unwinder from epilogue. */ + +static const struct frame_unwind arm_epilogue_frame_unwind = +{ + NORMAL_FRAME, + default_frame_unwind_stop_reason, + arm_epilogue_frame_this_id, + arm_epilogue_frame_prev_register, + NULL, + arm_epilogue_frame_sniffer, +}; + /* Recognize GCC's trampoline for thumb call-indirect. If we are in a trampoline, return the target PC. Otherwise return 0. @@ -3124,19 +3226,14 @@ thumb_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) return found_stack_adjust; } -/* Implement the stack_frame_destroyed_p gdbarch method. */ - static int -arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) +arm_stack_frame_destroyed_p_1 (struct gdbarch *gdbarch, CORE_ADDR pc) { enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); unsigned int insn; int found_return; CORE_ADDR func_start, func_end; - if (arm_pc_is_thumb (gdbarch, pc)) - return thumb_stack_frame_destroyed_p (gdbarch, pc); - if (!find_pc_partial_function (pc, NULL, &func_start, &func_end)) return 0; @@ -3178,6 +3275,16 @@ arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) return 0; } +/* Implement the stack_frame_destroyed_p gdbarch method. */ + +static int +arm_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + if (arm_pc_is_thumb (gdbarch, pc)) + return thumb_stack_frame_destroyed_p (gdbarch, pc); + else + return arm_stack_frame_destroyed_p_1 (gdbarch, pc); +} /* When arguments must be pushed onto the stack, they go on in reverse order. The code below implements a FILO (stack) to do this. */ @@ -6741,7 +6848,7 @@ thumb2_decode_ext_reg_ld_st (struct gdbarch *gdbarch, uint16_t insn1, } static int -arm_decode_svc_copro (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to, +arm_decode_svc_copro (struct gdbarch *gdbarch, uint32_t insn, struct regcache *regs, struct displaced_step_closure *dsc) { unsigned int op1 = bits (insn, 20, 25); @@ -7446,7 +7553,7 @@ thumb_process_displaced_32bit_insn (struct gdbarch *gdbarch, uint16_t insn1, static void thumb_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from, - CORE_ADDR to, struct regcache *regs, + struct regcache *regs, struct displaced_step_closure *dsc) { enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); @@ -7487,7 +7594,7 @@ arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from, dsc->wrote_to_pc = 0; if (!displaced_in_arm_mode (regs)) - return thumb_process_displaced_insn (gdbarch, from, to, regs, dsc); + return thumb_process_displaced_insn (gdbarch, from, regs, dsc); dsc->is_thumb = 0; dsc->insn_size = 4; @@ -7518,7 +7625,7 @@ arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from, break; case 0xc: case 0xd: case 0xe: case 0xf: - err = arm_decode_svc_copro (gdbarch, insn, to, regs, dsc); + err = arm_decode_svc_copro (gdbarch, insn, regs, dsc); break; } @@ -8431,7 +8538,9 @@ coff_sym_is_thumb (int val) static void arm_elf_make_msymbol_special(asymbol *sym, struct minimal_symbol *msym) { - if (ARM_SYM_BRANCH_TYPE (&((elf_symbol_type *)sym)->internal_elf_sym) + elf_symbol_type *elfsym = (elf_symbol_type *) sym; + + if (ARM_GET_SYM_BRANCH_TYPE (elfsym->internal_elf_sym.st_target_internal) == ST_BRANCH_TO_THUMB) MSYMBOL_SET_SPECIAL (msym); } @@ -8753,6 +8862,22 @@ arm_register_g_packet_guesses (struct gdbarch *gdbarch) /* Otherwise we don't have a useful guess. */ } +/* Implement the code_of_frame_writable gdbarch method. */ + +static int +arm_code_of_frame_writable (struct gdbarch *gdbarch, struct frame_info *frame) +{ + if (gdbarch_tdep (gdbarch)->is_m + && get_frame_type (frame) == SIGTRAMP_FRAME) + { + /* M-profile exception frames return to some magic PCs, where + isn't writable at all. */ + return 0; + } + else + return 1; +} + /* Initialize the current architecture based on INFO. If possible, re-use an architecture from ARCHES, which is a list of @@ -9203,6 +9328,9 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call); set_gdbarch_frame_align (gdbarch, arm_frame_align); + if (is_m) + set_gdbarch_code_of_frame_writable (gdbarch, arm_code_of_frame_writable); + set_gdbarch_write_pc (gdbarch, arm_write_pc); /* Frame handling. */ @@ -9280,6 +9408,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) frame_unwind_append_unwinder (gdbarch, &arm_stub_unwind); dwarf2_append_unwinders (gdbarch); frame_unwind_append_unwinder (gdbarch, &arm_exidx_unwind); + frame_unwind_append_unwinder (gdbarch, &arm_epilogue_frame_unwind); frame_unwind_append_unwinder (gdbarch, &arm_prologue_unwind); /* Now we have tuned the configuration, set a few final things, @@ -9884,11 +10013,6 @@ arm_record_extension_space (insn_decode_record *arm_insn_r) { /* SPSR is going to be changed. */ /* We need to get SPSR value, which is yet to be done. */ - printf_unfiltered (_("Process record does not support " - "instruction 0x%0x at address %s.\n"), - arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, - arm_insn_r->this_addr)); return -1; } } @@ -9929,10 +10053,6 @@ arm_record_extension_space (insn_decode_record *arm_insn_r) arm_insn_r->reg_rec_count = 2; /* Save SPSR also;how? */ - printf_unfiltered (_("Process record does not support " - "instruction 0x%0x at address %s.\n"), - arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr)); return -1; } else if(8 == bits (arm_insn_r->arm_insn, 4, 7) @@ -9978,11 +10098,6 @@ arm_record_extension_space (insn_decode_record *arm_insn_r) { /* SPSR is going to be changed. */ /* we need to get SPSR value, which is yet to be done */ - printf_unfiltered (_("Process record does not support " - "instruction 0x%0x at address %s.\n"), - arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, - arm_insn_r->this_addr)); return -1; } } @@ -10059,10 +10174,7 @@ arm_record_extension_space (insn_decode_record *arm_insn_r) /* To be done for ARMv5 and later; as of now we return -1. */ if (-1 == ret) - printf_unfiltered (_("Process record does not support instruction x%0x " - "at address %s.\n"),arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr)); - + return ret; REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf); MEM_ALLOC (arm_insn_r->arm_mems, arm_insn_r->mem_rec_count, record_buf_mem); @@ -10148,10 +10260,6 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r) { /* SPSR is going to be changed. */ /* How to read SPSR value? */ - printf_unfiltered (_("Process record does not support instruction " - "0x%0x at address %s.\n"), - arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, arm_insn_r->this_addr)); return -1; } } @@ -10207,10 +10315,6 @@ arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r) arm_insn_r->reg_rec_count = 2; /* Save SPSR also; how? */ - printf_unfiltered (_("Process record does not support instruction " - "0x%0x at address %s.\n"),arm_insn_r->arm_insn, - paddress (arm_insn_r->gdbarch, - arm_insn_r->this_addr)); return -1; } else if (11 == arm_insn_r->decode @@ -10313,6 +10417,88 @@ arm_record_data_proc_imm (insn_decode_record *arm_insn_r) return 0; } +static int +arm_record_media (insn_decode_record *arm_insn_r) +{ + uint32_t record_buf[8]; + + switch (bits (arm_insn_r->arm_insn, 22, 24)) + { + case 0: + /* Parallel addition and subtraction, signed */ + case 1: + /* Parallel addition and subtraction, unsigned */ + case 2: + case 3: + /* Packing, unpacking, saturation and reversal */ + { + int rd = bits (arm_insn_r->arm_insn, 12, 15); + + record_buf[arm_insn_r->reg_rec_count++] = rd; + } + break; + + case 4: + case 5: + /* Signed multiplies */ + { + int rd = bits (arm_insn_r->arm_insn, 16, 19); + unsigned int op1 = bits (arm_insn_r->arm_insn, 20, 22); + + record_buf[arm_insn_r->reg_rec_count++] = rd; + if (op1 == 0x0) + record_buf[arm_insn_r->reg_rec_count++] = ARM_PS_REGNUM; + else if (op1 == 0x4) + record_buf[arm_insn_r->reg_rec_count++] + = bits (arm_insn_r->arm_insn, 12, 15); + } + break; + + case 6: + { + if (bit (arm_insn_r->arm_insn, 21) + && bits (arm_insn_r->arm_insn, 5, 6) == 0x2) + { + /* SBFX */ + record_buf[arm_insn_r->reg_rec_count++] + = bits (arm_insn_r->arm_insn, 12, 15); + } + else if (bits (arm_insn_r->arm_insn, 20, 21) == 0x0 + && bits (arm_insn_r->arm_insn, 5, 7) == 0x0) + { + /* USAD8 and USADA8 */ + record_buf[arm_insn_r->reg_rec_count++] + = bits (arm_insn_r->arm_insn, 16, 19); + } + } + break; + + case 7: + { + if (bits (arm_insn_r->arm_insn, 20, 21) == 0x3 + && bits (arm_insn_r->arm_insn, 5, 7) == 0x7) + { + /* Permanently UNDEFINED */ + return -1; + } + else + { + /* BFC, BFI and UBFX */ + record_buf[arm_insn_r->reg_rec_count++] + = bits (arm_insn_r->arm_insn, 12, 15); + } + } + break; + + default: + return -1; + } + + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf); + + return 0; +} + /* Handle ARM mode instructions with opcode 010. */ static int @@ -10419,6 +10605,9 @@ arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r) LONGEST s_word; ULONGEST u_regval[2]; + if (bit (arm_insn_r->arm_insn, 4)) + return arm_record_media (arm_insn_r); + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24); arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7); @@ -10807,7 +10996,6 @@ arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r) uint32_t bits_a, bit_c, bit_l, reg_t, reg_v; uint32_t record_buf[4]; - const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); reg_t = bits (arm_insn_r->arm_insn, 12, 15); reg_v = bits (arm_insn_r->arm_insn, 21, 23); bits_a = bits (arm_insn_r->arm_insn, 21, 23); @@ -10825,12 +11013,7 @@ arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r) /* Handle VMOV instruction. */ if (bits_a == 0x00) { - if (bit (arm_insn_r->arm_insn, 20)) - record_buf[0] = reg_t; - else - record_buf[0] = num_regs + (bit (arm_insn_r->arm_insn, 7) | - (reg_v << 1)); - + record_buf[0] = reg_t; arm_insn_r->reg_rec_count = 1; } /* Handle VMRS instruction. */ @@ -10848,11 +11031,7 @@ arm_record_vdata_transfer_insn (insn_decode_record *arm_insn_r) /* Handle VMOV instruction. */ if (bits_a == 0x00) { - if (bit (arm_insn_r->arm_insn, 20)) - record_buf[0] = reg_t; - else - record_buf[0] = num_regs + (bit (arm_insn_r->arm_insn, 7) | - (reg_v << 1)); + record_buf[0] = ARM_D0_REGNUM + reg_v; arm_insn_r->reg_rec_count = 1; } @@ -10906,16 +11085,15 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) ULONGEST u_regval = 0; struct regcache *reg_cache = arm_insn_r->regcache; - const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); opcode = bits (arm_insn_r->arm_insn, 20, 24); - single_reg = bit (arm_insn_r->arm_insn, 8); + single_reg = !bit (arm_insn_r->arm_insn, 8); op_vldm_vstm = opcode & 0x1b; /* Handle VMOV instructions. */ if ((opcode & 0x1e) == 0x04) { - if (bit (arm_insn_r->arm_insn, 4)) + if (bit (arm_insn_r->arm_insn, 20)) /* to_arm_registers bit 20? */ { record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15); record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19); @@ -10923,18 +11101,29 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) } else { - uint8_t reg_m = ((bits (arm_insn_r->arm_insn, 0, 3) << 1) - | bit (arm_insn_r->arm_insn, 5)); + uint8_t reg_m = bits (arm_insn_r->arm_insn, 0, 3); + uint8_t bit_m = bit (arm_insn_r->arm_insn, 5); - if (!single_reg) + if (single_reg) { - record_buf[0] = num_regs + reg_m; - record_buf[1] = num_regs + reg_m + 1; - arm_insn_r->reg_rec_count = 2; + /* The first S register number m is REG_M:M (M is bit 5), + the corresponding D register number is REG_M:M / 2, which + is REG_M. */ + record_buf[arm_insn_r->reg_rec_count++] = ARM_D0_REGNUM + reg_m; + /* The second S register number is REG_M:M + 1, the + corresponding D register number is (REG_M:M + 1) / 2. + IOW, if bit M is 1, the first and second S registers + are mapped to different D registers, otherwise, they are + in the same D register. */ + if (bit_m) + { + record_buf[arm_insn_r->reg_rec_count++] + = ARM_D0_REGNUM + reg_m + 1; + } } else { - record_buf[0] = reg_m + ARM_D0_REGNUM; + record_buf[0] = ((bit_m << 4) + reg_m + ARM_D0_REGNUM); arm_insn_r->reg_rec_count = 1; } } @@ -10949,7 +11138,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; memory_count = imm_off8; if (bit (arm_insn_r->arm_insn, 23)) @@ -10965,19 +11154,19 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) while (memory_count > 0) { - if (!single_reg) + if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; start_address = start_address + 4; memory_index = memory_index + 2; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; start_address = start_address + 8; memory_index = memory_index + 4; } @@ -10991,25 +11180,36 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) { uint32_t reg_count, reg_vd; uint32_t reg_index = 0; + uint32_t bit_d = bit (arm_insn_r->arm_insn, 22); reg_vd = bits (arm_insn_r->arm_insn, 12, 15); reg_count = bits (arm_insn_r->arm_insn, 0, 7); - if (single_reg) - reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4); - else - reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); + /* REG_VD is the first D register number. If the instruction + loads memory to S registers (SINGLE_REG is TRUE), the register + number is (REG_VD << 1 | bit D), so the corresponding D + register number is (REG_VD << 1 | bit D) / 2 = REG_VD. */ + if (!single_reg) + reg_vd = reg_vd | (bit_d << 4); - if (bit (arm_insn_r->arm_insn, 21)) + if (bit (arm_insn_r->arm_insn, 21) /* write back */) record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19); - while (reg_count > 0) + /* If the instruction loads memory to D register, REG_COUNT should + be divided by 2, according to the ARM Architecture Reference + Manual. If the instruction loads memory to S register, divide by + 2 as well because two S registers are mapped to D register. */ + reg_count = reg_count / 2; + if (single_reg && bit_d) { - if (single_reg) - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; - else - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; + /* Increase the register count if S register list starts from + an odd number (bit d is one). */ + reg_count++; + } + while (reg_count > 0) + { + record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; reg_count--; } arm_insn_r->reg_rec_count = reg_index; @@ -11023,7 +11223,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; if (bit (arm_insn_r->arm_insn, 23)) start_address = u_regval + imm_off32; @@ -11032,16 +11232,16 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; arm_insn_r->mem_rec_count = 1; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; arm_insn_r->mem_rec_count = 2; } } @@ -11058,7 +11258,8 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) else { reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); - record_buf[0] = num_regs + reg_vd; + /* Record register D rather than pseudo register S. */ + record_buf[0] = ARM_D0_REGNUM + reg_vd / 2; } arm_insn_r->reg_rec_count = 1; } @@ -11512,10 +11713,10 @@ thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r) } else { - /* Format 8; special data processing insns. */ - reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2); - record_buf[0] = ARM_PS_REGNUM; - record_buf[1] = reg_src1; + /* Format 8; special data processing insns. */ + record_buf[0] = ARM_PS_REGNUM; + record_buf[1] = (bit (thumb_insn_r->arm_insn, 7) << 3 + | bits (thumb_insn_r->arm_insn, 0, 2)); thumb_insn_r->reg_rec_count = 2; } } @@ -12697,13 +12898,20 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, { arm_record->cond = bits (arm_record->arm_insn, 28, 31); insn_id = bits (arm_record->arm_insn, 25, 27); - ret = arm_record_extension_space (arm_record); - /* If this insn has fallen into extension space - then we need not decode it anymore. */ - if (ret != -1 && !INSN_RECORDED(arm_record)) + + if (arm_record->cond == 0xf) + ret = arm_record_extension_space (arm_record); + else { + /* If this insn has fallen into extension space + then we need not decode it anymore. */ ret = arm_handle_insn[insn_id] (arm_record); } + if (ret != ARM_RECORD_SUCCESS) + { + arm_record_unsupported_insn (arm_record); + ret = -1; + } } else if (THUMB_RECORD == record_type) { @@ -12711,6 +12919,11 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, arm_record->cond = -1; insn_id = bits (arm_record->arm_insn, 13, 15); ret = thumb_handle_insn[insn_id] (arm_record); + if (ret != ARM_RECORD_SUCCESS) + { + arm_record_unsupported_insn (arm_record); + ret = -1; + } } else if (THUMB2_RECORD == record_type) { @@ -12721,9 +12934,9 @@ decode_insn (insn_decode_record *arm_record, record_type_t record_type, arm_record->arm_insn = (arm_record->arm_insn >> 16) | (arm_record->arm_insn << 16); - insn_id = thumb2_record_decode_insn_handler (arm_record); + ret = thumb2_record_decode_insn_handler (arm_record); - if (insn_id != ARM_RECORD_SUCCESS) + if (ret != ARM_RECORD_SUCCESS) { arm_record_unsupported_insn (arm_record); ret = -1;