* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-05-29 15:38 paawan oza
2011-05-31 18:05 ` Tom Tromey
0 siblings, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-05-29 15:38 UTC (permalink / raw)
To: gdb-patches, Petr Hluzín
Hi,
Fixed some minor issues with Patch.
PATCH STARTS
---------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c 2011-05-29 20:44:25.000000000 +0530
@@ -54,6 +54,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -7929,3 +7931,1751 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define GET_REG_VAL(REGCACHE,NO,VAL) \
+ regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL) \
+ regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = 0; \
+ reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
+ while (reg_len) \
+ { \
+ REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
+ reg_len--; \
+ } \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = 0; \
+ mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = (struct arm_mem_r *)xmalloc \
+ (sizeof(struct arm_mem_r) * (mem_len)); \
+ while (mem_len) \
+ { \
+ MEMS[mem_len - 1].addr = RECORD_BUF[(mem_len * 2) - 1]; \
+ MEMS[mem_len - 1].len = RECORD_BUF[(mem_len * 2) - 2]; \
+ mem_len--; \
+ } \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* record length. */
+ CORE_ADDR addr; /* memory address. */
+};
+
+/* ARM instruction record.
+contains opcode of current insn and execution state (before entry to
+decode_insn() ),
+contains list of to-be-modified registers and memory blocks (on return from
+decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* address of the insn being decoded. */
+ uint32_t arm_insn; /* should accommodate thumb. */
+ uint32_t cond; /* condition code. */
+ uint32_t opcode; /* insn opcode. */
+ uint32_t decode; /* insn decode bits. */
+ uint32_t mem_rec_count; /* no of mem recors */
+ uint32_t reg_rec_count; /* no of reg records */
+ uint32_t *arm_regs; /* registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* checks ARM SBZ and SBO mendatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if(!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((!opcode1) && (9 == opcode2))
+ {
+ ret = -1;
+ /* handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+ {
+ ret = -1;
+ /* handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+ && (bit(arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+ {
+ ret = -1;
+ /* handle coprocessor insn extension space. */
+ }
+
+ /* to be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* handling opcode 000 insns. */
+
+static int
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+ {
+ /* handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* Handling SWP, SWPB. */
+ /* these insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1)))
+ {
+ /* handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly */
+ /* what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1,
&u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) store, register offset. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) store, immediate pre-indexed. */
+ /* 5) store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) store, register pre-indexed. */
+ /* 6) store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* handle BX, branch and link/exchange. */
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)))
+ {
+ /* count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+ )
+ {
+ /* handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 001 insns. */
+
+static int
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ )
+ {
+ /* handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ /* Oza: FIX ME ? how to read SPSR value? */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 010 insns. */
+
+static int
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* we are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 011 insns. */
+
+static int
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ /* pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
u_buf[0].unsigned_regval;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL_SIGNED (reg_cache, reg_src1, &u_buf[0].signed_word);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* offset_12 used as shift. */
+ switch(offset_12)
+ {
+ case 0:
+ /* offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* this is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ GET_REG_VAL (reg_cache, ARM_PS_REGNUM,
&u_buf[1].unsigned_regval);
+ /* get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31)
\
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 100 insns. */
+
+static int
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* this mode is exclusively for load and store multiple. */
+ /* handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if ((bit (arm_insn_r->arm_insn,20)) && !(bit (arm_insn_r->arm_insn,22)))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* register_count gives total no of registers and dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* it handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch(addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4) +
4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ /* base register also changes; based on condition and W bit. */
+ /* we save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 101 insns. */
+
+static int
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* handle B, BL, BLX(1) insns. */
+ /* wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* handling opcode 110 insns. */
+
+static int
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* handling opcode 111 insns. */
+
+static int
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* handling opcode 000 insns. */
+
+static int
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* handling opcode 001 insns. */
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* handling opcode 010 insns. */
+
+static int
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] =
u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 001 insns. */
+
+static int
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 100 insns. */
+
+static int
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 101 insns. */
+
+static int
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly. */
+ /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 110 insns. */
+
+static int
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* it handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 111 insns. */
+
+static int
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch
it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_handle_data_proc_misc_ld_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_handle_ld_st_multiple_insn, /* 100. */
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_handle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+ thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is useless.
*/
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* throw assertion. */
+ gdb_assert(0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* we are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* we are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h 2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -310,6 +313,10 @@
struct displaced_step_closure *,
CORE_ADDR, CORE_ADDR, struct regcache *);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
+
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-05-29 15:38 [PATCH] arm reversible : <phase_2_complete> paawan oza
@ 2011-05-31 18:05 ` Tom Tromey
2011-06-03 7:44 ` paawan oza
2011-06-03 7:51 ` paawan oza
0 siblings, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-05-31 18:05 UTC (permalink / raw)
To: paawan oza; +Cc: gdb-patches, Petr Hluzín
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> Fixed some minor issues with Patch.
Thanks.
Overall I think the basic structure is probably ok.
I'd appreciate it if an actual ARM person took a look.
Oza> +#define GET_REG_VAL(REGCACHE,NO,VAL) \
Oza> + regcache_raw_read_unsigned (REGCACHE, NO, VAL);
Oza> +
Oza> +#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL) \
Oza> + regcache_raw_read_unsigned (REGCACHE, NO, VAL);
I think it is better not to have these macros. They don't add anything,
but just obscure the underlying implementation.
I don't understand why the "SIGNED" macro is defined as calling a
function named ..._unsigned.
Oza> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
Oza> +do \
Oza> + { \
Oza> + unsigned int reg_len = 0; \
Oza> + reg_len = LENGTH; \
You might as well coalesce these two lines.
Oza> + if (reg_len) \
Oza> + { \
Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Oza> + while (reg_len) \
Oza> + { \
Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
Oza> + reg_len--; \
I think this could be replaced with memcpy.
Oza> +struct arm_mem_r
Oza> +{
Oza> + uint32_t len; /* record length. */
Wrong indentation.
Oza> +/* ARM instruction record.
Oza> +contains opcode of current insn and execution state (before entry to
Oza> +decode_insn() ),
Oza> +contains list of to-be-modified registers and memory blocks (on return from
Oza> +decode_insn() ). */
Wrong formatting.
Oza> +/* checks ARM SBZ and SBO mendatory fields. */
Capitalize.
This problem appears more than once.
Oza> + memset(&u_buf, 0, sizeof(u_buf));
Wrong formatting.
This appears a few times too.
Oza> + printf_unfiltered (_("Process record does not support instruction "
Oza> + "0x%0x at address %s.\n"),
Oza> + arm_insn_r->arm_insn,
Oza> + paddress (arm_insn_r->gdbarch,
It seems odd that a failure is reported just with a printf.
What is the reason for not throwing an exception?
Oza> + gdb_assert_not_reached ("no decoding pattern found");
This text makes it sound like this assertion could possibly be reached
somehow. I didn't track through all the insn decoding logic; but if
this can be triggered by some value (perhaps an invalid instruction)
then it is extremely unfriendly to assert.
Oza> + struct
Oza> + {
Oza> + ULONGEST signed_word;
It is weird that a "signed" word has an unsigned type.
Why is this?
Oza> + /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
Oza> + that case, we need to go back with previous CPSR and
Oza> + Program Counter.. */
No names in comments.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-05-31 18:05 ` Tom Tromey
@ 2011-06-03 7:44 ` paawan oza
2011-06-03 7:51 ` paawan oza
1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-06-03 7:44 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín
Hi Tom,
please find my comments inlined below.
Regards,
Oza.
----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Tue, May 31, 2011 11:34:49 PM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> Fixed some minor issues with Patch.
Thanks.
Overall I think the basic structure is probably ok.
I'd appreciate it if an actual ARM person took a look.
Oza> +#define GET_REG_VAL(REGCACHE,NO,VAL) \
Oza> + regcache_raw_read_unsigned (REGCACHE, NO, VAL);
Oza> +
Oza> +#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL) \
Oza> + regcache_raw_read_unsigned (REGCACHE, NO, VAL);
I think it is better not to have these macros. They don't add anything,
but just obscure the underlying implementation.
I don't understand why the "SIGNED" macro is defined as calling a
function named ..._unsigned.
Oza: macors removed and it was a mistake to have unsigned, corrected too.
Oza> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
Oza> +do \
Oza> + { \
Oza> + unsigned int reg_len = 0; \
Oza> + reg_len = LENGTH; \
You might as well coalesce these two lines.
Oza: done
Oza> + if (reg_len) \
Oza> + { \
Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Oza> + while (reg_len) \
Oza> + { \
Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
Oza> + reg_len--; \
I think this could be replaced with memcpy.
Oza: yes, but just to make the logic look symmetrical with MEM_ALLOC I have kept
that way.
Oza> +struct arm_mem_r
Oza> +{
Oza> + uint32_t len; /* record length. */
Wrong indentation.
Oza: corrected.
Oza> +/* ARM instruction record.
Oza> +contains opcode of current insn and execution state (before entry to
Oza> +decode_insn() ),
Oza> +contains list of to-be-modified registers and memory blocks (on return
from
Oza> +decode_insn() ). */
Wrong formatting.
Oza: corrected.
Oza> +/* checks ARM SBZ and SBO mendatory fields. */
Capitalize.
This problem appears more than once.
Oza: Capitalization is taken care in all the comments now.
Oza> + memset(&u_buf, 0, sizeof(u_buf));
Wrong formatting.
This appears a few times too.
Oza: sizeof (...) formatting correctedin memset, I am not sure if any other
formatting you referred to.
Oza> + printf_unfiltered (_("Process record does not support
instruction "
Oza> + "0x%0x at address %s.\n"),
Oza> + arm_insn_r->arm_insn,
Oza> + paddress (arm_insn_r->gdbarch,
It seems odd that a failure is reported just with a printf.
What is the reason for not throwing an exception?
Oza : If you see next line
ret = -1
eventullly gdb record code throws an exception as below.
if (ret < 0)
error (_("Process record: failed to record execution log."));
Oza> + gdb_assert_not_reached ("no decoding pattern found");
This text makes it sound like this assertion could possibly be reached
somehow. I didn't track through all the insn decoding logic; but if
this can be triggered by some value (perhaps an invalid instruction)
then it is extremely unfriendly to assert.
Oza: this code would never be reached, except in the case where ARM changes/adds
decoding logic to this set of insns.
or compiler is producing faulty code.
both have rare chances.
basically I was looking for throwing assertion with message, and could not find
macro other than this.
please suggest if any better way to handle.
Oza> + struct
Oza> + {
Oza> + ULONGEST signed_word;
It is weird that a "signed" word has an unsigned type.
Why is this?
oza: turned into LONGEST, corrected now.
Oza> + /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
Oza> + that case, we need to go back with previous CPSR and
Oza> + Program Counter.. */
No names in comments.
Oza: sure, removed.
execuse me if you have to tell things twice as it is quite a long code base
where i might have failed to take care of same error at all places.
though I tried best to eliminate duplicate errors.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-05-31 18:05 ` Tom Tromey
2011-06-03 7:44 ` paawan oza
@ 2011-06-03 7:51 ` paawan oza
2011-07-12 21:10 ` Tom Tromey
1 sibling, 1 reply; 128+ messages in thread
From: paawan oza @ 2011-06-03 7:51 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín
Hi Tom,
Fixed almost all comments.
any more comments are welcome make this patch ok, if ARM person can have a look
at it it would be great.
PATCH STARTS
------------------------------------diff -urN arm_orig/arm-linux-tdep.c
arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c 2011-06-03 13:16:35.000000000 +0530
@@ -54,6 +54,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -7929,3 +7931,1763 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = 0; reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
+ while (reg_len) \
+ { \
+ REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
+ reg_len--; \
+ } \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = 0; mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = (struct arm_mem_r *)xmalloc \
+ (sizeof(struct arm_mem_r) * (mem_len)); \
+ while (mem_len) \
+ { \
+ MEMS[mem_len - 1].addr = RECORD_BUF[(mem_len * 2) - 1]; \
+ MEMS[mem_len - 1].len = RECORD_BUF[(mem_len * 2) - 2]; \
+ mem_len--; \
+ } \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn and execution state
(before entry to
+decode_insn() ), contains list of to-be-modified registers and memory blocks
(on return from
+decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem recors */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mendatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if(!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((!opcode1) && (9 == opcode2))
+ {
+ ret = -1;
+ /* Handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+ {
+ ret = -1;
+ /* Handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+ && (bit(arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* Handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset(&u_buf, 0, sizeof (u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1)))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ ,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned(reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset(&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ LONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset(&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ ,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
u_buf[0].unsigned_regval;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &u_buf[0].signed_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Offset_12 used as shift. */
+ switch(offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_buf[1].unsigned_regval);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31)
\
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if ((bit (arm_insn_r->arm_insn,20)) && !(bit (arm_insn_r->arm_insn,22)))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers and dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch(addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4) +
4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* Wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] =
u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch
it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_handle_data_proc_misc_ld_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_handle_ld_st_multiple_insn, /* 100. */
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_handle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+ thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is useless.
*/
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* Yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert(0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h 2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -310,6 +313,10 @@
struct displaced_step_closure *,
CORE_ADDR, CORE_ADDR, struct regcache *);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
+
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-06-03 7:51 ` paawan oza
@ 2011-07-12 21:10 ` Tom Tromey
2011-07-13 3:17 ` chandra krishnappa
` (2 more replies)
0 siblings, 3 replies; 128+ messages in thread
From: Tom Tromey @ 2011-07-12 21:10 UTC (permalink / raw)
To: paawan oza; +Cc: gdb-patches, Petr Hluzín
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.
You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding. I think we should proceed on the
theory that this is simply not going to happen.
Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code. I expect
there will be bugs; those can be fixed.
You need a ChangeLog entry. A patch of this magnitude should also have
a NEWS entry.
Some kind of testing would be good. Do the existing tests in
gdb.reverse work with your port? If so then I think that is sufficient
Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
Just write unsigned int reg_len = LENGTH;
Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Mind the spaces and parens. Better, use XNEWVEC:
REGS = XNEWVEC (uint32_t, reg_len);
Oza> + while (reg_len) \
Oza> + { \
Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
Oza> + reg_len--; \
Oza> + } \
Just use memcpy.
Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
The same comments apply for this macro.
Oza> +/* ARM instruction record contains opcode of current insn and execution state
Oza> (before entry to
Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
Oza> (on return from
Your email got corrupted. Usually this is some bad MUA setting.
Oza> + uint32_t mem_rec_count; /* No of mem recors */
Typo, "recors"
Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
Typo, should be "mandatory".
Oza> + if(!sbo)
Spacing.
Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
Over-parenthesizing makes the code harder to read. Please fix this. I
noticed it in many places. This specific case should read:
if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
Oza> + memset(&u_buf, 0, sizeof (u_buf));
Spacing. Just go through the entire patch and fix all the spacing
issues.
I feel like I have mentioned this before.
Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> + , &u_buf[0].unsigned_regval);
What if this does not return REG_VALID?
There are multiple instances of this.
Oza> + gdb_assert_not_reached ("no decoding pattern found");
It seems wrong to use an assert in this code. At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction. An unrecognized instruction can occur
for many reasons, e.g., a bad jump.
Oza> + if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
This reads very oddly. Is there a particular reason behind the ordering
(if so -- document). If not, isn't this:
if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
There are other odd-looking conditions like this.
Oza> + default:
Oza> + gdb_assert_not_reached ("Invalid addressing mode for insn");
Again, assert seems wrong.
I'm afraid I ran out of steam here. Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up. I want this patch to go in, but first it
must comply to the usual gdb standards.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-07-12 21:10 ` Tom Tromey
@ 2011-07-13 3:17 ` chandra krishnappa
2011-07-13 5:36 ` paawan oza
2011-07-13 15:20 ` Tom Tromey
2011-07-13 6:57 ` paawan oza
[not found] ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
2 siblings, 2 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-07-13 3:17 UTC (permalink / raw)
To: paawan oza, Tom Tromey; +Cc: gdb-patches, Petr Hluzín
Hi,
I am trying to the test if the existing gdb.reverse works with the ARM porting done by Oza..
I am a learner, and I am taking more time than a average developer to get documentation, read, understand and complete the testing of ARM porting of reversible....
Thanks & Regards,
-Chandra K
--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:
> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "paawan oza" <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 2:29 AM
> >>>>> "Oza" == paawan
> oza <paawan1982@yahoo.com>
> writes:
>
> Oza> any more comments are welcome make this patch ok,
> if ARM person can
> Oza> have a look at it it would be great.
>
> You have submitted this patch many times now and nobody has
> commented
> on the details of the ARM decoding. I think we should
> proceed on the
> theory that this is simply not going to happen.
>
> Also, I am not as concerned about the correctness of every
> detail as I
> am about the general maintainability and style of the
> code. I expect
> there will be bugs; those can be fixed.
>
> You need a ChangeLog entry. A patch of this magnitude
> should also have
> a NEWS entry.
>
> Some kind of testing would be good. Do the existing
> tests in
> gdb.reverse work with your port? If so then I think
> that is sufficient
>
> Oza> + unsigned int reg_len = 0; reg_len =
> LENGTH; \
>
> Just write unsigned int reg_len = LENGTH;
>
> Oza> + REGS = (uint32_t*)
> xmalloc (sizeof(uint32_t) * (reg_len)); \
>
> Mind the spaces and parens. Better, use XNEWVEC:
>
> REGS = XNEWVEC (uint32_t, reg_len);
>
> Oza> + while (reg_len) \
> Oza> + { \
> Oza> +
> REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
> Oza> +
> reg_len--; \
> Oza> + } \
>
> Just use memcpy.
>
> Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>
> The same comments apply for this macro.
>
> Oza> +/* ARM instruction record contains opcode of
> current insn and execution state
> Oza> (before entry to
>
> Oza> +decode_insn() ), contains list of to-be-modified
> registers and memory blocks
> Oza> (on return from
>
> Your email got corrupted. Usually this is some bad
> MUA setting.
>
> Oza> + uint32_t mem_rec_count;
> /* No of mem recors */
>
> Typo, "recors"
>
> Oza> +/* Checks ARM SBZ and SBO mendatory fields.
> */
>
> Typo, should be "mandatory".
>
> Oza> + if(!sbo)
>
> Spacing.
>
> Oza> + if ((3 == opcode1) && (bit
> (arm_insn_r->arm_insn, 4)))
>
> Over-parenthesizing makes the code harder to read.
> Please fix this. I
> noticed it in many places. This specific case should
> read:
>
> if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
>
> Oza> + memset(&u_buf, 0, sizeof (u_buf));
>
> Spacing. Just go through the entire patch and fix all
> the spacing
> issues.
>
> I feel like I have mentioned this before.
>
> Oza> + regcache_raw_read_unsigned
> (reg_cache, reg_src1
> Oza> +
>
> , &u_buf[0].unsigned_regval);
>
> What if this does not return REG_VALID?
> There are multiple instances of this.
>
> Oza> + gdb_assert_not_reached ("no
> decoding pattern found");
>
> It seems wrong to use an assert in this code. At
> least, it is not
> obvious to me that this represents a logic error in gdb as
> opposed to a
> merely unrecognized instruction. An unrecognized
> instruction can occur
> for many reasons, e.g., a bad jump.
>
> Oza> + if ((8 ==
> arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> Oza> + || (12 ==
> arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> + || (9 ==
> arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> Oza> + || (13 ==
> arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
>
> Oza> + || (0 ==
> arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>
> Oza> + || (4 ==
> arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> + || (1 ==
> arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> + || (5 ==
> arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>
> This reads very oddly. Is there a particular reason
> behind the ordering
> (if so -- document). If not, isn't this:
>
> if (arm_insn_r->opcode >= 0 &&
> arm_insn_r->opcode <= 15)
>
> There are other odd-looking conditions like this.
>
> Oza> +
> default:
> Oza> +
> gdb_assert_not_reached ("Invalid addressing mode for
> insn");
>
> Again, assert seems wrong.
>
> I'm afraid I ran out of steam here. Please fix all
> the issues already
> noted and look at the rest of the patch with a critical eye
> to see what
> else should be cleaned up. I want this patch to go
> in, but first it
> must comply to the usual gdb standards.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-07-13 3:17 ` chandra krishnappa
@ 2011-07-13 5:36 ` paawan oza
2011-07-13 15:20 ` Tom Tromey
1 sibling, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-07-13 5:36 UTC (permalink / raw)
To: chandra krishnappa, Tom Tromey; +Cc: gdb-patches, Petr Hluzín
I appreciate your effort on this Chandra K; will be sending you updated patch
with Tom's comments fixed.
thanks for you work and time.
Oza.
----- Original Message ----
From: chandra krishnappa <chandra_roadking@yahoo.com>
To: paawan oza <paawan1982@yahoo.com>; Tom Tromey <tromey@redhat.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wed, July 13, 2011 7:33:50 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>
Hi,
I am trying to the test if the existing gdb.reverse works with the ARM porting
done by Oza..
I am a learner, and I am taking more time than a average developer to get
documentation, read, understand and complete the testing of ARM porting of
reversible....
Thanks & Regards,
-Chandra K
--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:
> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "paawan oza" <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 2:29 AM
> >>>>> "Oza" == paawan
> oza <paawan1982@yahoo.com>
> writes:
>
> Oza> any more comments are welcome make this patch ok,
> if ARM person can
> Oza> have a look at it it would be great.
>
> You have submitted this patch many times now and nobody has
> commented
> on the details of the ARM decoding. I think we should
> proceed on the
> theory that this is simply not going to happen.
>
> Also, I am not as concerned about the correctness of every
> detail as I
> am about the general maintainability and style of the
> code. I expect
> there will be bugs; those can be fixed.
>
> You need a ChangeLog entry. A patch of this magnitude
> should also have
> a NEWS entry.
>
> Some kind of testing would be good. Do the existing
> tests in
> gdb.reverse work with your port? If so then I think
> that is sufficient
>
> Oza> + unsigned int reg_len = 0; reg_len =
> LENGTH; \
>
> Just write unsigned int reg_len = LENGTH;
>
> Oza> + REGS = (uint32_t*)
> xmalloc (sizeof(uint32_t) * (reg_len)); \
>
> Mind the spaces and parens. Better, use XNEWVEC:
>
> REGS = XNEWVEC (uint32_t, reg_len);
>
> Oza> + while (reg_len) \
> Oza> + { \
> Oza> +
> REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
> Oza> +
> reg_len--; \
> Oza> + } \
>
> Just use memcpy.
>
> Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>
> The same comments apply for this macro.
>
> Oza> +/* ARM instruction record contains opcode of
> current insn and execution state
> Oza> (before entry to
>
> Oza> +decode_insn() ), contains list of to-be-modified
> registers and memory blocks
> Oza> (on return from
>
> Your email got corrupted. Usually this is some bad
> MUA setting.
>
> Oza> + uint32_t mem_rec_count;
> /* No of mem recors */
>
> Typo, "recors"
>
> Oza> +/* Checks ARM SBZ and SBO mendatory fields.
> */
>
> Typo, should be "mandatory".
>
> Oza> + if(!sbo)
>
> Spacing.
>
> Oza> + if ((3 == opcode1) && (bit
> (arm_insn_r->arm_insn, 4)))
>
> Over-parenthesizing makes the code harder to read.
> Please fix this. I
> noticed it in many places. This specific case should
> read:
>
> if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
>
> Oza> + memset(&u_buf, 0, sizeof (u_buf));
>
> Spacing. Just go through the entire patch and fix all
> the spacing
> issues.
>
> I feel like I have mentioned this before.
>
> Oza> + regcache_raw_read_unsigned
> (reg_cache, reg_src1
> Oza> +
>
> , &u_buf[0].unsigned_regval);
>
> What if this does not return REG_VALID?
> There are multiple instances of this.
>
> Oza> + gdb_assert_not_reached ("no
> decoding pattern found");
>
> It seems wrong to use an assert in this code. At
> least, it is not
> obvious to me that this represents a logic error in gdb as
> opposed to a
> merely unrecognized instruction. An unrecognized
> instruction can occur
> for many reasons, e.g., a bad jump.
>
> Oza> + if ((8 ==
> arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> Oza> + || (12 ==
> arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> + || (9 ==
> arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> Oza> + || (13 ==
> arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
>
> Oza> + || (0 ==
> arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>
> Oza> + || (4 ==
> arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> + || (1 ==
> arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> + || (5 ==
> arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>
> This reads very oddly. Is there a particular reason
> behind the ordering
> (if so -- document). If not, isn't this:
>
> if (arm_insn_r->opcode >= 0 &&
> arm_insn_r->opcode <= 15)
>
> There are other odd-looking conditions like this.
>
> Oza> +
> default:
> Oza> +
> gdb_assert_not_reached ("Invalid addressing mode for
> insn");
>
> Again, assert seems wrong.
>
> I'm afraid I ran out of steam here. Please fix all
> the issues already
> noted and look at the rest of the patch with a critical eye
> to see what
> else should be cleaned up. I want this patch to go
> in, but first it
> must comply to the usual gdb standards.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-07-13 3:17 ` chandra krishnappa
2011-07-13 5:36 ` paawan oza
@ 2011-07-13 15:20 ` Tom Tromey
2011-07-14 4:49 ` chandra krishnappa
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-07-13 15:20 UTC (permalink / raw)
To: chandra krishnappa; +Cc: paawan oza, gdb-patches, Petr Hluzín
>>>>> "Chandra" == chandra krishnappa <chandra_roadking@yahoo.com> writes:
Chandra> I am trying to the test if the existing gdb.reverse works with the ARM
Chandra> porting done by Oza..
Great, thank you.
Chandra> I am a learner, and I am taking more time than a average developer to
Chandra> get documentation, read, understand and complete the testing of ARM
Chandra> porting of reversible....
No problem. Feel free to send email if you have questions, or join us
on irc.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-07-13 15:20 ` Tom Tromey
@ 2011-07-14 4:49 ` chandra krishnappa
2011-07-14 15:01 ` Yao Qi
0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-07-14 4:49 UTC (permalink / raw)
To: Tom Tromey; +Cc: paawan oza, gdb-patches, Petr Hluzín
two questions... rather I would derive directions out of it....
1. what is the common time I can find you and Oza online or active on IRC?
2. gdb test development active members, with whom I may seek help??
Thanks & Regards,
-Chandra K
--- On Wed, 7/13/11, Tom Tromey <tromey@redhat.com> wrote:
> From: Tom Tromey <tromey@redhat.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "chandra krishnappa" <chandra_roadking@yahoo.com>
> Cc: "paawan oza" <paawan1982@yahoo.com>, gdb-patches@sourceware.org, "Petr Hluzín" <petr.hluzin@gmail.com>
> Date: Wednesday, July 13, 2011, 7:29 PM
> >>>>> "Chandra" ==
> chandra krishnappa <chandra_roadking@yahoo.com>
> writes:
>
> Chandra> I am trying to the test if the existing
> gdb.reverse works with the ARM
> Chandra> porting done by Oza..
>
> Great, thank you.
>
> Chandra> I am a learner, and I am taking more time than
> a average developer to
> Chandra> get documentation, read, understand and
> complete the testing of ARM
> Chandra> porting of reversible....
>
> No problem. Feel free to send email if you have
> questions, or join us
> on irc.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-07-12 21:10 ` Tom Tromey
2011-07-13 3:17 ` chandra krishnappa
@ 2011-07-13 6:57 ` paawan oza
[not found] ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
2 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-07-13 6:57 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín
Thanks for your comments; I think I will need to scrutinize the overall patch
and make it correct with your comments.
I understand this patch has been lying around,but as Chandra K is working on the
port of gdb.reverse, we will see the results soon.
Regards,
Oza.
----- Original Message ----
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wed, July 13, 2011 2:29:36 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.
You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding. I think we should proceed on the
theory that this is simply not going to happen.
Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code. I expect
there will be bugs; those can be fixed.
You need a ChangeLog entry. A patch of this magnitude should also have
a NEWS entry.
Some kind of testing would be good. Do the existing tests in
gdb.reverse work with your port? If so then I think that is sufficient
Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
Just write unsigned int reg_len = LENGTH;
Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Mind the spaces and parens. Better, use XNEWVEC:
REGS = XNEWVEC (uint32_t, reg_len);
Oza> + while (reg_len) \
Oza> + { \
Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
Oza> + reg_len--; \
Oza> + } \
Just use memcpy.
Oza> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
The same comments apply for this macro.
Oza> +/* ARM instruction record contains opcode of current insn and execution
state
Oza> (before entry to
Oza> +decode_insn() ), contains list of to-be-modified registers and memory
blocks
Oza> (on return from
Your email got corrupted. Usually this is some bad MUA setting.
Oza> + uint32_t mem_rec_count; /* No of mem recors */
Typo, "recors"
Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
Typo, should be "mandatory".
Oza> + if(!sbo)
Spacing.
Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
Over-parenthesizing makes the code harder to read. Please fix this. I
noticed it in many places. This specific case should read:
if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
Oza> + memset(&u_buf, 0, sizeof (u_buf));
Spacing. Just go through the entire patch and fix all the spacing
issues.
I feel like I have mentioned this before.
Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> + , &u_buf[0].unsigned_regval);
What if this does not return REG_VALID?
There are multiple instances of this.
Oza> + gdb_assert_not_reached ("no decoding pattern found");
It seems wrong to use an assert in this code. At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction. An unrecognized instruction can occur
for many reasons, e.g., a bad jump.
Oza> + if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
This reads very oddly. Is there a particular reason behind the ordering
(if so -- document). If not, isn't this:
if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
There are other odd-looking conditions like this.
Oza> + default:
Oza> + gdb_assert_not_reached ("Invalid addressing mode for
insn");
Again, assert seems wrong.
I'm afraid I ran out of steam here. Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up. I want this patch to go in, but first it
must comply to the usual gdb standards.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
[parent not found: <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>]
* Re: [PATCH] arm reversible : <phase_2_complete>
[not found] ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
@ 2011-09-19 7:37 ` paawan oza
2011-09-22 17:12 ` oza Pawandeep
2011-10-14 20:13 ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
0 siblings, 2 replies; 128+ messages in thread
From: paawan oza @ 2011-09-19 7:37 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa
Hi all,
Sorry for delay in fixing review comments.
Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
PATCH STARTS
----------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address
(gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN
arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,1769 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define
REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ }
\
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn and execution state (before entry to
+decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
+decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t
cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn,
uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits
(arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (!opcode1 && (9 == opcode2))
+ {
+ ret = -1;
+ /* Handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+
{
+ ret = -1;
+ /* Handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+ && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To
be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t
record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 ==
arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
}
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+
{
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+
{
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /*
Handling SWP, SWPB. */
+ /* These insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] =
4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12,
1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software
breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit
(arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+
regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) |
immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count =
1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ ,
&u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+
}
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+
record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 =
(immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+
}
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 ==
arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ ,
&u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+
else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+
}
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz
(arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+
record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+
{
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+
)
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data
processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns.
*/
+
+static int
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching,
if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] =
reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache,
reg_src1
+ , &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+
{
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 4:
+ case 0:
+
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case
7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+
arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed
mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t
reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ LONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+
{
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+
}
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get
Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache,
reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval =
u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
+ u_buf[1].unsigned_regval;
+
}
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
+ u_buf[0].unsigned_regval;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case
8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case
4:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+
default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16,
19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ ,
&u_buf[0].signed_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index.
*/
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
+ break;
+
+ case 2:
+ if
(!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+
else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift.
*/
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache,
ARM_PS_REGNUM
+ , &u_buf[1].unsigned_regval);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+ | (u_buf[0].unsigned_regval) >>
1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
+
}
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* U == 1
*/
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch
(arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case
5:
+ /* STR */
+ case 0:
+ case 4:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+
/* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn.
*/
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count =
1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 ==
arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0,
sizeof(u_buf));
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+
else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for
Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers and dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /*
Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address +
4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] =
start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count =
register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case
3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+
register_count--;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode
101 insns. */
+
+static int
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* Wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
0;
+ uint32_t start_address = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record
support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] =
ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn,
12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8)
&& (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache,
reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] =
2; /* STRH (2). */
+ record_buf_mem[1] = u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1
= reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache,
reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t
record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0,
2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 ==
opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC
(thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 =
bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count +
2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache,
ARM_PC_REGNUM
+ , &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count))
;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn.
*/
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] =
ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+
{
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110
insns. */
+
+static int
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+
{
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for
(register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits
(thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] =
start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+
{
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+
uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_handle_data_proc_misc_ld_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_handle_ld_st_multiple_insn, /* 100.
*/
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
+ static int (*const thumb_handle_insn[8])
+
(insn_decode_record*) =
+ { \
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_handle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+
thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered
(_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28,
31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is useless. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* Yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+
arm_record->arm_insn,
+ paddress (arm_record->gdbarch, arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache
*regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog,
"Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* We are decoding arm
insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
+
{
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if
(arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct
gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
________________________________
From: Tom Tromey <tromey@redhat.com>
To: paawan oza <paawan1982@yahoo.com>
Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
Sent: Wednesday, 13 July 2011 1:29 AM
Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> any more comments are welcome make this patch ok, if ARM person can
Oza> have a look at it it would be great.
You have submitted this patch many times now and nobody has commented
on the details of the ARM decoding. I think we should proceed on the
theory that this is simply not going to happen.
Also, I am not as concerned about the correctness of every detail as I
am about the general maintainability and style of the code. I expect
there will be bugs; those can be fixed.
You need a ChangeLog entry. A patch of this magnitude
should also have
a NEWS entry.
Some kind of testing would be good. Do the existing tests in
gdb.reverse work with your port? If so then I think that is sufficient
Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
Just write unsigned int reg_len = LENGTH;
Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
Mind the spaces and parens. Better, use XNEWVEC:
REGS = XNEWVEC (uint32_t, reg_len);
Oza> + while (reg_len) \
Oza> + { \
Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
Oza> + reg_len--; \
Oza> + } \
Just use memcpy.
Oza> +#define
MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
The same comments apply for this macro.
Oza> +/* ARM instruction record contains opcode of current insn and execution state
Oza> (before entry to
Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
Oza> (on return from
Your email got corrupted. Usually this is some bad MUA setting.
Oza> + uint32_t mem_rec_count; /* No of mem recors */
Typo, "recors"
Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
Typo, should be "mandatory".
Oza> + if(!sbo)
Spacing.
Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
Over-parenthesizing makes the code harder to read. Please fix this. I
noticed it in many places. This specific case should read:
if (3 == opcode1 && bit
(arm_insn_r->arm_insn, 4))
Oza> + memset(&u_buf, 0, sizeof (u_buf));
Spacing. Just go through the entire patch and fix all the spacing
issues.
I feel like I have mentioned this before.
Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
Oza> + , &u_buf[0].unsigned_regval);
What if this does not return REG_VALID?
There are multiple instances of this.
Oza> + gdb_assert_not_reached ("no decoding pattern found");
It seems wrong to use an assert in this code. At least, it is not
obvious to me that this represents a logic error in gdb as opposed to a
merely unrecognized instruction. An unrecognized instruction can occur
for many reasons, e.g., a bad jump.
Oza> +
if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
This reads very oddly. Is there a particular reason behind the ordering
(if so -- document). If not, isn't
this:
if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
There are other odd-looking conditions like this.
Oza> + default:
Oza> + gdb_assert_not_reached ("Invalid addressing mode for insn");
Again, assert seems wrong.
I'm afraid I ran out of steam here. Please fix all the issues already
noted and look at the rest of the patch with a critical eye to see what
else should be cleaned up. I want this patch to go in, but first it
must comply to the usual gdb standards.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-09-19 7:37 ` paawan oza
@ 2011-09-22 17:12 ` oza Pawandeep
2011-09-27 6:52 ` oza Pawandeep
2011-10-14 20:13 ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-09-22 17:12 UTC (permalink / raw)
To: Tom Tromey, gdb-patches, Petr Hluzín, chandra krishnappa
Hello Chandra,
Let me know if you are planning to do anymore basic testing on this patch.
@Tom: is it possible to get this patch move in, of course I have been
keen on any review comment; but it has been lying around for a long
time.
and I would like to move to phase-3 implementation then.
Regards,
Oza.
On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>
>
> Hi all,
>
> Sorry for delay in fixing review comments.
>
> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>
> PATCH STARTS
> ----------------------------------
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
> set_gdbarch_fetch_tls_load_module_address
> (gdbarch,
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch, arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff -urN
> arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -8821,3 +8823,1769 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define
> REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
> + } \
> + }
> \
> +while (0)
> +
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn and execution state (before entry to
> +decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
> +decode_insn() ). */
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t
> cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records */
> + uint32_t reg_rec_count; /* No of reg records */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn,
> uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = bits
> (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to handle if later versions
> + define it. */
> + }
> +
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (!opcode1 && (9 == opcode2))
> + {
> + ret = -1;
> + /* Handle arithmetic insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> +
> {
> + ret = -1;
> + /* Handle control insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
> + && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Handle load/store insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* To
> be done for ARMv5 and later; as of now we return -1. */
> + if (-1 == ret)
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t
> record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 ==
> arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> +
> }
> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is preccedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> +
> {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> +
> {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /*
> Handling SWP, SWPB. */
> + /* These insns, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] =
> 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12,
> 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
> + {
> + /* Handle enhanced software
> breakpoint insn, BKPT */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* Accorindly to high vector configuration PC is set accordingly */
> + /* What if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit
> (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD)
> + let us begin according to addressing modes for store insns
> + STRH insn, addresing modes are taken following. */
> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> +
> regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + if (15 == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + offset_8 = (immed_high << 4) |
> immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count =
> 1;
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> +
> }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> +
> record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 =
> (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> +
> }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 ==
> arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> +
> else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> +
> }
> + /* DSP insns (e.g. LDRD) TBD. */
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> +
> record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> +
> {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && (2 == bits (arm_insn_r->arm_insn, 20, 21))
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> +
> )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /*CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data
> processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns.
> */
> +
> +static int
> +arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching,
> if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] =
> reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Store, immediate offset, immediate pre-indexed,
> + immediate post-indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + , &u_buf.unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf.unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf.unsigned_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> +
> {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 4:
> + case 0:
> +
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case
> 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> +
> arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* We are handling pre-indexed mode; post-indexed
> mode;
> + where Rn is going to be changed. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t
> reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + LONGEST signed_word;
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + let us begin according to addressing modes for store insns
> + STRH insn. */
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> +
> {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> +
> }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and register pre-indexed,
> + register post-indexed. */
> + /* Get
> Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> + , &u_buf[1].unsigned_regval);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval +
> + u_buf[1].unsigned_regval;
> +
> }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval -
> + u_buf[0].unsigned_regval;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case
> 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 0:
> + case
> 4:
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> +
> default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in pre-indexed mode and
> + post-indexed mode as well. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset; scaled pre-indexed. */
> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + /* Get shift_imm. */
> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_signed (reg_cache, reg_src1
> + ,
> &u_buf[0].signed_word);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* Offset_12 used as shift. */
> + switch (offset_12)
> + {
> + case 0:
> + /* Offset_12 used as index.
> */
> + offset_12 = u_buf[0].unsigned_regval << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
> + break;
> +
> + case 2:
> + if
> (!shift_imm)
> + {
> + if (bit (u_buf[0].unsigned_regval, 31))
> + {
> + offset_12 = 0xFFFFFFFF;
> + }
> +
> else
> + {
> + offset_12 = 0;
> + }
> + }
> + else
> + {
> + /* This is arithmetic shift.
> */
> + offset_12 = u_buf[0].signed_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> + regcache_raw_read_unsigned (reg_cache,
> ARM_PS_REGNUM
> + , &u_buf[1].unsigned_regval);
> + /* Get C flag value and shift it by 31. */
> + offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
> + | (u_buf[0].unsigned_regval) >>
> 1);
> + }
> + else
> + {
> + offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
> + | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
> +
> }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* U == 1
> */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
> + }
> +
> + switch
> (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case
> 5:
> + /* STR */
> + case 0:
> + case 4:
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> +
> /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn.
> */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count =
> 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in register scaled pre-indexed
> + mode, and scaled post indexed mode. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0,
> sizeof(u_buf));
> +
> + /* This mode is exclusively for load and store multiple. */
> + /* Handle incremenrt after/before and decrment after.before mode;
> + Rn is changing depending on W bit, but as of now we store Rn too without optmization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
> +
> + if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> +
> else
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> +
> + /* Extra space for
> Base Register and CPSR; wihtout optmization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = register_count + 2;
> +
> + for (register_count = 0; register_count < no_of_regs; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + /* Register_count gives total no of registers and dually working
> + as reg number. */
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + /*
> Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch (addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address +
> 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] =
> start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case
> 3:
> + start_address = u_buf[0].unsigned_regval + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> +
> register_count--;
> + }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + /* Base register also changes; based on condition and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode
> 101 insns. */
> +
> +static int
> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* Wihtout optmization we save link register,
> + CSPR for the insn which changes T bit. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
> 0;
> + uint32_t start_address = 0;
> +
> + /* Handle SWI insn; system call would be handled over here. */
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
> + if (15 == arm_insn_r->opcode)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record
> support\n"));
> + return -1;
> + }
> + }
> +
> + 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;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> +
> + record_buf[0] =
> ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + gdb_byte buf[4];
> + } u_buf[2];
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
> +
> + if (bit (thumb_insn_r->arm_insn,
> 12))
> + {
> + /* Handle load/store register offset. */
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
> + if ((opcode2 >= 12) && (opcode2 <= 15))
> + {
> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
> + reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if ((opcode2 >= 8)
> && (opcode2 <= 10))
> + {
> + /* STR(2), STRB(2), STRH(2) . */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> + , &u_buf[1].unsigned_regval);
> + if (8 == opcode2)
> + record_buf_mem[0] = 4; /* STR (2). */
> + else if (10 == opcode2)
> + record_buf_mem[0] = 1; /* STRB (2). */
> + else if (9 == opcode2)
> + record_buf_mem[0] =
> 2; /* STRH (2). */
> + record_buf_mem[1] = u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + }
> + else if (bit (thumb_insn_r->arm_insn, 11))
> + {
> + /* Handle load from literal pool. */
> + /* LDR(3). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode1)
> + {
> + opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
> + opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if ((3 == opcode2) && (!opcode3))
> + {
> + /* Branch with exchange. */
> + record_buf[0] = ARM_PS_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + 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;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Format 5; data processing insns. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if (bit (thumb_insn_r->arm_insn, 7))
> + {
> + reg_src1
> = reg_src1 + 8;
> + }
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> +
> struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (opcode)
> + {
> + /* LDR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* STR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t
> record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (3 == opcode)
> + {
> + /* LDR(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == opcode)
> + {
> + /* LDRH(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* STR(3). */
> + immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
> + , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + else if (0 ==
> opcode)
> + {
> + /* STRH(1). */
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC
> (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 =
> bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count +
> 2;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache,
> ARM_PC_REGNUM
> + , &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval - \
> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count))
> ;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn.
> */
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* Accorindly to high vector configuration PC is set accordingly. */
> + /* FIX ME ? what if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter.. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] =
> ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* Save SPSR also; how?. */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb_insn_r->arm_insn,
> + paddress (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> +
> {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110
> insns. */
> +
> +static int
> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> +
> {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count + 1;
> + for
> (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits
> (thumb_insn_r->arm_insn, 8, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] =
> start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> + else
> +
> {
> + printf_unfiltered (_("no syscall record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B(1), conditional branch is automatically taken care in process_record,
> + as PC is saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> +
> uint32_t opcode = 0, immed_5 = 0;
> +
> +
> + /* BL , BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + /* B(2) is automatically taken care in process_record, as PC is saved
> + there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
> + static int (*const arm_handle_insn[8])
> + (insn_decode_record*) =
> + {
> + arm_handle_data_proc_misc_ld_str_insn, /* 000. */
> + arm_handle_data_proc_imm_insn, /* 001. */
> + arm_handle_ld_st_imm_offset_insn, /* 010. */
> + arm_handle_ld_st_reg_offset_insn, /* 011. */
> + arm_handle_ld_st_multiple_insn, /* 100.
> */
> + arm_handle_brn_insn, /* 101. */
> + arm_handle_coproc_insn, /* 110. */
> + arm_handle_coproc_data_proc_insn /* 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
> + static int (*const thumb_handle_insn[8])
> +
> (insn_decode_record*) =
> + { \
> + thumb_handle_shift_add_sub_insn, /* 000. */
> + thumb_handle_add_sub_cmp_mov_insn, /* 001. */
> + thumb_handle_ld_st_reg_offset_insn, /* 010. */
> + thumb_handle_ld_st_imm_offset_insn, /* 011. */
> + thumb_handle_ld_st_stack_insn, /* 100. */
> + thumb_handle_misc_insn, /* 101. */
> +
> thumb_handle_swi_insn, /* 110. */
> + thumb_handle_branch_insn /* 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered
> (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_INSN_SIZE_BYTES == insn_size)
> + {
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> + arm_record->cond = bits (arm_record->arm_insn, 28,
> 31);
> + insn_id = bits (arm_record->arm_insn, 25, 27);
> + ret = (0x0F != arm_record->cond)
> + ? arm_handle_insn[insn_id] (arm_record)
> + : handle_extension_space (arm_record);
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes, following field is useless. */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> +
> + insn_id = bits (arm_record->arm_insn, 13, 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> + {
> + /* Yet to be implemented; handle thumb2 part here. */
> + printf_unfiltered (_("Process record does not support instruction 0x%0x "
> + "at address %s.\n"),
> +
> arm_record->arm_insn,
> + paddress (arm_record->gdbarch, arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to "record_arch_list".
> + Return -1 if something is wrong.. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache
> *regcache,
> + CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog,
> "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one. */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
> + , &u_buf.unsigned_regval);
> +
> + if (!(u_buf.unsigned_regval & t_bit))
> + {
> + /* We are decoding arm
> insn. */
> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
> +
> {
> + if (record_arch_list_add_reg (arm_record.regcache \
> + , (arm_record.arm_regs[no_of_rec])))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> + arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if
> (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
> /* Return the expected next PC if FRAME is stopped at a syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
> /* Structures used for displaced stepping. */
> @@ -331,6 +334,8 @@
> instruction? */
> extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct
> gdbarch *gdbarch,
> + struct regcache *regcache, CORE_ADDR addr);
> /* Functions exported from armbsd-tdep.h. */
>
> /* Return the appropriate register set for the core section identified
>
>
>
>
> ________________________________
> From: Tom Tromey <tromey@redhat.com>
> To: paawan oza <paawan1982@yahoo.com>
> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
> Sent: Wednesday, 13 July 2011 1:29 AM
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>
>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>
> Oza> any more comments are welcome make this patch ok, if ARM person can
> Oza> have a look at it it would be great.
>
> You have submitted this patch many times now and nobody has commented
> on the details of the ARM decoding. I think we should proceed on the
> theory that this is simply not going to happen.
>
> Also, I am not as concerned about the correctness of every detail as I
> am about the general maintainability and style of the code. I expect
> there will be bugs; those can be fixed.
>
> You need a ChangeLog entry. A patch of this magnitude
> should also have
> a NEWS entry.
>
> Some kind of testing would be good. Do the existing tests in
> gdb.reverse work with your port? If so then I think that is sufficient
>
> Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
>
> Just write unsigned int reg_len = LENGTH;
>
> Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>
> Mind the spaces and parens. Better, use XNEWVEC:
>
> REGS = XNEWVEC (uint32_t, reg_len);
>
> Oza> + while (reg_len) \
> Oza> + { \
> Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
> Oza> + reg_len--; \
> Oza> + } \
>
> Just use memcpy.
>
> Oza> +#define
> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>
> The same comments apply for this macro.
>
> Oza> +/* ARM instruction record contains opcode of current insn and execution state
> Oza> (before entry to
>
> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
> Oza> (on return from
>
> Your email got corrupted. Usually this is some bad MUA setting.
>
> Oza> + uint32_t mem_rec_count; /* No of mem recors */
>
> Typo, "recors"
>
> Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
>
> Typo, should be "mandatory".
>
> Oza> + if(!sbo)
>
> Spacing.
>
> Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>
> Over-parenthesizing makes the code harder to read. Please fix this. I
> noticed it in many places. This specific case should read:
>
> if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
>
> Oza> + memset(&u_buf, 0, sizeof (u_buf));
>
> Spacing. Just go through the entire patch and fix all the spacing
> issues.
>
> I feel like I have mentioned this before.
>
> Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
> Oza> + , &u_buf[0].unsigned_regval);
>
> What if this does not return REG_VALID?
> There are multiple instances of this.
>
> Oza> + gdb_assert_not_reached ("no decoding pattern found");
>
> It seems wrong to use an assert in this code. At least, it is not
> obvious to me that this represents a logic error in gdb as opposed to a
> merely unrecognized instruction. An unrecognized instruction can occur
> for many reasons, e.g., a bad jump.
>
> Oza> +
> if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
> Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
> Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>
> This reads very oddly. Is there a particular reason behind the ordering
> (if so -- document). If not, isn't
> this:
>
> if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>
> There are other odd-looking conditions like this.
>
> Oza> + default:
> Oza> + gdb_assert_not_reached ("Invalid addressing mode for insn");
>
> Again, assert seems wrong.
>
> I'm afraid I ran out of steam here. Please fix all the issues already
> noted and look at the rest of the patch with a critical eye to see what
> else should be cleaned up. I want this patch to go in, but first it
> must comply to the usual gdb standards.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-09-22 17:12 ` oza Pawandeep
@ 2011-09-27 6:52 ` oza Pawandeep
2011-10-06 18:01 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-09-27 6:52 UTC (permalink / raw)
To: Tom Tromey, gdb-patches, Petr Hluzín
Hi Tom,
What do you think about the patch to be ready to to move in <phase_2> ?
Any more comments are welcome from ARM specific community here.
most of the review comments from Michael, Petr, Tom and other folks
have been implemented.
Regards,
Oza.
On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hello Chandra,
>
> Let me know if you are planning to do anymore basic testing on this patch.
>
> @Tom: is it possible to get this patch move in, of course I have been
> keen on any review comment; but it has been lying around for a long
> time.
> and I would like to move to phase-3 implementation then.
>
> Regards,
> Oza.
>
> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>
>>
>> Hi all,
>>
>> Sorry for delay in fixing review comments.
>>
>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>
>> PATCH STARTS
>> ----------------------------------
>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
>> @@ -1025,6 +1025,9 @@
>> set_gdbarch_fetch_tls_load_module_address
>> (gdbarch,
>> svr4_fetch_objfile_link_map);
>>
>> + /* Enable process record. */
>> + set_gdbarch_process_record (gdbarch, arm_process_record);
>> +
>> tramp_frame_prepend_unwinder (gdbarch,
>> &arm_linux_sigreturn_tramp_frame);
>> tramp_frame_prepend_unwinder (gdbarch,
>> @@ -1054,6 +1057,8 @@
>>
>>
>> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>> +
>> + tdep->arm_swi_record = NULL;
>> }
>>
>> /* Provide a prototype to silence -Wmissing-prototypes. */
>> diff -urN
>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
>> @@ -55,6 +55,8 @@
>> #include "gdb_assert.h"
>> #include "vec.h"
>>
>> +#include "record.h"
>> +
>> #include "features/arm-with-m.c"
>>
>> static int arm_debug;
>> @@ -8821,3 +8823,1769 @@
>> NULL, /* FIXME: i18n: "ARM debugging is %s. */
>> &setdebuglist, &showdebuglist);
>> }
>> +/* ARM-reversible process record data structures. */
>> +
>> +#define ARM_INSN_SIZE_BYTES 4
>> +#define THUMB_INSN_SIZE_BYTES 2
>> +#define THUMB2_INSN_SIZE_BYTES 4
>> +
>> +#define INSN_S_L_BIT_NUM 20
>> +
>> +#define
>> REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
>> +do \
>> + { \
>> + unsigned int reg_len = LENGTH; \
>> + if (reg_len) \
>> + { \
>> + REGS = XNEWVEC (uint32_t, reg_len); \
>> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>> + } \
>> + } \
>> +while (0)
>> +
>> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>> +do \
>> + { \
>> + unsigned int mem_len = LENGTH; \
>> + if (mem_len) \
>> + { \
>> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
>> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>> + } \
>> + }
>> \
>> +while (0)
>> +
>> +
>> +/* ARM memory record structure. */
>> +struct arm_mem_r
>> +{
>> + uint32_t len; /* Record length. */
>> + CORE_ADDR addr; /* Memory address. */
>> +};
>> +
>> +/* ARM instruction record contains opcode of current insn and execution state (before entry to
>> +decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
>> +decode_insn() ). */
>> +typedef struct insn_decode_record_t
>> +{
>> + struct gdbarch *gdbarch;
>> + struct regcache *regcache;
>> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
>> + uint32_t arm_insn; /* Should accommodate thumb. */
>> + uint32_t
>> cond; /* Condition code. */
>> + uint32_t opcode; /* Insn opcode. */
>> + uint32_t decode; /* Insn decode bits. */
>> + uint32_t mem_rec_count; /* No of mem records */
>> + uint32_t reg_rec_count; /* No of reg records */
>> + uint32_t *arm_regs; /* Registers to be saved for this record. */
>> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
>> +} insn_decode_record;
>> +
>> +
>> +/* Checks ARM SBZ and SBO mandatory fields. */
>> +
>> +static int
>> +sbo_sbz (uint32_t insn,
>> uint32_t bit_num, uint32_t len, uint32_t sbo)
>> +{
>> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
>> +
>> + if (!len)
>> + return 1;
>> +
>> + if (!sbo)
>> + ones = ~ones;
>> +
>> + while (ones)
>> + {
>> + if (!(ones & sbo))
>> + {
>> + return 0;
>> + }
>> + ones = ones >> 1;
>> + }
>> + return 1;
>> +}
>> +
>> +/* Handling ARM extension space insns. */
>> +
>> +static int
>> +handle_extension_space (insn_decode_record *arm_insn_r)
>> +{
>> + uint32_t ret = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0;
>> +
>> + opcode1 = bits
>> (arm_insn_r->arm_insn, 25, 27);
>> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
>> + {
>> + ret = -1;
>> + /* Undefined instruction on ARM V5; need to handle if later versions
>> + define it. */
>> + }
>> +
>> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> + if (!opcode1 && (9 == opcode2))
>> + {
>> + ret = -1;
>> + /* Handle arithmetic insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>> +
>> {
>> + ret = -1;
>> + /* Handle control insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>> + && bit (arm_insn_r->arm_insn, 4))
>> + {
>> + ret = -1;
>> + /* Handle load/store insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>> + {
>> + ret = -1;
>> + /* Handle coprocessor insn extension space. */
>> + }
>> +
>> + /* To
>> be done for ARMv5 and later; as of now we return -1. */
>> + if (-1 == ret)
>> + 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 ret;
>> +}
>> +
>> +/* Handling opcode 000 insns. */
>> +
>> +static int
>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> + uint32_t
>> record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> +
>> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
>> + uint32_t opcode1 = 0;
>> +
>> + memset (&u_buf, 0, sizeof (u_buf));
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
>> +
>> + /* Data processing insn /multiply insn. */
>> + if ((9 == arm_insn_r->decode)
>> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
>> + || ((0 == arm_insn_r->opcode) || (1 ==
>> arm_insn_r->opcode))))
>> + {
>> + /* Handle multiply instructions. */
>> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
>> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
>> + {
>> + /* Handle MLA and MUL. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> +
>> }
>> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
>> + {
>> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
>> + record_buf[2] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 3;
>> + }
>> + }
>> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
>> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
>> + {
>> + /* Handle misc load insns, as 20th bit (L = 1). */
>> + /* LDR insn has a capability to do branching, if
>> + MOV LR, PC is preccedded by LDR insn having Rn as R15
>> + in that case, it emulates branch and link insn, and hence we
>> + need to save CSPR and PC as well. I am not sure this is right
>> + place as opcode = 010 LDR insn make this happen, if R15 was
>> + used. */
>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> +
>> {
>> + record_buf[0] = reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
>> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
>> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
>> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
>> + {
>> + /* Handle MSR insn. */
>> + if (9 == arm_insn_r->opcode)
>> +
>> {
>> + /* CSPR is going to be changed. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* 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;
>> + }
>> + }
>> + else if ((9 == arm_insn_r->decode)
>> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + /*
>> Handling SWP, SWPB. */
>> + /* These insns, changes register and memory as well. */
>> + /* SWP or SWPB insn. */
>> + /* Get memory address given by Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + /* SWP insn ?, swaps word. */
>> + if (8 == arm_insn_r->opcode)
>> + {
>> + record_buf_mem[0] =
>> 4;
>> + }
>> + else
>> + {
>> + /* SWPB insn, swaps only byte. */
>> + record_buf_mem[0] = 1;
>> + }
>> + record_buf_mem[1] = u_buf[0].unsigned_regval;
>> + arm_insn_r->mem_rec_count = 1;
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12,
>> 1))
>> + {
>> + /* Handle BLX, branch and link/exchange. */
>> + if (9 == arm_insn_r->opcode)
>> + {
>> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
>> + and R14 stores the return address. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
>> + {
>> + /* Handle enhanced software
>> breakpoint insn, BKPT */
>> + /* CPSR is changed to be executed in ARM state, disabling normal
>> + interrupts, entering abort mode. */
>> + /* Accorindly to high vector configuration PC is set accordingly */
>> + /* What if user hit breakpoint and type reverse, in
>> + that case, we need to go back with previous CPSR and
>> + Program Counter. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + 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)
>> + && !bit
>> (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + /* Handle enhanced store insns and DSP insns (e.g. LDRD)
>> + let us begin according to addressing modes for store insns
>> + STRH insn, addresing modes are taken following. */
>> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>> + {
>> + /* 1) Handle misc store, immediate offset. */
>> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
>> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> +
>> regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + if (15 == reg_src1)
>> + {
>> + /* If R15 was used as Rn, hence current PC+8. */
>> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>> + }
>> + offset_8 = (immed_high << 4) |
>> immed_low;
>> + /* Calculate target store address. */
>> + if (14 == arm_insn_r->opcode)
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count =
>> 1;
>> + }
>> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>> + {
>> + /* 2) Store, register offset. */
>> + /* Get Rm. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>> + /* Get Rn. */
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + if (15 == reg_src2)
>> + {
>> + /* If R15 was used as Rn, hence current PC+8. */
>> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>> +
>> }
>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>> + if (12 == arm_insn_r->opcode)
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>> + }
>> +
>> record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + }
>> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>> + {
>> + /* 3) Store, immediate pre-indexed. */
>> + /* 5) Store, immediate post-indexed. */
>> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
>> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
>> + offset_8 =
>> (immed_high << 4) | immed_low;
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>> +
>> }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + /* Record Rn also as it changes. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((9 ==
>> arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>> + {
>> + /* 4) Store, register pre-indexed. */
>> + /* 6) Store, register post -indexed. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>> + }
>> +
>> else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + /* Record Rn also as it changes. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>> + arm_insn_r->reg_rec_count = 1;
>> +
>> }
>> + /* DSP insns (e.g. LDRD) TBD. */
>> + }
>> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
>> + {
>> + /* Handle BX, branch and link/exchange. */
>> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
>> + && sbo_sbz
>> (arm_insn_r->arm_insn, 17, 4, 1))
>> + {
>> + /* Count leading zeros: CLZ. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
>> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
>> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
>> + )
>> + {
>> + /* Handle MRS insn. */
>> +
>> record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if (arm_insn_r->opcode <= 15)
>> + {
>> + /* Normal data processing insns. */
>> + /* Out of 11 shifter operands mode, all the insn modifies destination
>> + register, which is specified by 13-16 decode. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + else
>> +
>> {
>> + return -1;
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
>> +{
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> + if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
>> + && (2 == bits (arm_insn_r->arm_insn, 20, 21))
>> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
>> +
>> )
>> + {
>> + /* Handle MSR insn. */
>> + if (9 == arm_insn_r->opcode)
>> + {
>> + /*CSPR is going to be changed. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* SPSR is going to be changed. */
>> + }
>> + }
>> + else if (arm_insn_r->opcode <= 15)
>> + {
>> + /* Normal data
>> processing insns. */
>> + /* Out of 11 shifter operands mode, all the insn modifies destination
>> + register, which is specified by 13-16 decode. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + else
>> + {
>> + return -1;
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns.
>> */
>> +
>> +static int
>> +arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t reg_src1 = 0 , reg_dest = 0;
>> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + memset (&u_buf, 0, sizeof (u_buf));
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>> + /* LDR insn has a capability to do branching,
>> if
>> + MOV LR, PC is precedded by LDR insn having Rn as R15
>> + in that case, it emulates branch and link insn, and hence we
>> + need to save CSPR and PC as well. */
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + record_buf[0] =
>> reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + /* Store, immediate offset, immediate pre-indexed,
>> + immediate post-indexed. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + , &u_buf.unsigned_regval);
>> + /* U == 1 */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf.unsigned_regval - offset_12;
>> + }
>> +
>> + switch (arm_insn_r->opcode)
>> +
>> {
>> + /* STR */
>> + case 8:
>> + case 12:
>> + /* STR */
>> + case 9:
>> + case 13:
>> + /* STRT */
>> + case 1:
>> + case 5:
>> + /* STR */
>> + case 4:
>> + case 0:
>> +
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + /* STRB */
>> + case 10:
>> + case 14:
>> + /* STRB */
>> + case 11:
>> + case 15:
>> + /* STRBT */
>> + case 3:
>> + case
>> 7:
>> + /* STRB */
>> + case 2:
>> + case 6:
>> + /* STRB insn, STRBT insn. */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> + default:
>> + return -1;
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> +
>> arm_insn_r->mem_rec_count = 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>> + {
>> + /* We are handling pre-indexed mode; post-indexed
>> mode;
>> + where Rn is going to be changed. */
>> + record_buf[0] = reg_src1;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 011 insns. */
>> +
>> +static int
>> +arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t shift_imm = 0;
>> + uint32_t
>> reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + LONGEST signed_word;
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> + memset (&u_buf, 0, sizeof (u_buf));
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> + /* Handle enhanced store insns and LDRD DSP insn,
>> + let us begin according to addressing modes for store insns
>> + STRH insn. */
>> +
>> + /* LDR or STR? */
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> +
>> {
>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>> + /* LDR insn has a capability to do branching, if
>> + MOV LR, PC is precedded by LDR insn having Rn as R15
>> + in that case, it emulates branch and link insn, and hence we
>> + need to save CSPR and PC as well. */
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> +
>> }
>> + else
>> + {
>> + record_buf[0] = reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + if (! bits (arm_insn_r->arm_insn, 4, 11))
>> + {
>> + /* Store insn, register offset and register pre-indexed,
>> + register post-indexed. */
>> + /* Get
>> Rm. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>> + /* Get Rn. */
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + if (15 == reg_src2)
>> + {
>> + /* If R15 was used as Rn, hence current PC+8. */
>> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
>> + u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> + }
>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>> + /* U == 1. */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval +
>> + u_buf[1].unsigned_regval;
>> +
>> }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval -
>> + u_buf[0].unsigned_regval;
>> + }
>> +
>> + switch (arm_insn_r->opcode)
>> + {
>> + /* STR */
>> + case
>> 8:
>> + case 12:
>> + /* STR */
>> + case 9:
>> + case 13:
>> + /* STRT */
>> + case 1:
>> + case 5:
>> + /* STR */
>> + case 0:
>> + case
>> 4:
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + /* STRB */
>> + case 10:
>> + case 14:
>> + /* STRB */
>> + case 11:
>> + case 15:
>> + /* STRBT */
>> + case 3:
>> + case 7:
>> + /* STRB */
>> + case 2:
>> + case 6:
>> + /* STRB insn, STRBT insn. */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> +
>> default:
>> + return -1;
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>> + {
>> + /* Rn is going to be changed in pre-indexed mode and
>> + post-indexed mode as well. */
>> + record_buf[0] = reg_src2;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + else
>> + {
>> + /* Store insn, scaled register offset; scaled pre-indexed. */
>> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
>> + /* Get Rm. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>> + /* Get Rn. */
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + /* Get shift_imm. */
>> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + regcache_raw_read_signed (reg_cache, reg_src1
>> + ,
>> &u_buf[0].signed_word);
>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + /* Offset_12 used as shift. */
>> + switch (offset_12)
>> + {
>> + case 0:
>> + /* Offset_12 used as index.
>> */
>> + offset_12 = u_buf[0].unsigned_regval << shift_imm;
>> + break;
>> +
>> + case 1:
>> + offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>> + break;
>> +
>> + case 2:
>> + if
>> (!shift_imm)
>> + {
>> + if (bit (u_buf[0].unsigned_regval, 31))
>> + {
>> + offset_12 = 0xFFFFFFFF;
>> + }
>> +
>> else
>> + {
>> + offset_12 = 0;
>> + }
>> + }
>> + else
>> + {
>> + /* This is arithmetic shift.
>> */
>> + offset_12 = u_buf[0].signed_word >> shift_imm;
>> + }
>> + break;
>> +
>> + case 3:
>> + if (!shift_imm)
>> + {
>> + regcache_raw_read_unsigned (reg_cache,
>> ARM_PS_REGNUM
>> + , &u_buf[1].unsigned_regval);
>> + /* Get C flag value and shift it by 31. */
>> + offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>> + | (u_buf[0].unsigned_regval) >>
>> 1);
>> + }
>> + else
>> + {
>> + offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>> + | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>> +
>> }
>> + break;
>> +
>> + default:
>> + return -1;
>> + break;
>> + }
>> +
>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + /* U == 1
>> */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
>> + }
>> +
>> + switch
>> (arm_insn_r->opcode)
>> + {
>> + /* STR */
>> + case 8:
>> + case 12:
>> + /* STR */
>> + case 9:
>> + case 13:
>> + /* STRT */
>> + case 1:
>> + case
>> 5:
>> + /* STR */
>> + case 0:
>> + case 4:
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + /* STRB */
>> + case 10:
>> + case 14:
>> +
>> /* STRB */
>> + case 11:
>> + case 15:
>> + /* STRBT */
>> + case 3:
>> + case 7:
>> + /* STRB */
>> + case 2:
>> + case 6:
>> + /* STRB insn, STRBT insn.
>> */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> + default:
>> + return -1;
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count =
>> 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + /* Rn is going to be changed in register scaled pre-indexed
>> + mode, and scaled post indexed mode. */
>> + record_buf[0] = reg_src2;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns. */
>> +
>> +static int
>> +arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
>> + uint32_t shift_imm = 0;
>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>> + uint32_t start_address = 0, index = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> + memset (&u_buf, 0,
>> sizeof(u_buf));
>> +
>> + /* This mode is exclusively for load and store multiple. */
>> + /* Handle incremenrt after/before and decrment after.before mode;
>> + Rn is changing depending on W bit, but as of now we store Rn too without optmization. */
>> +
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
>> +
>> + if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
>> + {
>> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
>> + no_of_regs = 15;
>> + }
>> +
>> else
>> + {
>> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
>> + no_of_regs = 14;
>> + }
>> + /* Get Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> +
>> + /* Extra space for
>> Base Register and CPSR; wihtout optmization. */
>> + record_buf[register_count] = reg_src1;
>> + record_buf[register_count + 1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = register_count + 2;
>> +
>> + for (register_count = 0; register_count < no_of_regs; register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + /* Register_count gives total no of registers and dually working
>> + as reg number. */
>> + record_buf[index] = register_count;
>> + index++;
>> + }
>> + }
>> +
>> + }
>> + else
>> + {
>> + /* It handles both STM(1) and STM(2). */
>> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
>> + /*
>> Get Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> +
>> + switch (addr_mode)
>> + {
>> + /* Decrement after. */
>> + case 0:
>> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
>> + arm_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address +
>> 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Increment after. */
>> + case 1:
>> + start_address = u_buf[0].unsigned_regval;
>> + arm_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Decrement before. */
>> + case 2:
>> +
>> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
>> + arm_insn_r->mem_rec_count =
>> register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Increment before. */
>> + case
>> 3:
>> + start_address = u_buf[0].unsigned_regval + 4;
>> + arm_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address + 4;
>> +
>> register_count--;
>> + }
>> + break;
>> +
>> + default:
>> + return -1;
>> + break;
>> + }
>> +
>> + /* Base register also changes; based on condition and W bit. */
>> + /* We save it anyway without optimization. */
>> + record_buf[0] = reg_src1;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode
>> 101 insns. */
>> +
>> +static int
>> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
>> +{
>> +
>> + uint32_t record_buf[8];
>> +
>> + /* Handle B, BL, BLX(1) insns. */
>> + /* Wihtout optmization we save link register,
>> + CSPR for the insn which changes T bit. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns. */
>> +
>> +static int
>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>> +{
>> + 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;
>> +}
>> +
>> +/* Handling opcode 111 insns. */
>> +
>> +static int
>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>> +{
>> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t shift_imm = 0;
>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>> 0;
>> + uint32_t start_address = 0;
>> +
>> + /* Handle SWI insn; system call would be handled over here. */
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
>> + if (15 == arm_insn_r->opcode)
>> + {
>> + /* Handle arm syscall insn. */
>> + if (tdep->arm_swi_record != NULL)
>> + {
>> + tdep->arm_swi_record(reg_cache);
>> + }
>> + else
>> + {
>> + printf_unfiltered (_("no syscall record
>> support\n"));
>> + return -1;
>> + }
>> + }
>> +
>> + 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;
>> +}
>> +
>> +/* Handling opcode 000 insns. */
>> +
>> +static int
>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_src1 = 0;
>> +
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>> +
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_src1 = 0;
>> +
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> +
>> + record_buf[0] =
>> ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_src1 = 0, reg_src2 = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
>> +
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + gdb_byte buf[4];
>> + } u_buf[2];
>> +
>> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
>> +
>> + if (bit (thumb_insn_r->arm_insn,
>> 12))
>> + {
>> + /* Handle load/store register offset. */
>> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
>> + if ((opcode2 >= 12) && (opcode2 <= 15))
>> + {
>> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((opcode2 >= 8)
>> && (opcode2 <= 10))
>> + {
>> + /* STR(2), STRB(2), STRH(2) . */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>> + reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> + , &u_buf[1].unsigned_regval);
>> + if (8 == opcode2)
>> + record_buf_mem[0] = 4; /* STR (2). */
>> + else if (10 == opcode2)
>> + record_buf_mem[0] = 1; /* STRB (2). */
>> + else if (9 == opcode2)
>> + record_buf_mem[0] =
>> 2; /* STRH (2). */
>> + record_buf_mem[1] = u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> + }
>> + else if (bit (thumb_insn_r->arm_insn, 11))
>> + {
>> + /* Handle load from literal pool. */
>> + /* LDR(3). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (opcode1)
>> + {
>> + opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
>> + opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
>> + if ((3 == opcode2) && (!opcode3))
>> + {
>> + /* Branch with exchange. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + 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;
>> + thumb_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + /* Format 5; data processing insns. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>> + if (bit (thumb_insn_r->arm_insn, 7))
>> + {
>> + reg_src1
>> = reg_src1 + 8;
>> + }
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (opcode)
>> + {
>> + /* LDR(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* STR(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + , &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 4;
>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>> + uint32_t
>> record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (3 == opcode)
>> + {
>> + /* LDR(4). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (1 == opcode)
>> + {
>> + /* LDRH(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (2 == opcode)
>> + {
>> + /* STR(3). */
>> + immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
>> + regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
>> + , &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 4;
>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> + else if (0 ==
>> opcode)
>> + {
>> + /* STRH(1). */
>> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + , &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC
>> (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 101 insns. */
>> +
>> +static int
>> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
>> + uint32_t register_bits = 0, register_count = 0;
>> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> + opcode2 =
>> bits (thumb_insn_r->arm_insn, 9, 12);
>> +
>> + if (14 == opcode2)
>> + {
>> + /* POP. */
>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> + record_buf[register_count] = ARM_PS_REGNUM;
>> + record_buf[register_count + 1] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = register_count +
>> 2;
>> + for (register_count = 0; register_count < 8; register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + record_buf[index] = register_count;
>> + index++;
>> + }
>> + }
>> + }
>> + else if (10 == opcode2)
>> + {
>> + /* PUSH. */
>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>> + regcache_raw_read_unsigned (reg_cache,
>> ARM_PC_REGNUM
>> + , &u_buf.unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> + start_address = u_buf.unsigned_regval - \
>> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count))
>> ;
>> + thumb_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + record_buf[0] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (0x1E == opcode1)
>> + {
>> + /* BKPT insn.
>> */
>> + /* Handle enhanced software breakpoint insn, BKPT. */
>> + /* CPSR is changed to be executed in ARM state, disabling normal
>> + interrupts, entering abort mode. */
>> + /* Accorindly to high vector configuration PC is set accordingly. */
>> + /* FIX ME ? what if user hit breakpoint and type reverse, in
>> + that case, we need to go back with previous CPSR and
>> + Program Counter.. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] =
>> ARM_LR_REGNUM;
>> + thumb_insn_r->reg_rec_count = 2;
>> + /* Save SPSR also; how?. */
>> + printf_unfiltered (_("Process record does not support instruction "
>> + "0x%0x at address %s.\n"),
>> + thumb_insn_r->arm_insn,
>> + paddress (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
>> + return -1;
>> + }
>> + else if ((0 == opcode) || (1 == opcode))
>> +
>> {
>> + /* ADD(5), ADD(6). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (2 == opcode)
>> + {
>> + /* ADD(7), SUB(4). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> + record_buf[0] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 110
>> insns. */
>> +
>> +static int
>> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
>> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (1 == opcode2)
>> +
>> {
>> +
>> + /* LDMIA. */
>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>> + /* Get Rn. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> + record_buf[register_count] = reg_src1;
>> + thumb_insn_r->reg_rec_count = register_count + 1;
>> + for
>> (register_count = 0; register_count < 8; register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + record_buf[index] = register_count;
>> + index++;
>> + }
>> + }
>> + }
>> + else if (0 == opcode2)
>> + {
>> + /* It handles both STMIA. */
>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>> + /* Get Rn. */
>> + reg_src1 = bits
>> (thumb_insn_r->arm_insn, 8, 10);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> + start_address = u_buf.unsigned_regval;
>> + thumb_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> + record_buf_mem[(register_count * 2) - 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + }
>> + else if (0x1F == opcode1)
>> + {
>> + /* Handle arm syscall insn. */
>> + if (tdep->arm_swi_record != NULL)
>> + {
>> + tdep->arm_swi_record(reg_cache);
>> + }
>> + else
>> +
>> {
>> + printf_unfiltered (_("no syscall record support\n"));
>> + return -1;
>> + }
>> + }
>> +
>> + /* B(1), conditional branch is automatically taken care in process_record,
>> + as PC is saved there. */
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 111 insns. */
>> +
>> +static int
>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> +
>> uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> + /* BL , BLX(1). */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + /* B(2) is automatically taken care in process_record, as PC is saved
>> + there. */
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +
>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
>> +
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>> +{
>> +
>> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
>> + static int (*const arm_handle_insn[8])
>> + (insn_decode_record*) =
>> + {
>> + arm_handle_data_proc_misc_ld_str_insn, /* 000. */
>> + arm_handle_data_proc_imm_insn, /* 001. */
>> + arm_handle_ld_st_imm_offset_insn, /* 010. */
>> + arm_handle_ld_st_reg_offset_insn, /* 011. */
>> + arm_handle_ld_st_multiple_insn, /* 100.
>> */
>> + arm_handle_brn_insn, /* 101. */
>> + arm_handle_coproc_insn, /* 110. */
>> + arm_handle_coproc_data_proc_insn /* 111. */
>> + };
>> +
>> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
>> + static int (*const thumb_handle_insn[8])
>> +
>> (insn_decode_record*) =
>> + { \
>> + thumb_handle_shift_add_sub_insn, /* 000. */
>> + thumb_handle_add_sub_cmp_mov_insn, /* 001. */
>> + thumb_handle_ld_st_reg_offset_insn, /* 010. */
>> + thumb_handle_ld_st_imm_offset_insn, /* 011. */
>> + thumb_handle_ld_st_stack_insn, /* 100. */
>> + thumb_handle_misc_insn, /* 101. */
>> +
>> thumb_handle_swi_insn, /* 110. */
>> + thumb_handle_branch_insn /* 111. */
>> + };
>> +
>> + struct
>> + {
>> + gdb_byte buf[insn_size];
>> + } u_buf;
>> +
>> + uint32_t ret=0, insn_id = 0;
>> +
>> + memset (&u_buf, 0, sizeof(u_buf));
>> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
>> + {
>> + if (record_debug)
>> + {
>> + printf_unfiltered
>> (_("Process record: error reading memory at "
>> + "addr %s len = %d.\n"),
>> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
>> + return -1;
>> + }
>> + }
>> + else if (ARM_INSN_SIZE_BYTES == insn_size)
>> + {
>> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>> + arm_record->cond = bits (arm_record->arm_insn, 28,
>> 31);
>> + insn_id = bits (arm_record->arm_insn, 25, 27);
>> + ret = (0x0F != arm_record->cond)
>> + ? arm_handle_insn[insn_id] (arm_record)
>> + : handle_extension_space (arm_record);
>> + }
>> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> + {
>> + /* As thumb does not have condition codes, following field is useless. */
>> + arm_record->cond = -1;
>> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>> (arm_record->gdbarch));
>> +
>> + insn_id = bits (arm_record->arm_insn, 13, 15);
>> + ret = thumb_handle_insn[insn_id] (arm_record);
>> + }
>> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>> + {
>> + /* Yet to be implemented; handle thumb2 part here. */
>> + printf_unfiltered (_("Process record does not support instruction 0x%0x "
>> + "at address %s.\n"),
>> +
>> arm_record->arm_insn,
>> + paddress (arm_record->gdbarch, arm_record->this_addr));
>> + ret = -1;
>> + }
>> + else
>> + {
>> + /* Throw assertion. */
>> + gdb_assert (0);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +/* Parse the current instruction and record the values of the registers and
>> + memory that will be changed in current instruction to "record_arch_list".
>> + Return -1 if something is wrong.. */
>> +
>> +int
>> +arm_process_record (struct gdbarch *gdbarch, struct regcache
>> *regcache,
>> + CORE_ADDR insn_addr)
>> +{
>> +
>> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>> + uint32_t no_of_rec = 0;
>> + uint32_t ret = 0;
>> + ULONGEST t_bit = 0;
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + insn_decode_record arm_record;
>> + memset (&u_buf, 0, sizeof(u_buf));
>> +
>> + memset (&arm_record, 0, sizeof (insn_decode_record));
>> + arm_record.regcache = regcache;
>> + arm_record.this_addr = insn_addr;
>> + arm_record.gdbarch = gdbarch;
>> +
>> +
>> + if (record_debug > 1)
>> + {
>> + fprintf_unfiltered (gdb_stdlog,
>> "Process record: arm_process_record "
>> + "addr = %s\n",
>> + paddress (gdbarch, arm_record.this_addr));
>> + }
>> +
>> + /* Check the insn, whether it is thumb or arm one. */
>> +
>> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
>> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
>> + , &u_buf.unsigned_regval);
>> +
>> + if (!(u_buf.unsigned_regval & t_bit))
>> + {
>> + /* We are decoding arm
>> insn. */
>> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>> + }
>> + else
>> + {
>> + /* We are decoding thumb insn. */
>> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>> + }
>> +
>> + if (0 == ret)
>> + {
>> + /* Record registers. */
>> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>> + if (arm_record.arm_regs)
>> + {
>> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>> +
>> {
>> + if (record_arch_list_add_reg (arm_record.regcache \
>> + , (arm_record.arm_regs[no_of_rec])))
>> + ret = -1;
>> + }
>> + }
>> + /* Record memories. */
>> + if (arm_record.arm_mems)
>> + {
>> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
>> no_of_rec++)
>> + {
>> + if (record_arch_list_add_mem \
>> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
>> + arm_record.arm_mems[no_of_rec].len))
>> + ret = -1;
>> + }
>> + }
>> +
>> + if (record_arch_list_add_end ())
>> + ret = -1;
>> + }
>> +
>> + if (arm_record.arm_regs)
>> + xfree (arm_record.arm_regs);
>> + if
>> (arm_record.arm_mems)
>> + xfree (arm_record.arm_mems);
>> +
>> + return ret;
>> +}
>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
>> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
>> @@ -201,6 +201,9 @@
>> /* Return the expected next PC if FRAME is stopped at a syscall
>> instruction. */
>> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>> +
>> + /* Parse swi insn args, sycall record. */
>> + int (*arm_swi_record) (struct regcache *regcache);
>> };
>>
>> /* Structures used for displaced stepping. */
>> @@ -331,6 +334,8 @@
>> instruction? */
>> extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>
>> +extern int arm_process_record (struct
>> gdbarch *gdbarch,
>> + struct regcache *regcache, CORE_ADDR addr);
>> /* Functions exported from armbsd-tdep.h. */
>>
>> /* Return the appropriate register set for the core section identified
>>
>>
>>
>>
>> ________________________________
>> From: Tom Tromey <tromey@redhat.com>
>> To: paawan oza <paawan1982@yahoo.com>
>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>> Sent: Wednesday, 13 July 2011 1:29 AM
>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>
>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>
>> Oza> any more comments are welcome make this patch ok, if ARM person can
>> Oza> have a look at it it would be great.
>>
>> You have submitted this patch many times now and nobody has commented
>> on the details of the ARM decoding. I think we should proceed on the
>> theory that this is simply not going to happen.
>>
>> Also, I am not as concerned about the correctness of every detail as I
>> am about the general maintainability and style of the code. I expect
>> there will be bugs; those can be fixed.
>>
>> You need a ChangeLog entry. A patch of this magnitude
>> should also have
>> a NEWS entry.
>>
>> Some kind of testing would be good. Do the existing tests in
>> gdb.reverse work with your port? If so then I think that is sufficient
>>
>> Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
>>
>> Just write unsigned int reg_len = LENGTH;
>>
>> Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>
>> Mind the spaces and parens. Better, use XNEWVEC:
>>
>> REGS = XNEWVEC (uint32_t, reg_len);
>>
>> Oza> + while (reg_len) \
>> Oza> + { \
>> Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
>> Oza> + reg_len--; \
>> Oza> + } \
>>
>> Just use memcpy.
>>
>> Oza> +#define
>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>
>> The same comments apply for this macro.
>>
>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>> Oza> (before entry to
>>
>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>> Oza> (on return from
>>
>> Your email got corrupted. Usually this is some bad MUA setting.
>>
>> Oza> + uint32_t mem_rec_count; /* No of mem recors */
>>
>> Typo, "recors"
>>
>> Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
>>
>> Typo, should be "mandatory".
>>
>> Oza> + if(!sbo)
>>
>> Spacing.
>>
>> Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>
>> Over-parenthesizing makes the code harder to read. Please fix this. I
>> noticed it in many places. This specific case should read:
>>
>> if (3 == opcode1 && bit
>> (arm_insn_r->arm_insn, 4))
>>
>> Oza> + memset(&u_buf, 0, sizeof (u_buf));
>>
>> Spacing. Just go through the entire patch and fix all the spacing
>> issues.
>>
>> I feel like I have mentioned this before.
>>
>> Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> Oza> + , &u_buf[0].unsigned_regval);
>>
>> What if this does not return REG_VALID?
>> There are multiple instances of this.
>>
>> Oza> + gdb_assert_not_reached ("no decoding pattern found");
>>
>> It seems wrong to use an assert in this code. At least, it is not
>> obvious to me that this represents a logic error in gdb as opposed to a
>> merely unrecognized instruction. An unrecognized instruction can occur
>> for many reasons, e.g., a bad jump.
>>
>> Oza> +
>> if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>> Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>> Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>> Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>> Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>> Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>> Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>> Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>
>> This reads very oddly. Is there a particular reason behind the ordering
>> (if so -- document). If not, isn't
>> this:
>>
>> if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>
>> There are other odd-looking conditions like this.
>>
>> Oza> + default:
>> Oza> + gdb_assert_not_reached ("Invalid addressing mode for insn");
>>
>> Again, assert seems wrong.
>>
>> I'm afraid I ran out of steam here. Please fix all the issues already
>> noted and look at the rest of the patch with a critical eye to see what
>> else should be cleaned up. I want this patch to go in, but first it
>> must comply to the usual gdb standards.
>>
>> Tom
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-09-27 6:52 ` oza Pawandeep
@ 2011-10-06 18:01 ` oza Pawandeep
[not found] ` <CAK1A=4xuUT++WRzdUnZc0KodYF0AiukUyJa7Pr=wzb4i-OQ5eQ@mail.gmail.com>
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-06 18:01 UTC (permalink / raw)
To: Tom Tromey, gdb-patches, Petr Hluzín
Hi Tom,
Gentle reminder to look into patch.
any arm related comment would be highly appreciated.
Regards,
Oza.
On Tue, Sep 27, 2011 at 9:21 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom,
>
> What do you think about the patch to be ready to to move in <phase_2> ?
> Any more comments are welcome from ARM specific community here.
> most of the review comments from Michael, Petr, Tom and other folks
> have been implemented.
>
> Regards,
> Oza.
>
> On Thu, Sep 22, 2011 at 7:38 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hello Chandra,
>>
>> Let me know if you are planning to do anymore basic testing on this patch.
>>
>> @Tom: is it possible to get this patch move in, of course I have been
>> keen on any review comment; but it has been lying around for a long
>> time.
>> and I would like to move to phase-3 implementation then.
>>
>> Regards,
>> Oza.
>>
>> On Mon, Sep 19, 2011 at 9:17 AM, paawan oza <paawan1982@yahoo.com> wrote:
>>>
>>>
>>> Hi all,
>>>
>>> Sorry for delay in fixing review comments.
>>>
>>> Thanks Chandra for doing testing and working on porintg x86 tcl test cases to arm reversible.
>>> please find the latest version of the patch after fixing couple of bugs and review comment fix from Tom.
>>>
>>> PATCH STARTS
>>> ----------------------------------
>>> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
>>> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
>>> @@ -1025,6 +1025,9 @@
>>> set_gdbarch_fetch_tls_load_module_address
>>> (gdbarch,
>>> svr4_fetch_objfile_link_map);
>>>
>>> + /* Enable process record. */
>>> + set_gdbarch_process_record (gdbarch, arm_process_record);
>>> +
>>> tramp_frame_prepend_unwinder (gdbarch,
>>> &arm_linux_sigreturn_tramp_frame);
>>> tramp_frame_prepend_unwinder (gdbarch,
>>> @@ -1054,6 +1057,8 @@
>>>
>>>
>>> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>>> +
>>> + tdep->arm_swi_record = NULL;
>>> }
>>>
>>> /* Provide a prototype to silence -Wmissing-prototypes. */
>>> diff -urN
>>> arm_orig/arm-tdep.c arm_new/arm-tdep.c
>>> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
>>> @@ -55,6 +55,8 @@
>>> #include "gdb_assert.h"
>>> #include "vec.h"
>>>
>>> +#include "record.h"
>>> +
>>> #include "features/arm-with-m.c"
>>>
>>> static int arm_debug;
>>> @@ -8821,3 +8823,1769 @@
>>> NULL, /* FIXME: i18n: "ARM debugging is %s. */
>>> &setdebuglist, &showdebuglist);
>>> }
>>> +/* ARM-reversible process record data structures. */
>>> +
>>> +#define ARM_INSN_SIZE_BYTES 4
>>> +#define THUMB_INSN_SIZE_BYTES 2
>>> +#define THUMB2_INSN_SIZE_BYTES 4
>>> +
>>> +#define INSN_S_L_BIT_NUM 20
>>> +
>>> +#define
>>> REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
>>> +do \
>>> + { \
>>> + unsigned int reg_len = LENGTH; \
>>> + if (reg_len) \
>>> + { \
>>> + REGS = XNEWVEC (uint32_t, reg_len); \
>>> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>>> + } \
>>> + } \
>>> +while (0)
>>> +
>>> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>> +do \
>>> + { \
>>> + unsigned int mem_len = LENGTH; \
>>> + if (mem_len) \
>>> + { \
>>> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
>>> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>>> + } \
>>> + }
>>> \
>>> +while (0)
>>> +
>>> +
>>> +/* ARM memory record structure. */
>>> +struct arm_mem_r
>>> +{
>>> + uint32_t len; /* Record length. */
>>> + CORE_ADDR addr; /* Memory address. */
>>> +};
>>> +
>>> +/* ARM instruction record contains opcode of current insn and execution state (before entry to
>>> +decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
>>> +decode_insn() ). */
>>> +typedef struct insn_decode_record_t
>>> +{
>>> + struct gdbarch *gdbarch;
>>> + struct regcache *regcache;
>>> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
>>> + uint32_t arm_insn; /* Should accommodate thumb. */
>>> + uint32_t
>>> cond; /* Condition code. */
>>> + uint32_t opcode; /* Insn opcode. */
>>> + uint32_t decode; /* Insn decode bits. */
>>> + uint32_t mem_rec_count; /* No of mem records */
>>> + uint32_t reg_rec_count; /* No of reg records */
>>> + uint32_t *arm_regs; /* Registers to be saved for this record. */
>>> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
>>> +} insn_decode_record;
>>> +
>>> +
>>> +/* Checks ARM SBZ and SBO mandatory fields. */
>>> +
>>> +static int
>>> +sbo_sbz (uint32_t insn,
>>> uint32_t bit_num, uint32_t len, uint32_t sbo)
>>> +{
>>> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
>>> +
>>> + if (!len)
>>> + return 1;
>>> +
>>> + if (!sbo)
>>> + ones = ~ones;
>>> +
>>> + while (ones)
>>> + {
>>> + if (!(ones & sbo))
>>> + {
>>> + return 0;
>>> + }
>>> + ones = ones >> 1;
>>> + }
>>> + return 1;
>>> +}
>>> +
>>> +/* Handling ARM extension space insns. */
>>> +
>>> +static int
>>> +handle_extension_space (insn_decode_record *arm_insn_r)
>>> +{
>>> + uint32_t ret = 0;
>>> + uint32_t opcode1 = 0, opcode2 = 0;
>>> +
>>> + opcode1 = bits
>>> (arm_insn_r->arm_insn, 25, 27);
>>> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
>>> + {
>>> + ret = -1;
>>> + /* Undefined instruction on ARM V5; need to handle if later versions
>>> + define it. */
>>> + }
>>> +
>>> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> + if (!opcode1 && (9 == opcode2))
>>> + {
>>> + ret = -1;
>>> + /* Handle arithmetic insn extension space. */
>>> + }
>>> +
>>> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>>> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>>> +
>>> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
>>> +
>>> {
>>> + ret = -1;
>>> + /* Handle control insn extension space. */
>>> + }
>>> +
>>> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>>> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
>>> + && bit (arm_insn_r->arm_insn, 4))
>>> + {
>>> + ret = -1;
>>> + /* Handle load/store insn extension space. */
>>> + }
>>> +
>>> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>>> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
>>> + {
>>> + ret = -1;
>>> + /* Handle coprocessor insn extension space. */
>>> + }
>>> +
>>> + /* To
>>> be done for ARMv5 and later; as of now we return -1. */
>>> + if (-1 == ret)
>>> + 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 ret;
>>> +}
>>> +
>>> +/* Handling opcode 000 insns. */
>>> +
>>> +static int
>>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + struct regcache *reg_cache = arm_insn_r->regcache;
>>> + uint32_t
>>> record_buf[8], record_buf_mem[8];
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf[2];
>>> +
>>> +
>>> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>>> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
>>> + uint32_t opcode1 = 0;
>>> +
>>> + memset (&u_buf, 0, sizeof (u_buf));
>>> +
>>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>>> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
>>> +
>>> + /* Data processing insn /multiply insn. */
>>> + if ((9 == arm_insn_r->decode)
>>> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
>>> + || ((0 == arm_insn_r->opcode) || (1 ==
>>> arm_insn_r->opcode))))
>>> + {
>>> + /* Handle multiply instructions. */
>>> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
>>> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
>>> + {
>>> + /* Handle MLA and MUL. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> +
>>> }
>>> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
>>> + {
>>> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + record_buf[2] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 3;
>>> + }
>>> + }
>>> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
>>> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
>>> + {
>>> + /* Handle misc load insns, as 20th bit (L = 1). */
>>> + /* LDR insn has a capability to do branching, if
>>> + MOV LR, PC is preccedded by LDR insn having Rn as R15
>>> + in that case, it emulates branch and link insn, and hence we
>>> + need to save CSPR and PC as well. I am not sure this is right
>>> + place as opcode = 010 LDR insn make this happen, if R15 was
>>> + used. */
>>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>>> + if (15 != reg_dest)
>>> + {
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> +
>>> {
>>> + record_buf[0] = reg_dest;
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
>>> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
>>> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
>>> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
>>> + {
>>> + /* Handle MSR insn. */
>>> + if (9 == arm_insn_r->opcode)
>>> +
>>> {
>>> + /* CSPR is going to be changed. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + /* 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;
>>> + }
>>> + }
>>> + else if ((9 == arm_insn_r->decode)
>>> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>>> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>>> + {
>>> + /*
>>> Handling SWP, SWPB. */
>>> + /* These insns, changes register and memory as well. */
>>> + /* SWP or SWPB insn. */
>>> + /* Get memory address given by Rn. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + /* SWP insn ?, swaps word. */
>>> + if (8 == arm_insn_r->opcode)
>>> + {
>>> + record_buf_mem[0] =
>>> 4;
>>> + }
>>> + else
>>> + {
>>> + /* SWPB insn, swaps only byte. */
>>> + record_buf_mem[0] = 1;
>>> + }
>>> + record_buf_mem[1] = u_buf[0].unsigned_regval;
>>> + arm_insn_r->mem_rec_count = 1;
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
>>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12,
>>> 1))
>>> + {
>>> + /* Handle BLX, branch and link/exchange. */
>>> + if (9 == arm_insn_r->opcode)
>>> + {
>>> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
>>> + and R14 stores the return address. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = ARM_LR_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
>>> + {
>>> + /* Handle enhanced software
>>> breakpoint insn, BKPT */
>>> + /* CPSR is changed to be executed in ARM state, disabling normal
>>> + interrupts, entering abort mode. */
>>> + /* Accorindly to high vector configuration PC is set accordingly */
>>> + /* What if user hit breakpoint and type reverse, in
>>> + that case, we need to go back with previous CPSR and
>>> + Program Counter. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = ARM_LR_REGNUM;
>>> + 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)
>>> + && !bit
>>> (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>>> + {
>>> + /* Handle enhanced store insns and DSP insns (e.g. LDRD)
>>> + let us begin according to addressing modes for store insns
>>> + STRH insn, addresing modes are taken following. */
>>> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>>> + {
>>> + /* 1) Handle misc store, immediate offset. */
>>> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
>>> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> +
>>> regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + if (15 == reg_src1)
>>> + {
>>> + /* If R15 was used as Rn, hence current PC+8. */
>>> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> + }
>>> + offset_8 = (immed_high << 4) |
>>> immed_low;
>>> + /* Calculate target store address. */
>>> + if (14 == arm_insn_r->opcode)
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> + }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> + }
>>> + record_buf_mem[0] = 2;
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count =
>>> 1;
>>> + }
>>> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>>> + {
>>> + /* 2) Store, register offset. */
>>> + /* Get Rm. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>>> + /* Get Rn. */
>>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + ,
>>> &u_buf[0].unsigned_regval);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + if (15 == reg_src2)
>>> + {
>>> + /* If R15 was used as Rn, hence current PC+8. */
>>> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
>>> +
>>> }
>>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>>> + if (12 == arm_insn_r->opcode)
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> + }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> + }
>>> +
>>> record_buf_mem[0] = 2;
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count = 1;
>>> + }
>>> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>>> + {
>>> + /* 3) Store, immediate pre-indexed. */
>>> + /* 5) Store, immediate post-indexed. */
>>> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
>>> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
>>> + offset_8 =
>>> (immed_high << 4) | immed_low;
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>>> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
>>> +
>>> }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
>>> + }
>>> + record_buf_mem[0] = 2;
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count = 1;
>>> + /* Record Rn also as it changes. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if ((9 ==
>>> arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
>>> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>>> + {
>>> + /* 4) Store, register pre-indexed. */
>>> + /* 6) Store, register post -indexed. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + ,
>>> &u_buf[0].unsigned_regval);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>>> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
>>> + }
>>> +
>>> else
>>> + {
>>> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
>>> + }
>>> + record_buf_mem[0] = 2;
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count = 1;
>>> + /* Record Rn also as it changes. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
>>> + arm_insn_r->reg_rec_count = 1;
>>> +
>>> }
>>> + /* DSP insns (e.g. LDRD) TBD. */
>>> + }
>>> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
>>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
>>> + {
>>> + /* Handle BX, branch and link/exchange. */
>>> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
>>> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
>>> + && sbo_sbz
>>> (arm_insn_r->arm_insn, 17, 4, 1))
>>> + {
>>> + /* Count leading zeros: CLZ. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
>>> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>>> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
>>> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
>>> + )
>>> + {
>>> + /* Handle MRS insn. */
>>> +
>>> record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (arm_insn_r->opcode <= 15)
>>> + {
>>> + /* Normal data processing insns. */
>>> + /* Out of 11 shifter operands mode, all the insn modifies destination
>>> + register, which is specified by 13-16 decode. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + else
>>> +
>>> {
>>> + return -1;
>>> + }
>>> +
>>> + 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);
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 001 insns. */
>>> +
>>> +static int
>>> +arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> + if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
>>> + && (2 == bits (arm_insn_r->arm_insn, 20, 21))
>>> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
>>> +
>>> )
>>> + {
>>> + /* Handle MSR insn. */
>>> + if (9 == arm_insn_r->opcode)
>>> + {
>>> + /*CSPR is going to be changed. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + /* SPSR is going to be changed. */
>>> + }
>>> + }
>>> + else if (arm_insn_r->opcode <= 15)
>>> + {
>>> + /* Normal data
>>> processing insns. */
>>> + /* Out of 11 shifter operands mode, all the insn modifies destination
>>> + register, which is specified by 13-16 decode. */
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + else
>>> + {
>>> + return -1;
>>> + }
>>> +
>>> + 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);
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 010 insns.
>>> */
>>> +
>>> +static int
>>> +arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> + uint32_t reg_src1 = 0 , reg_dest = 0;
>>> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
>>> + uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + memset (&u_buf, 0, sizeof (u_buf));
>>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>>> + {
>>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>>> + /* LDR insn has a capability to do branching,
>>> if
>>> + MOV LR, PC is precedded by LDR insn having Rn as R15
>>> + in that case, it emulates branch and link insn, and hence we
>>> + need to save CSPR and PC as well. */
>>> + if (15 != reg_dest)
>>> + {
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + record_buf[0] =
>>> reg_dest;
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + /* Store, immediate offset, immediate pre-indexed,
>>> + immediate post-indexed. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
>>> + regcache_raw_read_unsigned (reg_cache,
>>> reg_src1
>>> + , &u_buf.unsigned_regval);
>>> + /* U == 1 */
>>> + if (bit (arm_insn_r->arm_insn, 23))
>>> + {
>>> + tgt_mem_addr = u_buf.unsigned_regval + offset_12;
>>> + }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf.unsigned_regval - offset_12;
>>> + }
>>> +
>>> + switch (arm_insn_r->opcode)
>>> +
>>> {
>>> + /* STR */
>>> + case 8:
>>> + case 12:
>>> + /* STR */
>>> + case 9:
>>> + case 13:
>>> + /* STRT */
>>> + case 1:
>>> + case 5:
>>> + /* STR */
>>> + case 4:
>>> + case 0:
>>> +
>>> + /* STR insn, STRT insn. */
>>> + record_buf_mem[0] = 4;
>>> + break;
>>> +
>>> + /* STRB */
>>> + case 10:
>>> + case 14:
>>> + /* STRB */
>>> + case 11:
>>> + case 15:
>>> + /* STRBT */
>>> + case 3:
>>> + case
>>> 7:
>>> + /* STRB */
>>> + case 2:
>>> + case 6:
>>> + /* STRB insn, STRBT insn. */
>>> + record_buf_mem[0] = 1;
>>> + break;
>>> +
>>> + default:
>>> + return -1;
>>> + break;
>>> + }
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> +
>>> arm_insn_r->mem_rec_count = 1;
>>> +
>>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>> + {
>>> + /* We are handling pre-indexed mode; post-indexed
>>> mode;
>>> + where Rn is going to be changed. */
>>> + record_buf[0] = reg_src1;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> +
>>> + 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);
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 011 insns. */
>>> +
>>> +static int
>>> +arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> + uint32_t shift_imm = 0;
>>> + uint32_t
>>> reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>>> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
>>> + uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> + struct
>>> + {
>>> + LONGEST signed_word;
>>> + ULONGEST unsigned_regval;
>>> + } u_buf[2];
>>> +
>>> + memset (&u_buf, 0, sizeof (u_buf));
>>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
>>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
>>> +
>>> + /* Handle enhanced store insns and LDRD DSP insn,
>>> + let us begin according to addressing modes for store insns
>>> + STRH insn. */
>>> +
>>> + /* LDR or STR? */
>>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>>> +
>>> {
>>> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
>>> + /* LDR insn has a capability to do branching, if
>>> + MOV LR, PC is precedded by LDR insn having Rn as R15
>>> + in that case, it emulates branch and link insn, and hence we
>>> + need to save CSPR and PC as well. */
>>> + if (15 != reg_dest)
>>> + {
>>> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
>>> + arm_insn_r->reg_rec_count = 1;
>>> +
>>> }
>>> + else
>>> + {
>>> + record_buf[0] = reg_dest;
>>> + record_buf[1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + if (! bits (arm_insn_r->arm_insn, 4, 11))
>>> + {
>>> + /* Store insn, register offset and register pre-indexed,
>>> + register post-indexed. */
>>> + /* Get
>>> Rm. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>>> + /* Get Rn. */
>>> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + if (15 == reg_src2)
>>> + {
>>> + /* If R15 was used as Rn, hence current PC+8. */
>>> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
>>> + u_buf[0].unsigned_regval =
>>> u_buf[0].unsigned_regval + 8;
>>> + }
>>> + /* Calculate target store address, Rn +/- Rm, register offset. */
>>> + /* U == 1. */
>>> + if (bit (arm_insn_r->arm_insn, 23))
>>> + {
>>> + tgt_mem_addr = u_buf[0].unsigned_regval +
>>> + u_buf[1].unsigned_regval;
>>> +
>>> }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf[1].unsigned_regval -
>>> + u_buf[0].unsigned_regval;
>>> + }
>>> +
>>> + switch (arm_insn_r->opcode)
>>> + {
>>> + /* STR */
>>> + case
>>> 8:
>>> + case 12:
>>> + /* STR */
>>> + case 9:
>>> + case 13:
>>> + /* STRT */
>>> + case 1:
>>> + case 5:
>>> + /* STR */
>>> + case 0:
>>> + case
>>> 4:
>>> + /* STR insn, STRT insn. */
>>> + record_buf_mem[0] = 4;
>>> + break;
>>> +
>>> + /* STRB */
>>> + case 10:
>>> + case 14:
>>> + /* STRB */
>>> + case 11:
>>> + case 15:
>>> + /* STRBT */
>>> + case 3:
>>> + case 7:
>>> + /* STRB */
>>> + case 2:
>>> + case 6:
>>> + /* STRB insn, STRBT insn. */
>>> + record_buf_mem[0] = 1;
>>> + break;
>>> +
>>> +
>>> default:
>>> + return -1;
>>> + break;
>>> + }
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count = 1;
>>> +
>>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>> + {
>>> + /* Rn is going to be changed in pre-indexed mode and
>>> + post-indexed mode as well. */
>>> + record_buf[0] = reg_src2;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + /* Store insn, scaled register offset; scaled pre-indexed. */
>>> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
>>> + /* Get Rm. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
>>> + /* Get Rn. */
>>> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
>>> 19);
>>> + /* Get shift_imm. */
>>> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + regcache_raw_read_signed (reg_cache, reg_src1
>>> + ,
>>> &u_buf[0].signed_word);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + /* Offset_12 used as shift. */
>>> + switch (offset_12)
>>> + {
>>> + case 0:
>>> + /* Offset_12 used as index.
>>> */
>>> + offset_12 = u_buf[0].unsigned_regval << shift_imm;
>>> + break;
>>> +
>>> + case 1:
>>> + offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>>> + break;
>>> +
>>> + case 2:
>>> + if
>>> (!shift_imm)
>>> + {
>>> + if (bit (u_buf[0].unsigned_regval, 31))
>>> + {
>>> + offset_12 = 0xFFFFFFFF;
>>> + }
>>> +
>>> else
>>> + {
>>> + offset_12 = 0;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + /* This is arithmetic shift.
>>> */
>>> + offset_12 = u_buf[0].signed_word >> shift_imm;
>>> + }
>>> + break;
>>> +
>>> + case 3:
>>> + if (!shift_imm)
>>> + {
>>> + regcache_raw_read_unsigned (reg_cache,
>>> ARM_PS_REGNUM
>>> + , &u_buf[1].unsigned_regval);
>>> + /* Get C flag value and shift it by 31. */
>>> + offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
>>> + | (u_buf[0].unsigned_regval) >>
>>> 1);
>>> + }
>>> + else
>>> + {
>>> + offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
>>> + | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
>>> +
>>> }
>>> + break;
>>> +
>>> + default:
>>> + return -1;
>>> + break;
>>> + }
>>> +
>>> + regcache_raw_read_unsigned (reg_cache, reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + /* U == 1
>>> */
>>> + if (bit (arm_insn_r->arm_insn, 23))
>>> + {
>>> + tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
>>> + }
>>> + else
>>> + {
>>> + tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
>>> + }
>>> +
>>> + switch
>>> (arm_insn_r->opcode)
>>> + {
>>> + /* STR */
>>> + case 8:
>>> + case 12:
>>> + /* STR */
>>> + case 9:
>>> + case 13:
>>> + /* STRT */
>>> + case 1:
>>> + case
>>> 5:
>>> + /* STR */
>>> + case 0:
>>> + case 4:
>>> + /* STR insn, STRT insn. */
>>> + record_buf_mem[0] = 4;
>>> + break;
>>> +
>>> + /* STRB */
>>> + case 10:
>>> + case 14:
>>> +
>>> /* STRB */
>>> + case 11:
>>> + case 15:
>>> + /* STRBT */
>>> + case 3:
>>> + case 7:
>>> + /* STRB */
>>> + case 2:
>>> + case 6:
>>> + /* STRB insn, STRBT insn.
>>> */
>>> + record_buf_mem[0] = 1;
>>> + break;
>>> +
>>> + default:
>>> + return -1;
>>> + break;
>>> + }
>>> + record_buf_mem[1] = tgt_mem_addr;
>>> + arm_insn_r->mem_rec_count =
>>> 1;
>>> +
>>> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> + || (5 == arm_insn_r->opcode) || (7 ==
>>> arm_insn_r->opcode))
>>> + {
>>> + /* Rn is going to be changed in register scaled pre-indexed
>>> + mode, and scaled post indexed mode. */
>>> + record_buf[0] = reg_src2;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> + }
>>> +
>>> + 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);
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 100 insns. */
>>> +
>>> +static int
>>> +arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
>>> + uint32_t shift_imm = 0;
>>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
>>> + uint32_t start_address = 0, index = 0;
>>> + uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf[2];
>>> +
>>> + memset (&u_buf, 0,
>>> sizeof(u_buf));
>>> +
>>> + /* This mode is exclusively for load and store multiple. */
>>> + /* Handle incremenrt after/before and decrment after.before mode;
>>> + Rn is changing depending on W bit, but as of now we store Rn too without optmization. */
>>> +
>>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>>> + {
>>> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
>>> +
>>> + if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
>>> + {
>>> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
>>> + no_of_regs = 15;
>>> + }
>>> +
>>> else
>>> + {
>>> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
>>> + no_of_regs = 14;
>>> + }
>>> + /* Get Rn. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_list[register_count++] = 1;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> +
>>> + /* Extra space for
>>> Base Register and CPSR; wihtout optmization. */
>>> + record_buf[register_count] = reg_src1;
>>> + record_buf[register_count + 1] = ARM_PS_REGNUM;
>>> + arm_insn_r->reg_rec_count = register_count + 2;
>>> +
>>> + for (register_count = 0; register_count < no_of_regs; register_count++)
>>> + {
>>> + if (register_list[register_count])
>>> + {
>>> + /* Register_count gives total no of registers and dually working
>>> + as reg number. */
>>> + record_buf[index] = register_count;
>>> + index++;
>>> + }
>>> + }
>>> +
>>> + }
>>> + else
>>> + {
>>> + /* It handles both STM(1) and STM(2). */
>>> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
>>> +
>>> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
>>> + /*
>>> Get Rn. */
>>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_count++;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> +
>>> + switch (addr_mode)
>>> + {
>>> + /* Decrement after. */
>>> + case 0:
>>> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
>>> + arm_insn_r->mem_rec_count = register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address +
>>> 4;
>>> + register_count--;
>>> + }
>>> + break;
>>> +
>>> + /* Increment after. */
>>> + case 1:
>>> + start_address = u_buf[0].unsigned_regval;
>>> + arm_insn_r->mem_rec_count = register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] =
>>> start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address + 4;
>>> + register_count--;
>>> + }
>>> + break;
>>> +
>>> + /* Decrement before. */
>>> + case 2:
>>> +
>>> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
>>> + arm_insn_r->mem_rec_count =
>>> register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address + 4;
>>> + register_count--;
>>> + }
>>> + break;
>>> +
>>> + /* Increment before. */
>>> + case
>>> 3:
>>> + start_address = u_buf[0].unsigned_regval + 4;
>>> + arm_insn_r->mem_rec_count = register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address + 4;
>>> +
>>> register_count--;
>>> + }
>>> + break;
>>> +
>>> + default:
>>> + return -1;
>>> + break;
>>> + }
>>> +
>>> + /* Base register also changes; based on condition and W bit. */
>>> + /* We save it anyway without optimization. */
>>> + record_buf[0] = reg_src1;
>>> + arm_insn_r->reg_rec_count = 1;
>>> + }
>>> +
>>> + 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);
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode
>>> 101 insns. */
>>> +
>>> +static int
>>> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> +
>>> + uint32_t record_buf[8];
>>> +
>>> + /* Handle B, BL, BLX(1) insns. */
>>> + /* Wihtout optmization we save link register,
>>> + CSPR for the insn which changes T bit. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = ARM_LR_REGNUM;
>>> + arm_insn_r->reg_rec_count = 2;
>>> +
>>> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 110 insns. */
>>> +
>>> +static int
>>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + 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;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns. */
>>> +
>>> +static int
>>> +arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
>>> +{
>>> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
>>> + struct regcache *reg_cache = arm_insn_r->regcache;
>>> +
>>> + uint32_t shift_imm = 0;
>>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode =
>>> 0;
>>> + uint32_t start_address = 0;
>>> +
>>> + /* Handle SWI insn; system call would be handled over here. */
>>> +
>>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
>>> + if (15 == arm_insn_r->opcode)
>>> + {
>>> + /* Handle arm syscall insn. */
>>> + if (tdep->arm_swi_record != NULL)
>>> + {
>>> + tdep->arm_swi_record(reg_cache);
>>> + }
>>> + else
>>> + {
>>> + printf_unfiltered (_("no syscall record
>>> support\n"));
>>> + return -1;
>>> + }
>>> + }
>>> +
>>> + 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;
>>> +}
>>> +
>>> +/* Handling opcode 000 insns. */
>>> +
>>> +static int
>>> +thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + uint32_t record_buf[8];
>>> + uint32_t reg_src1 = 0;
>>> +
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>>> +
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +
>>> +/* Handling opcode 001 insns. */
>>> +
>>> +static int
>>> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + uint32_t record_buf[8];
>>> + uint32_t reg_src1 = 0;
>>> +
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> +
>>> + record_buf[0] =
>>> ARM_PS_REGNUM;
>>> + record_buf[1] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 010 insns. */
>>> +
>>> +static int
>>> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>>> + uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> + uint32_t reg_src1 = 0, reg_src2 = 0;
>>> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
>>> +
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + gdb_byte buf[4];
>>> + } u_buf[2];
>>> +
>>> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
>>> +
>>> + if (bit (thumb_insn_r->arm_insn,
>>> 12))
>>> + {
>>> + /* Handle load/store register offset. */
>>> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
>>> + if ((opcode2 >= 12) && (opcode2 <= 15))
>>> + {
>>> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if ((opcode2 >= 8)
>>> && (opcode2 <= 10))
>>> + {
>>> + /* STR(2), STRB(2), STRH(2) . */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>>> + reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf[0].unsigned_regval);
>>> + regcache_raw_read_unsigned (reg_cache,
>>> reg_src2
>>> + , &u_buf[1].unsigned_regval);
>>> + if (8 == opcode2)
>>> + record_buf_mem[0] = 4; /* STR (2). */
>>> + else if (10 == opcode2)
>>> + record_buf_mem[0] = 1; /* STRB (2). */
>>> + else if (9 == opcode2)
>>> + record_buf_mem[0] =
>>> 2; /* STRH (2). */
>>> + record_buf_mem[1] = u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>> + thumb_insn_r->mem_rec_count = 1;
>>> + }
>>> + }
>>> + else if (bit (thumb_insn_r->arm_insn, 11))
>>> + {
>>> + /* Handle load from literal pool. */
>>> + /* LDR(3). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (opcode1)
>>> + {
>>> + opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
>>> + opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
>>> + if ((3 == opcode2) && (!opcode3))
>>> + {
>>> + /* Branch with exchange. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + 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;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + /* Format 5; data processing insns. */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>>> + if (bit (thumb_insn_r->arm_insn, 7))
>>> + {
>>> + reg_src1
>>> = reg_src1 + 8;
>>> + }
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> + }
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 001 insns. */
>>> +
>>> +static int
>>> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>>> + uint32_t record_buf[8], record_buf_mem[8];
>>> +
>>> + uint32_t reg_val1 = 0;
>>> + uint32_t reg_src1 = 0;
>>> + uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>>> +
>>> + if (opcode)
>>> + {
>>> + /* LDR(1). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + /* STR(1). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>>> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
>>> + regcache_raw_read_unsigned (reg_cache,
>>> reg_src1
>>> + , &u_buf.unsigned_regval);
>>> + record_buf_mem[0] = 4;
>>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
>>> + thumb_insn_r->mem_rec_count = 1;
>>> + }
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 100 insns. */
>>> +
>>> +static int
>>> +thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>>> + uint32_t
>>> record_buf[8], record_buf_mem[8];
>>> +
>>> + uint32_t reg_val1 = 0;
>>> + uint32_t reg_src1 = 0;
>>> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>>> +
>>> + if (3 == opcode)
>>> + {
>>> + /* LDR(4). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (1 == opcode)
>>> + {
>>> + /* LDRH(1). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>>> 2);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (2 == opcode)
>>> + {
>>> + /* STR(3). */
>>> + immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
>>> + regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
>>> + , &u_buf.unsigned_regval);
>>> + record_buf_mem[0] = 4;
>>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
>>> + thumb_insn_r->mem_rec_count = 1;
>>> + }
>>> + else if (0 ==
>>> opcode)
>>> + {
>>> + /* STRH(1). */
>>> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> + , &u_buf.unsigned_regval);
>>> + record_buf_mem[0] = 2;
>>> + record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
>>> + thumb_insn_r->mem_rec_count = 1;
>>> + }
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> + MEM_ALLOC
>>> (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 101 insns. */
>>> +
>>> +static int
>>> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>>> +
>>> + uint32_t reg_val1 = 0;
>>> + uint32_t reg_src1 = 0;
>>> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
>>> + uint32_t register_bits = 0, register_count = 0;
>>> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
>>> + uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>>> + opcode2 =
>>> bits (thumb_insn_r->arm_insn, 9, 12);
>>> +
>>> + if (14 == opcode2)
>>> + {
>>> + /* POP. */
>>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_list[register_count++] = 1;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> + record_buf[register_count] = ARM_PS_REGNUM;
>>> + record_buf[register_count + 1] = ARM_SP_REGNUM;
>>> + thumb_insn_r->reg_rec_count = register_count +
>>> 2;
>>> + for (register_count = 0; register_count < 8; register_count++)
>>> + {
>>> + if (register_list[register_count])
>>> + {
>>> + record_buf[index] = register_count;
>>> + index++;
>>> + }
>>> + }
>>> + }
>>> + else if (10 == opcode2)
>>> + {
>>> + /* PUSH. */
>>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>>> + regcache_raw_read_unsigned (reg_cache,
>>> ARM_PC_REGNUM
>>> + , &u_buf.unsigned_regval);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_count++;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> + start_address = u_buf.unsigned_regval - \
>>> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count))
>>> ;
>>> + thumb_insn_r->mem_rec_count = register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] = start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address + 4;
>>> + register_count--;
>>> + }
>>> + record_buf[0] = ARM_SP_REGNUM;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (0x1E == opcode1)
>>> + {
>>> + /* BKPT insn.
>>> */
>>> + /* Handle enhanced software breakpoint insn, BKPT. */
>>> + /* CPSR is changed to be executed in ARM state, disabling normal
>>> + interrupts, entering abort mode. */
>>> + /* Accorindly to high vector configuration PC is set accordingly. */
>>> + /* FIX ME ? what if user hit breakpoint and type reverse, in
>>> + that case, we need to go back with previous CPSR and
>>> + Program Counter.. */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] =
>>> ARM_LR_REGNUM;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> + /* Save SPSR also; how?. */
>>> + printf_unfiltered (_("Process record does not support instruction "
>>> + "0x%0x at address %s.\n"),
>>> + thumb_insn_r->arm_insn,
>>> + paddress (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
>>> + return -1;
>>> + }
>>> + else if ((0 == opcode) || (1 == opcode))
>>> +
>>> {
>>> + /* ADD(5), ADD(6). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> + record_buf[0] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (2 == opcode)
>>> + {
>>> + /* ADD(7), SUB(4). */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> + record_buf[0] = ARM_SP_REGNUM;
>>> + thumb_insn_r->reg_rec_count = 1;
>>> + }
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 110
>>> insns. */
>>> +
>>> +static int
>>> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
>>> + struct regcache *reg_cache = thumb_insn_r->regcache;
>>> +
>>> + uint32_t reg_val1 = 0;
>>> + uint32_t reg_src1 = 0;
>>> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
>>> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
>>> + uint32_t record_buf[24], record_buf_mem[48];
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>>> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
>>> +
>>> + if (1 == opcode2)
>>> +
>>> {
>>> +
>>> + /* LDMIA. */
>>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>>> + /* Get Rn. */
>>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_list[register_count++] = 1;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> + record_buf[register_count] = reg_src1;
>>> + thumb_insn_r->reg_rec_count = register_count + 1;
>>> + for
>>> (register_count = 0; register_count < 8; register_count++)
>>> + {
>>> + if (register_list[register_count])
>>> + {
>>> + record_buf[index] = register_count;
>>> + index++;
>>> + }
>>> + }
>>> + }
>>> + else if (0 == opcode2)
>>> + {
>>> + /* It handles both STMIA. */
>>> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
>>> + /* Get Rn. */
>>> + reg_src1 = bits
>>> (thumb_insn_r->arm_insn, 8, 10);
>>> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
>>> + while (register_bits)
>>> + {
>>> + if (register_bits & 0x00000001)
>>> + register_count++;
>>> + register_bits = register_bits >> 1;
>>> + }
>>> + start_address = u_buf.unsigned_regval;
>>> + thumb_insn_r->mem_rec_count = register_count;
>>> + while (register_count)
>>> + {
>>> + record_buf_mem[(register_count * 2) - 1] =
>>> start_address;
>>> + record_buf_mem[(register_count * 2) - 2] = 4;
>>> + start_address = start_address + 4;
>>> + register_count--;
>>> + }
>>> + }
>>> + else if (0x1F == opcode1)
>>> + {
>>> + /* Handle arm syscall insn. */
>>> + if (tdep->arm_swi_record != NULL)
>>> + {
>>> + tdep->arm_swi_record(reg_cache);
>>> + }
>>> + else
>>> +
>>> {
>>> + printf_unfiltered (_("no syscall record support\n"));
>>> + return -1;
>>> + }
>>> + }
>>> +
>>> + /* B(1), conditional branch is automatically taken care in process_record,
>>> + as PC is saved there. */
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +/* Handling opcode 111 insns. */
>>> +
>>> +static int
>>> +thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
>>> +{
>>> + uint32_t record_buf[8];
>>> + uint32_t reg_val1 = 0;
>>> + uint32_t reg_src1 = 0;
>>> +
>>> uint32_t opcode = 0, immed_5 = 0;
>>> +
>>> +
>>> + /* BL , BLX(1). */
>>> + record_buf[0] = ARM_PS_REGNUM;
>>> + record_buf[1] = ARM_LR_REGNUM;
>>> + thumb_insn_r->reg_rec_count = 2;
>>> +
>>> + /* B(2) is automatically taken care in process_record, as PC is saved
>>> + there. */
>>> +
>>> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +
>>> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
>>> +
>>> +static int
>>> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
>>> +{
>>> +
>>> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
>>> + static int (*const arm_handle_insn[8])
>>> + (insn_decode_record*) =
>>> + {
>>> + arm_handle_data_proc_misc_ld_str_insn, /* 000. */
>>> + arm_handle_data_proc_imm_insn, /* 001. */
>>> + arm_handle_ld_st_imm_offset_insn, /* 010. */
>>> + arm_handle_ld_st_reg_offset_insn, /* 011. */
>>> + arm_handle_ld_st_multiple_insn, /* 100.
>>> */
>>> + arm_handle_brn_insn, /* 101. */
>>> + arm_handle_coproc_insn, /* 110. */
>>> + arm_handle_coproc_data_proc_insn /* 111. */
>>> + };
>>> +
>>> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
>>> + static int (*const thumb_handle_insn[8])
>>> +
>>> (insn_decode_record*) =
>>> + { \
>>> + thumb_handle_shift_add_sub_insn, /* 000. */
>>> + thumb_handle_add_sub_cmp_mov_insn, /* 001. */
>>> + thumb_handle_ld_st_reg_offset_insn, /* 010. */
>>> + thumb_handle_ld_st_imm_offset_insn, /* 011. */
>>> + thumb_handle_ld_st_stack_insn, /* 100. */
>>> + thumb_handle_misc_insn, /* 101. */
>>> +
>>> thumb_handle_swi_insn, /* 110. */
>>> + thumb_handle_branch_insn /* 111. */
>>> + };
>>> +
>>> + struct
>>> + {
>>> + gdb_byte buf[insn_size];
>>> + } u_buf;
>>> +
>>> + uint32_t ret=0, insn_id = 0;
>>> +
>>> + memset (&u_buf, 0, sizeof(u_buf));
>>> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
>>> + {
>>> + if (record_debug)
>>> + {
>>> + printf_unfiltered
>>> (_("Process record: error reading memory at "
>>> + "addr %s len = %d.\n"),
>>> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
>>> + return -1;
>>> + }
>>> + }
>>> + else if (ARM_INSN_SIZE_BYTES == insn_size)
>>> + {
>>> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
>>> + arm_record->cond = bits (arm_record->arm_insn, 28,
>>> 31);
>>> + insn_id = bits (arm_record->arm_insn, 25, 27);
>>> + ret = (0x0F != arm_record->cond)
>>> + ? arm_handle_insn[insn_id] (arm_record)
>>> + : handle_extension_space (arm_record);
>>> + }
>>> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
>>> + {
>>> + /* As thumb does not have condition codes, following field is useless. */
>>> + arm_record->cond = -1;
>>> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
>>> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
>>> (arm_record->gdbarch));
>>> +
>>> + insn_id = bits (arm_record->arm_insn, 13, 15);
>>> + ret = thumb_handle_insn[insn_id] (arm_record);
>>> + }
>>> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>>> + {
>>> + /* Yet to be implemented; handle thumb2 part here. */
>>> + printf_unfiltered (_("Process record does not support instruction 0x%0x "
>>> + "at address %s.\n"),
>>> +
>>> arm_record->arm_insn,
>>> + paddress (arm_record->gdbarch, arm_record->this_addr));
>>> + ret = -1;
>>> + }
>>> + else
>>> + {
>>> + /* Throw assertion. */
>>> + gdb_assert (0);
>>> + }
>>> +
>>> + return ret;
>>> +}
>>> +
>>> +/* Parse the current instruction and record the values of the registers and
>>> + memory that will be changed in current instruction to "record_arch_list".
>>> + Return -1 if something is wrong.. */
>>> +
>>> +int
>>> +arm_process_record (struct gdbarch *gdbarch, struct regcache
>>> *regcache,
>>> + CORE_ADDR insn_addr)
>>> +{
>>> +
>>> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
>>> + uint32_t no_of_rec = 0;
>>> + uint32_t ret = 0;
>>> + ULONGEST t_bit = 0;
>>> +
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf;
>>> +
>>> + insn_decode_record arm_record;
>>> + memset (&u_buf, 0, sizeof(u_buf));
>>> +
>>> + memset (&arm_record, 0, sizeof (insn_decode_record));
>>> + arm_record.regcache = regcache;
>>> + arm_record.this_addr = insn_addr;
>>> + arm_record.gdbarch = gdbarch;
>>> +
>>> +
>>> + if (record_debug > 1)
>>> + {
>>> + fprintf_unfiltered (gdb_stdlog,
>>> "Process record: arm_process_record "
>>> + "addr = %s\n",
>>> + paddress (gdbarch, arm_record.this_addr));
>>> + }
>>> +
>>> + /* Check the insn, whether it is thumb or arm one. */
>>> +
>>> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
>>> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
>>> + , &u_buf.unsigned_regval);
>>> +
>>> + if (!(u_buf.unsigned_regval & t_bit))
>>> + {
>>> + /* We are decoding arm
>>> insn. */
>>> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
>>> + }
>>> + else
>>> + {
>>> + /* We are decoding thumb insn. */
>>> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
>>> + }
>>> +
>>> + if (0 == ret)
>>> + {
>>> + /* Record registers. */
>>> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
>>> + if (arm_record.arm_regs)
>>> + {
>>> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
>>> +
>>> {
>>> + if (record_arch_list_add_reg (arm_record.regcache \
>>> + , (arm_record.arm_regs[no_of_rec])))
>>> + ret = -1;
>>> + }
>>> + }
>>> + /* Record memories. */
>>> + if (arm_record.arm_mems)
>>> + {
>>> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
>>> no_of_rec++)
>>> + {
>>> + if (record_arch_list_add_mem \
>>> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
>>> + arm_record.arm_mems[no_of_rec].len))
>>> + ret = -1;
>>> + }
>>> + }
>>> +
>>> + if (record_arch_list_add_end ())
>>> + ret = -1;
>>> + }
>>> +
>>> + if (arm_record.arm_regs)
>>> + xfree (arm_record.arm_regs);
>>> + if
>>> (arm_record.arm_mems)
>>> + xfree (arm_record.arm_mems);
>>> +
>>> + return ret;
>>> +}
>>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>>> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
>>> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
>>> @@ -201,6 +201,9 @@
>>> /* Return the expected next PC if FRAME is stopped at a syscall
>>> instruction. */
>>> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
>>> +
>>> + /* Parse swi insn args, sycall record. */
>>> + int (*arm_swi_record) (struct regcache *regcache);
>>> };
>>>
>>> /* Structures used for displaced stepping. */
>>> @@ -331,6 +334,8 @@
>>> instruction? */
>>> extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>>>
>>> +extern int arm_process_record (struct
>>> gdbarch *gdbarch,
>>> + struct regcache *regcache, CORE_ADDR addr);
>>> /* Functions exported from armbsd-tdep.h. */
>>>
>>> /* Return the appropriate register set for the core section identified
>>>
>>>
>>>
>>>
>>> ________________________________
>>> From: Tom Tromey <tromey@redhat.com>
>>> To: paawan oza <paawan1982@yahoo.com>
>>> Cc: gdb-patches@sourceware.org; Petr Hluzín <petr.hluzin@gmail.com>
>>> Sent: Wednesday, 13 July 2011 1:29 AM
>>> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
>>>
>>>>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
>>>
>>> Oza> any more comments are welcome make this patch ok, if ARM person can
>>> Oza> have a look at it it would be great.
>>>
>>> You have submitted this patch many times now and nobody has commented
>>> on the details of the ARM decoding. I think we should proceed on the
>>> theory that this is simply not going to happen.
>>>
>>> Also, I am not as concerned about the correctness of every detail as I
>>> am about the general maintainability and style of the code. I expect
>>> there will be bugs; those can be fixed.
>>>
>>> You need a ChangeLog entry. A patch of this magnitude
>>> should also have
>>> a NEWS entry.
>>>
>>> Some kind of testing would be good. Do the existing tests in
>>> gdb.reverse work with your port? If so then I think that is sufficient
>>>
>>> Oza> + unsigned int reg_len = 0; reg_len = LENGTH; \
>>>
>>> Just write unsigned int reg_len = LENGTH;
>>>
>>> Oza> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (reg_len)); \
>>>
>>> Mind the spaces and parens. Better, use XNEWVEC:
>>>
>>> REGS = XNEWVEC (uint32_t, reg_len);
>>>
>>> Oza> + while (reg_len) \
>>> Oza> + { \
>>> Oza> + REGS[reg_len - 1] = RECORD_BUF[reg_len - 1]; \
>>> Oza> + reg_len--; \
>>> Oza> + } \
>>>
>>> Just use memcpy.
>>>
>>> Oza> +#define
>>> MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>>>
>>> The same comments apply for this macro.
>>>
>>> Oza> +/* ARM instruction record contains opcode of current insn and execution state
>>> Oza> (before entry to
>>>
>>> Oza> +decode_insn() ), contains list of to-be-modified registers and memory blocks
>>> Oza> (on return from
>>>
>>> Your email got corrupted. Usually this is some bad MUA setting.
>>>
>>> Oza> + uint32_t mem_rec_count; /* No of mem recors */
>>>
>>> Typo, "recors"
>>>
>>> Oza> +/* Checks ARM SBZ and SBO mendatory fields. */
>>>
>>> Typo, should be "mandatory".
>>>
>>> Oza> + if(!sbo)
>>>
>>> Spacing.
>>>
>>> Oza> + if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
>>>
>>> Over-parenthesizing makes the code harder to read. Please fix this. I
>>> noticed it in many places. This specific case should read:
>>>
>>> if (3 == opcode1 && bit
>>> (arm_insn_r->arm_insn, 4))
>>>
>>> Oza> + memset(&u_buf, 0, sizeof (u_buf));
>>>
>>> Spacing. Just go through the entire patch and fix all the spacing
>>> issues.
>>>
>>> I feel like I have mentioned this before.
>>>
>>> Oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
>>> Oza> + , &u_buf[0].unsigned_regval);
>>>
>>> What if this does not return REG_VALID?
>>> There are multiple instances of this.
>>>
>>> Oza> + gdb_assert_not_reached ("no decoding pattern found");
>>>
>>> It seems wrong to use an assert in this code. At least, it is not
>>> obvious to me that this represents a logic error in gdb as opposed to a
>>> merely unrecognized instruction. An unrecognized instruction can occur
>>> for many reasons, e.g., a bad jump.
>>>
>>> Oza> +
>>> if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
>>> Oza> + || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
>>> Oza> + || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
>>> Oza> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
>>> Oza> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
>>> Oza> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
>>> Oza> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
>>> Oza> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
>>>
>>> This reads very oddly. Is there a particular reason behind the ordering
>>> (if so -- document). If not, isn't
>>> this:
>>>
>>> if (arm_insn_r->opcode >= 0 && arm_insn_r->opcode <= 15)
>>>
>>> There are other odd-looking conditions like this.
>>>
>>> Oza> + default:
>>> Oza> + gdb_assert_not_reached ("Invalid addressing mode for insn");
>>>
>>> Again, assert seems wrong.
>>>
>>> I'm afraid I ran out of steam here. Please fix all the issues already
>>> noted and look at the rest of the patch with a critical eye to see what
>>> else should be cleaned up. I want this patch to go in, but first it
>>> must comply to the usual gdb standards.
>>>
>>> Tom
>>>
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-09-19 7:37 ` paawan oza
2011-09-22 17:12 ` oza Pawandeep
@ 2011-10-14 20:13 ` Tom Tromey
2011-10-15 3:46 ` paawan oza
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-10-14 20:13 UTC (permalink / raw)
To: paawan oza; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa
>>>>> "Oza" == paawan oza <paawan1982@yahoo.com> writes:
Oza> Thanks Chandra for doing testing and working on porintg x86 tcl test
Oza> cases to arm reversible.
Oza> please find the latest version of the patch after fixing couple of
Oza> bugs and review comment fix from Tom.
Your patch got mangled somehow.
It wraps in various places, making it very hard to read.
Could you somehow fix this up and repost it? Thanks.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-14 20:13 ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
@ 2011-10-15 3:46 ` paawan oza
2011-10-15 7:01 ` chandra krishnappa
` (2 more replies)
0 siblings, 3 replies; 128+ messages in thread
From: paawan oza @ 2011-10-15 3:46 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, Petr Hluzín, chandra krishnappa
please find the patch below.
PATCH STARTS
------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,1769 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof (uint32_t) * LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], sizeof (struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn and execution state (before entry to
+decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
+decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (!opcode1 && (9 == opcode2))
+ {
+ ret = -1;
+ /* Handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+ {
+ ret = -1;
+ /* Handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+ && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 4:
+ case 0:
+
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ LONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
+ u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
+ u_buf[0].unsigned_regval;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &u_buf[0].signed_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_buf[1].unsigned_regval);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval << (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers and dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* Wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count, record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_handle_data_proc_misc_ld_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_handle_ld_st_multiple_insn, /* 100. */
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_handle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+ thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is useless. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* Yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch, arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count; no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 3:46 ` paawan oza
@ 2011-10-15 7:01 ` chandra krishnappa
2011-10-15 9:32 ` Yao Qi
2011-10-16 23:32 ` Petr Hluzín
2 siblings, 0 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-10-15 7:01 UTC (permalink / raw)
To: Tom Tromey, paawan oza; +Cc: gdb-patches, Petr Hluzín
Oza,
I guess this <below code snippet> phase_2 code require further testing.. are there any changes for what I tested previously?
Also can you suggest if test scripts are written once for all once your complete phase_3 is completed. i.e the syscall functions code is implemented for reversible debugging.
I am trying to buy some time till phase_3 code implementation. Please advice.
Thanks & Regards,
-Chandra K
--- On Sat, 10/15/11, paawan oza <paawan1982@yahoo.com> wrote:
> From: paawan oza <paawan1982@yahoo.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "Tom Tromey" <tromey@redhat.com>
> Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Petr Hluzín" <petr.hluzin@gmail.com>, "chandra krishnappa" <chandra_roadking@yahoo.com>
> Date: Saturday, October 15, 2011, 9:15 AM
> please find the patch below.
>
> PATCH STARTS
> ------------------------
>
>
> diff -urN arm_orig/arm-linux-tdep.c
> arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-07-28
> 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-07-28
> 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
>
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch,
> arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
>
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes.
> */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000
> +0530
> +++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000
> +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -8821,3 +8823,1769 @@
> NULL, /* FIXME: i18n: "ARM
> debugging is %s. */
> &setdebuglist,
> &showdebuglist);
> }
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0], &RECORD_BUF[0],
> sizeof (uint32_t) * LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r,
> mem_len); \
> + memcpy(&MEMS->len,
> &RECORD_BUF[0], sizeof (struct arm_mem_r) * LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn
> and execution state (before entry to
> +decode_insn() ), contains list of to-be-modified registers
> and memory blocks (on return from
> +decode_insn() ). */
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of
> the insn being decoded. */
> + uint32_t arm_insn; /* Should
> accommodate thumb. */
> + uint32_t cond; /*
> Condition code. */
> + uint32_t opcode; /* Insn
> opcode. */
> + uint32_t decode; /* Insn
> decode bits. */
> + uint32_t mem_rec_count; /* No of mem
> records */
> + uint32_t reg_rec_count; /* No of reg
> records */
> + uint32_t *arm_regs; /* Registers to
> be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved
> for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len,
> uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) +
> (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit
> (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to
> handle if later versions
> + define it. */
> + }
> +
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (!opcode1 && (9 == opcode2))
> + {
> + ret = -1;
> + /* Handle arithmetic insn extension space.
> */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + if (!opcode1 && (2 == opcode2) && !bit
> (arm_insn_r->arm_insn, 20))
> + {
> + ret = -1;
> + /* Handle control insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (!opcode1 && bit (arm_insn_r->arm_insn,
> 7) \
> + && bit
> (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Handle load/store insn extension space.
> */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit
> (arm_insn_r->arm_insn, 21))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space.
> */
> + }
> +
> + /* To be done for ARMv5 and later; as of now we return
> -1. */
> + if (-1 == ret)
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0,
> tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode)
> && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 ==
> arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 ==
> arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count =
> 2;
> + }
> + else if ((4 <= arm_insn_r->opcode)
> && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL.
> */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode)
> || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L
> = 1). */
> + /* LDR insn has a capability to do
> branching, if
> + MOV LR, PC is
> preccedded by LDR insn having Rn as R15
> + in that case, it
> emulates branch and link insn, and hence we
> + need to save CSPR and
> PC as well. I am not sure this is right
> + place as opcode = 010
> LDR insn make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn,
> 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5,
> 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn,
> 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn,
> 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 ==
> arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit
> (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insns, changes register and memory as
> well. */
> + /* SWP or SWPB insn. */
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12
> == opcode1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of
> CSPR, bitp[0] of Rm,
> + and R14 stores
> the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12
> == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn,
> BKPT */
> + /* CPSR is changed to be executed in ARM
> state, disabling normal
> + interrupts, entering abort
> mode. */
> + /* Accorindly to high vector configuration PC
> is set accordingly */
> + /* What if user hit breakpoint and type
> reverse, in
> + that case, we need to go back
> with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit
> (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g.
> LDRD)
> + let us begin according to addressing
> modes for store insns
> + STRH insn, addresing modes are taken
> following. */
> + if ((14 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate
> offset. */
> + immed_low = bits (arm_insn_r->arm_insn,
> 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn,
> 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn,
> 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + if (15 == reg_src1)
> + {
> + /* If R15 was used as Rn, hence
> current PC+8. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + offset_8 = (immed_high << 4) |
> immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 ==
> arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn,
> 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn,
> 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> ,
> &u_buf[1].unsigned_regval);
>
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence
> current PC+8. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/-
> Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed.
> */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn,
> 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn,
> 8, 11);
> + offset_8 = (immed_high << 4) |
> immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn,
> 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + /* Calculate target store address, Rn +/-
> Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn,
> 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn,
> 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + /* Calculate target store address, Rn +/-
> Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
>
> + arm_insn_r->reg_rec_count = 1;
> + }
> + /* DSP insns (e.g. LDRD) TBD. */
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12
> == opcode1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR,
> bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16
> == opcode1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM)
> + && ((8 ==
> arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz
> (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the
> insn modifies destination
> + register, which is
> specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_handle_data_proc_imm_insn (insn_decode_record
> *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + if (((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode))
> + && (2 == bits
> (arm_insn_r->arm_insn, 20, 21))
> + && sbo_sbz (arm_insn_r->arm_insn,
> 13, 4, 1)
> + )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /*CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the
> insn modifies destination
> + register, which is
> specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +arm_handle_ld_st_imm_offset_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12,
> 15);
> + /* LDR insn has a capability to do branching,
> if
> + MOV LR, PC is precedded by LDR
> insn having Rn as R15
> + in that case, it emulates
> branch and link insn, and hence we
> + need to save CSPR and PC as
> well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Store, immediate offset, immediate
> pre-indexed,
> + immediate post-indexed.
> */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + offset_12 = bits (arm_insn_r->arm_insn, 0,
> 11);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf.unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf.unsigned_regval +
> offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf.unsigned_regval -
> offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 4:
> + case 0:
> +
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* We are handling pre-indexed mode;
> post-indexed mode;
> + where Rn
> is going to be changed. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_handle_ld_st_reg_offset_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0,
> tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + LONGEST signed_word;
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + let us begin according to addressing modes
> for store insns
> + STRH insn. */
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12,
> 15);
> + /* LDR insn has a capability to do branching,
> if
> + MOV LR, PC is precedded by LDR
> insn having Rn as R15
> + in that case, it emulates
> branch and link insn, and hence we
> + need to save CSPR and PC as
> well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and
> register pre-indexed,
> + register
> post-indexed. */
> + /* Get Rm. */
> + reg_src1 = bits
> (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits
> (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> ,
> &u_buf[1].unsigned_regval);
>
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence
> current PC+8. */
> + /* Pre-indexed mode doesnt
> reach here ; illegal insn. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn
> +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval +
> +
> u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval -
> +
> u_buf[0].unsigned_regval;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case
> 5:
> + /* STR */
> + case 0:
> + case 4:
> + /* STR insn, STRT insn.
> */
> + record_buf_mem[0] =
> 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn.
> */
> + record_buf_mem[0] =
> 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11
> == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15
> == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2
> == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6
> == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3
> == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7
> == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in
> pre-indexed mode and
> +
> post-indexed mode as well. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count =
> 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset;
> scaled pre-indexed. */
> + offset_12 = bits
> (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits
> (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits
> (arm_insn_r->arm_insn, 16, 19);
> + /* Get shift_imm. */
> + shift_imm = bits
> (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_signed (reg_cache,
> reg_src1
> +
> , &u_buf[0].signed_word);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + /* Offset_12 used as shift. */
> + switch (offset_12)
> + {
> + case 0:
> + /* Offset_12 used as
> index. */
> + offset_12 =
> u_buf[0].unsigned_regval << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 =
> (!shift_imm)?0:u_buf[0].unsigned_regval >> shift_imm;
>
> + break;
> +
> + case 2:
> + if (!shift_imm)
> + {
> + if (bit
> (u_buf[0].unsigned_regval, 31))
> + {
> + offset_12 =
> 0xFFFFFFFF;
> + }
> + else
> + {
> + offset_12 =
> 0;
> + }
> + }
> + else
> + {
> + /* This is
> arithmetic shift. */
> + offset_12 =
> u_buf[0].signed_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> +
> regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> +
> , &u_buf[1].unsigned_regval);
> + /* Get C flag value
> and shift it by 31. */
> + offset_12 = (((bit
> (u_buf[1].unsigned_regval, 29)) << 31) \
> +
> | (u_buf[0].unsigned_regval) >> 1);
> + }
> + else
> +
> {
> + offset_12 =
> (u_buf[0].unsigned_regval >> shift_imm) \
> + |
> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
> shift_imm));
> + }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case
> 5:
> + /* STR */
> + case 0:
> + case 4:
> + /* STR insn, STRT insn.
> */
> + record_buf_mem[0] =
> 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + /* STRB insn, STRBT insn.
> */
> + record_buf_mem[0] =
> 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> +
> }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11
> == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15
> == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2
> == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6
> == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3
> == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7
> == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in
> register scaled pre-indexed
> +
> mode, and scaled post indexed mode. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count =
> 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_handle_ld_st_multiple_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0,
> register_bits = 0;
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
> no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + /* This mode is exclusively for load and store
> multiple. */
> + /* Handle incremenrt after/before and decrment
> after.before mode;
> + Rn is changing depending on W bit, but as
> of now we store Rn too without optmization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR
> too. */
> +
> + if (bit (arm_insn_r->arm_insn,20) &&
> !bit (arm_insn_r->arm_insn,22))
> + {
> + register_bits = bits
> (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> + else
> + {
> + register_bits = bits
> (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >>
> 1;
> + }
> +
> + /* Extra space for Base Register and CPSR;
> wihtout optmization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] =
> ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count =
> register_count + 2;
> +
> + for (register_count = 0; register_count
> < no_of_regs; register_count++)
> + {
> + if
> (register_list[register_count])
> + {
> + /* Register_count gives total
> no of registers and dually working
> +
> as reg number. */
> + record_buf[index] =
> register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23,
> 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0,
> 15);
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch (addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
>
> + start_address =
> (u_buf[0].unsigned_regval) - (register_count * 4) + 4;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count
> * 2) - 1] = start_address;
> + record_buf_mem[(register_count
> * 2) - 2] = 4;
> + start_address = start_address +
> 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address =
> u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count
> * 2) - 1] = start_address;
> + record_buf_mem[(register_count
> * 2) - 2] = 4;
> + start_address = start_address +
> 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address =
> (u_buf[0].unsigned_regval) - (register_count * 4);
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count
> * 2) - 1] = start_address;
> + record_buf_mem[(register_count
> * 2) - 2] = 4;
> + start_address = start_address +
> 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case 3:
> + start_address =
> u_buf[0].unsigned_regval + 4;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count
> * 2) - 1] = start_address;
> + record_buf_mem[(register_count
> * 2) - 2] = 4;
> + start_address = start_address +
> 4;
> + register_count--;
> + }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + /* Base register also changes; based on condition
> and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* Wihtout optmization we save link register,
> + CSPR for the insn which changes T bit.
> */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (arm_insn_r->arm_regs,
> arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +arm_handle_coproc_data_proc_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep
> (arm_insn_r->gdbarch);
> + struct regcache *reg_cache =
> arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
> + uint32_t start_address = 0;
> +
> + /* Handle SWI insn; system call would be handled over
> here. */
> +
> + arm_insn_r->opcode = bits
> (arm_insn_r->arm_insn, 24, 27);
> + if (15 == arm_insn_r->opcode)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> +
> tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall
> record support\n"));
> + return -1;
> + }
> + }
> +
> + 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;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_handle_shift_add_sub_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + gdb_byte buf[4];
> + } u_buf[2];
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
> +
> + if (bit (thumb_insn_r->arm_insn, 12))
> + {
> + /* Handle load/store register offset. */
> + opcode2 = bits (thumb_insn_r->arm_insn, 9,
> 10);
> + if ((opcode2 >= 12) && (opcode2
> <= 15))
> + {
> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB,
> LDRSH. */
> + reg_src1 = bits
> (thumb_insn_r->arm_insn,0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if ((opcode2 >= 8) && (opcode2
> <= 10))
> + {
> + /* STR(2), STRB(2), STRH(2) . */
> + reg_src1 = bits
> (thumb_insn_r->arm_insn, 3, 5);
> + reg_src2 = bits
> (thumb_insn_r->arm_insn, 6, 8);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + if (8 == opcode2)
> + record_buf_mem[0] = 4; /* STR
> (2). */
> + else if (10 == opcode2)
> + record_buf_mem[0] = 1; /*
> STRB (2). */
> + else if (9 == opcode2)
> + record_buf_mem[0] = 2; /*
> STRH (2). */
> + record_buf_mem[1] =
> u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + }
> + else if (bit (thumb_insn_r->arm_insn, 11))
> + {
> + /* Handle load from literal pool. */
> + /* LDR(3). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode1)
> + {
> + opcode2 = bits (thumb_insn_r->arm_insn, 8,
> 9);
> + opcode3 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + if ((3 == opcode2) && (!opcode3))
> + {
> + /* Branch with exchange. */
> + record_buf[0] = ARM_PS_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + 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;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Format 5; data processing insns. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + if (bit (thumb_insn_r->arm_insn, 7))
> + {
> + reg_src1 = reg_src1 + 8;
> + }
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (opcode)
> + {
> + /* LDR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* STR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
> 5);
> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
> 10);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_5 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +thumb_handle_ld_st_stack_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (3 == opcode)
> + {
> + /* LDR(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == opcode)
> + {
> + /* LDRH(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* STR(3). */
> + immed_8 = bits (thumb_insn_r->arm_insn, 0,
> 7);
> + regcache_raw_read_unsigned (reg_cache,
> ARM_SP_REGNUM
> +
> , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_8 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + else if (0 == opcode)
> + {
> + /* STRH(1). */
> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
> 10);
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
> 5);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf.unsigned_regval);
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_5 * 2);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
> = 0, immed_5 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0,
> start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits
> (thumb_insn_r->arm_insn, 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] =
> 1;
> + register_bits = register_bits >>
> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] =
> ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count
> + 2;
> + for (register_count = 0; register_count < 8;
> register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] =
> register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits
> (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache,
> ARM_PC_REGNUM
> +
> , &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >>
> 1;
> + }
> + start_address = u_buf.unsigned_regval - \
> + (4 * (bit
> (thumb_insn_r->arm_insn, 8) + register_count)) ;
> + thumb_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn. */
> + /* Handle enhanced software breakpoint insn,
> BKPT. */
> + /* CPSR is changed to be executed in ARM
> state, disabling normal
> + interrupts, entering abort
> mode. */
> + /* Accorindly to high vector configuration PC
> is set accordingly. */
> + /* FIX ME ? what if user hit breakpoint and
> type reverse, in
> + that case, we need to go back
> with previous CPSR and
> + Program Counter.. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* Save SPSR also; how?. */
> + printf_unfiltered (_("Process record does not
> support instruction "
> +
> "0x%0x at address %s.\n"),
> +
> thumb_insn_r->arm_insn,
> + paddress
> (thumb_insn_r->gdbarch, thumb_insn_r->this_addr));
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> + {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_handle_swi_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep
> (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0,
> register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0,
> start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits
> (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] =
> 1;
> + register_bits = register_bits >>
> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count
> + 1;
> + for (register_count = 0; register_count < 8;
> register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] =
> register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits
> (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1, &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >>
> 1;
> + }
> + start_address = u_buf.unsigned_regval;
> + thumb_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> +
> tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall
> record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B(1), conditional branch is automatically taken care
> in process_record,
> + as PC is saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count, record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_handle_branch_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> +
> + /* BL , BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + /* B(2) is automatically taken care in process_record,
> as PC is saved
> + there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and
> opcodes; and dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t
> insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes
> type of arm instruction. */
> + static int (*const arm_handle_insn[8])
> +
> (insn_decode_record*) =
> + {
> + arm_handle_data_proc_misc_ld_str_insn, /*
> 000. */
> +
> arm_handle_data_proc_imm_insn, /*
> 001. */
> +
> arm_handle_ld_st_imm_offset_insn, /* 010.
> */
> +
> arm_handle_ld_st_reg_offset_insn, /* 011.
> */
> +
> arm_handle_ld_st_multiple_insn, /*
> 100. */
> +
> arm_handle_brn_insn,
> /* 101. */
> +
> arm_handle_coproc_insn,
> /* 110. */
> +
> arm_handle_coproc_data_proc_insn /* 111.
> */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes
> type of thumb instruction. */
> + static int (*const thumb_handle_insn[8])
> +
> (insn_decode_record*) =
> + { \
> +
> thumb_handle_shift_add_sub_insn, /* 000.
> */
> + thumb_handle_add_sub_cmp_mov_insn,
> /* 001. */
> + thumb_handle_ld_st_reg_offset_insn,
> /* 010. */
> + thumb_handle_ld_st_imm_offset_insn,
> /* 011. */
> +
> thumb_handle_ld_st_stack_insn, /* 100.
> */
> +
> thumb_handle_misc_insn, /*
> 101. */
> +
> thumb_handle_swi_insn,
> /* 110. */
> +
> thumb_handle_branch_insn /*
> 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr,
> &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record:
> error reading memory at "
> +
> "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch,
> arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_INSN_SIZE_BYTES == insn_size)
> + {
> + arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> + arm_record->cond = bits
> (arm_record->arm_insn, 28, 31);
> + insn_id = bits (arm_record->arm_insn, 25,
> 27);
> + ret = (0x0F != arm_record->cond)
> + ? arm_handle_insn[insn_id]
> (arm_record)
> + : handle_extension_space
> (arm_record);
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes,
> following field is useless. */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> +
> + insn_id = bits (arm_record->arm_insn, 13,
> 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> + {
> + /* Yet to be implemented; handle thumb2 part
> here. */
> + printf_unfiltered (_("Process record does not
> support instruction 0x%0x "
> + "at
> address %s.\n"),
> +
> arm_record->arm_insn,
> + paddress
> (arm_record->gdbarch, arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
> +/* Parse the current instruction and record the values of
> the registers and
> + memory that will be changed in current instruction to
> "record_arch_list".
> + Return -1 if something is wrong.. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct
> regcache *regcache,
> +
> CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order
> (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof
> (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process
> record: arm_process_record "
> +
> "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one.
> */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache,
> ARM_PS_REGNUM
> +
> , &u_buf.unsigned_regval);
> +
> + if (!(u_buf.unsigned_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record,
> ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record,
> THUMB_INSN_SIZE_BYTES);
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache,
> ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec <
> arm_record.reg_rec_count; no_of_rec++)
> + {
> + if (record_arch_list_add_reg
> (arm_record.regcache \
> +
> , (arm_record.arm_regs[no_of_rec])))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec <
> arm_record.mem_rec_count; no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> +
> ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> +
> arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000
> +0530
> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000
> +0530
> @@ -201,6 +201,9 @@
> /* Return the expected next PC if FRAME is stopped at
> a syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info
> *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
> /* Structures used for displaced stepping. */
> @@ -331,6 +334,8 @@
> instruction? */
> extern int arm_pc_is_thumb (struct gdbarch *,
> CORE_ADDR);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> +
> struct regcache *regcache, CORE_ADDR addr);
> /* Functions exported from armbsd-tdep.h. */
>
> /* Return the appropriate register set for the core
> section identified
>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 3:46 ` paawan oza
2011-10-15 7:01 ` chandra krishnappa
@ 2011-10-15 9:32 ` Yao Qi
2011-10-15 13:33 ` Yao Qi
2011-11-03 17:10 ` Tom Tromey
2011-10-16 23:32 ` Petr Hluzín
2 siblings, 2 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-15 9:32 UTC (permalink / raw)
To: gdb-patches
On 10/15/2011 11:45 AM, paawan oza wrote:
> please find the patch below.
>
I noticed that test cases in gdb.reverse are *not* enabled in default.
You need to add the following two lines in your board file to turn them on,
set_board_info gdb,use_precord 1
set_board_info gdb,can_reverse 1
It is good if you can post the test result in gdb.reverse so that we are
more confidient to your patch.
I am not an expert on record, so I don't have much comment on your code
logic. However, some of my cents below.
>
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch, arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-09-18 12:55:12.000000000 +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -8821,3 +8823,1769 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +
> +/* ARM instruction record contains opcode of current insn and execution state (before entry to
> +decode_insn() ), contains list of to-be-modified registers and memory blocks (on return from
> +decode_insn() ). */
These lines exceed the hard limit (80 chars). The second line of
comment should start from column 4, like this:
/* ARM instruction ...
and execution state .... */
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records */
> + uint32_t reg_rec_count; /* No of reg records */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to handle if later versions
> + define it. */
^ one redundant space.
> + }
> +
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (!opcode1 && (9 == opcode2))
> + {
> + ret = -1;
> + /* Handle arithmetic insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> + {
> + ret = -1;
> + /* Handle control insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
> + && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Handle load/store insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* To be done for ARMv5 and later; as of now we return -1. */
> + if (-1 == ret)
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is preccedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
Indentation here is wrong.
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
^^ magic number here. Use ARM_PC_REGNUM.
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insns, changes register and memory as well. */
^^ remove "s".
> + /* SWP or SWPB insn. */
This line of comment is useless.
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
^ "," should go to last line.
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
^^^^^^^^^^ Wrong indentation, and instances in other places.
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn, BKPT */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* Accorindly to high vector configuration PC is set accordingly */
> + /* What if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD)
> + let us begin according to addressing modes for store insns
> + STRH insn, addresing modes are taken following. */
> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
^ "," should be put in previous line
> + if (15 == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + offset_8 = (immed_high << 4) | immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 = (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + /* DSP insns (e.g. LDRD) TBD. */
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
"arm_handle_brn_insn" is confusing, because there is no insn "brn". I
would name this function as "arm_record_b_bl_blx".
> +{
> +
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* Wihtout optmization we save link register,
> + CSPR for the insn which changes T bit. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
^^ trail spaces, and many other places.
We don't have to record PS and LR for these three kinds of insns. For
B, we don't have to do anything here. We only record LR for BL and
record LS and PS for BLX.
> +
> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm instruction. */
> + static int (*const arm_handle_insn[8])
> + (insn_decode_record*) =
> + {
> + arm_handle_data_proc_misc_ld_str_insn, /* 000. */
> + arm_handle_data_proc_imm_insn, /* 001. */
> + arm_handle_ld_st_imm_offset_insn, /* 010. */
> + arm_handle_ld_st_reg_offset_insn, /* 011. */
> + arm_handle_ld_st_multiple_insn, /* 100. */
> + arm_handle_brn_insn, /* 101. */
> + arm_handle_coproc_insn, /* 110. */
> + arm_handle_coproc_data_proc_insn /* 111. */
I don't like the name scheme "arm_handle_xxxx_insn" of these fucntions.
In gdb backend, we "handle" insn for many different purposees, such as
software-single-step, displaced stepping, record, and etc. I suggest
that we name them like "arm_record_xxx" (without "_insn").
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb instruction. */
> + static int (*const thumb_handle_insn[8])
> + (insn_decode_record*) =
> + { \
> + thumb_handle_shift_add_sub_insn, /* 000. */
> + thumb_handle_add_sub_cmp_mov_insn, /* 001. */
> + thumb_handle_ld_st_reg_offset_insn, /* 010. */
> + thumb_handle_ld_st_imm_offset_insn, /* 011. */
> + thumb_handle_ld_st_stack_insn, /* 100. */
> + thumb_handle_misc_insn, /* 101. */
> + thumb_handle_swi_insn, /* 110. */
> + thumb_handle_branch_insn /* 111. */
> + };
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to "record_arch_list".
> + Return -1 if something is wrong.. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one. */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
> + , &u_buf.unsigned_regval);
> +
> + if (!(u_buf.unsigned_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
It is not correct to me. Both thumb 16-bit and 32-bit insn are handled
here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count; no_of_rec++)
> + {
> + if (record_arch_list_add_reg (arm_record.regcache \
> + , (arm_record.arm_regs[no_of_rec])))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count; no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> + arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
> /* Return the expected next PC if FRAME is stopped at a syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
I don't see any function is installed on this function pointer.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 9:32 ` Yao Qi
@ 2011-10-15 13:33 ` Yao Qi
2011-10-15 16:34 ` oza Pawandeep
2011-11-03 17:10 ` Tom Tromey
1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-10-15 13:33 UTC (permalink / raw)
To: gdb-patches
On 10/15/2011 05:31 PM, Yao Qi wrote:
> I noticed that test cases in gdb.reverse are *not* enabled in default.
> You need to add the following two lines in your board file to turn them on,
>
> set_board_info gdb,use_precord 1
> set_board_info gdb,can_reverse 1
>
> It is good if you can post the test result in gdb.reverse so that we are
> more confidient to your patch.
^^^^^^^^^^ typo "confident".
I run test cases in gdb.reverse with my own board file [1], and get
following result on x86:
=== gdb Summary ===
# of expected passes 2774
# of unexpected failures 22
I also applied your patch, and run gdb.reverse test cases on arm natively:
=== gdb Summary ===
# of expected passes 1180
# of unexpected failures 1090
# of expected failures 142
I don't think these fails are all related to your arm-reverse patch.
IMO, it means there are still some work to do, not only in arm bits, but
also in gdb general parts and test cases. Sorry that I can't give any
useful suggestion here.
--
Yao (é½å°§)
[1] My board file reverse.exp
load_generic_config "unix"
process_multilib_options ""
# The default compiler for this target.
set_board_info compiler "[find_gcc]"
set_board_info gdb,can_reverse 1
set_board_info gdb,use_precord 1
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 13:33 ` Yao Qi
@ 2011-10-15 16:34 ` oza Pawandeep
2011-10-15 17:38 ` oza Pawandeep
2011-10-17 3:18 ` Yao Qi
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-15 16:34 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi Yao,
first of all thank you for your comments, will be sending the patch
soon with your comments incorporated as much as possible.
thank you again for sending test results;
I suppose failed test case might be including
1) system call support
2) signal support
3) any other linux ABI support
4) there are some programs on x86 assembly which needs to be written
for ARM and put separately.
Thanks Yao,
Oza.
On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 10/15/2011 05:31 PM, Yao Qi wrote:
>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>> You need to add the following two lines in your board file to turn them on,
>>
>> set_board_info gdb,use_precord 1
>> set_board_info gdb,can_reverse 1
>>
>> It is good if you can post the test result in gdb.reverse so that we are
>> more confidient to your patch.
> ^^^^^^^^^^ typo "confident".
>
> I run test cases in gdb.reverse with my own board file [1], and get
> following result on x86:
>
> === gdb Summary ===
>
> # of expected passes 2774
> # of unexpected failures 22
>
> I also applied your patch, and run gdb.reverse test cases on arm natively:
>
> === gdb Summary ===
>
> # of expected passes 1180
> # of unexpected failures 1090
> # of expected failures 142
>
> I don't think these fails are all related to your arm-reverse patch.
> IMO, it means there are still some work to do, not only in arm bits, but
> also in gdb general parts and test cases. Sorry that I can't give any
> useful suggestion here.
>
> --
> Yao (齐尧)
>
> [1] My board file reverse.exp
>
> load_generic_config "unix"
> process_multilib_options ""
>
> # The default compiler for this target.
> set_board_info compiler "[find_gcc]"
>
> set_board_info gdb,can_reverse 1
> set_board_info gdb,use_precord 1
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 16:34 ` oza Pawandeep
@ 2011-10-15 17:38 ` oza Pawandeep
2011-10-16 8:00 ` oza Pawandeep
2011-10-17 3:18 ` Yao Qi
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-15 17:38 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi Yao,
I have implemented your comments, and will be sending the patch soon.
please find my comments below on some of your comments.
1) all the lines are truncated to < 80 chars now:
2) all the trailing spaces are deleted.
3) fixed indentation as much as I could find any.
4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn". I
would name this function as "arm_record_b_bl_blx
Oza: the name is changed, and rest of the names are also changed as
you suggested.
5)
Yao:
We don't have to record PS and LR for these three kinds of insns. For
B, we don't have to do anything here. We only record LR for BL and
record LS and PS for BLX.
Oza: yes, but in that case we just need to handle BL insn.
because BLX(1) reside in extension space which is/should be handled
separately in function
handle_instruction_space function.
so, BLX(1) will not fall here at all.
6)
Yao: It is not correct to me. Both thumb 16-bit and 32-bit insn are handled
here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
Oza: yes currently we have support for only 16 bit thumb.
the moment we support 32 bit, we will have one more else case with
THUMB_FULL_INSN_SIZE_BYTES 4
it will look like this
else if (ARM_INSN_SIZE_BYTES == insn_size)
{
}
else if (THUMB_INSN_SIZE_BYTES == insn_size)
{
}
else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
{
}
name is just an example:
if we want to handle thumb in same branch then could be changed
easily, depending on the writer of the code.
but as of now code doesnt support, so havent thought about it.
7) Yao: I don't see any function is installed on this function pointer.
Oza: yes, because phase 3 implementation is still pending which is
supposed to include system call function pointer and support of
syscall reverse.
Regards,
Oza.
On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> first of all thank you for your comments, will be sending the patch
> soon with your comments incorporated as much as possible.
> thank you again for sending test results;
>
> I suppose failed test case might be including
>
> 1) system call support
> 2) signal support
> 3) any other linux ABI support
> 4) there are some programs on x86 assembly which needs to be written
> for ARM and put separately.
>
> Thanks Yao,
> Oza.
>
>
> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>> You need to add the following two lines in your board file to turn them on,
>>>
>>> set_board_info gdb,use_precord 1
>>> set_board_info gdb,can_reverse 1
>>>
>>> It is good if you can post the test result in gdb.reverse so that we are
>>> more confidient to your patch.
>> ^^^^^^^^^^ typo "confident".
>>
>> I run test cases in gdb.reverse with my own board file [1], and get
>> following result on x86:
>>
>> === gdb Summary ===
>>
>> # of expected passes 2774
>> # of unexpected failures 22
>>
>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>
>> === gdb Summary ===
>>
>> # of expected passes 1180
>> # of unexpected failures 1090
>> # of expected failures 142
>>
>> I don't think these fails are all related to your arm-reverse patch.
>> IMO, it means there are still some work to do, not only in arm bits, but
>> also in gdb general parts and test cases. Sorry that I can't give any
>> useful suggestion here.
>>
>> --
>> Yao (齐尧)
>>
>> [1] My board file reverse.exp
>>
>> load_generic_config "unix"
>> process_multilib_options ""
>>
>> # The default compiler for this target.
>> set_board_info compiler "[find_gcc]"
>>
>> set_board_info gdb,can_reverse 1
>> set_board_info gdb,use_precord 1
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 17:38 ` oza Pawandeep
@ 2011-10-16 8:00 ` oza Pawandeep
2011-10-16 8:44 ` oza Pawandeep
2011-10-17 4:25 ` Yao Qi
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-16 8:00 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi,
please find the updated patch with Yao's comments.
PATCH STARTS
--------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-10-16 10:25:10.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,1772 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+and execution state (before entry to decode_insn() ),
+contains list of to-be-modified registers and
+memory blocks (on return from decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (!opcode1 && (9 == opcode2))
+ {
+ ret = -1;
+ /* Handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+ {
+ ret = -1;
+ /* Handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+ && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ LONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
+ u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
+ u_buf[0].unsigned_regval;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &u_buf[0].signed_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
+ shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_buf[1].unsigned_regval);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers and
dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) -
(register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here */
+ /* Note: BLX(1) doesnt fall here but instead it falls into extension space */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] =
u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is
useless. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* Yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+memory that will be changed in current instruction to "record_arch_list".
+Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> I have implemented your comments, and will be sending the patch soon.
>
> please find my comments below on some of your comments.
>
> 1) all the lines are truncated to < 80 chars now:
>
> 2) all the trailing spaces are deleted.
>
> 3) fixed indentation as much as I could find any.
>
> 4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn". I
> would name this function as "arm_record_b_bl_blx
>
> Oza: the name is changed, and rest of the names are also changed as
> you suggested.
>
> 5)
> Yao:
> We don't have to record PS and LR for these three kinds of insns. For
> B, we don't have to do anything here. We only record LR for BL and
> record LS and PS for BLX.
>
> Oza: yes, but in that case we just need to handle BL insn.
> because BLX(1) reside in extension space which is/should be handled
> separately in function
> handle_instruction_space function.
>
> so, BLX(1) will not fall here at all.
>
> 6)
> Yao: It is not correct to me. Both thumb 16-bit and 32-bit insn are handled
> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>
> Oza: yes currently we have support for only 16 bit thumb.
> the moment we support 32 bit, we will have one more else case with
> THUMB_FULL_INSN_SIZE_BYTES 4
>
> it will look like this
>
> else if (ARM_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
> {
> }
>
> name is just an example:
> if we want to handle thumb in same branch then could be changed
> easily, depending on the writer of the code.
> but as of now code doesnt support, so havent thought about it.
>
> 7) Yao: I don't see any function is installed on this function pointer.
>
> Oza: yes, because phase 3 implementation is still pending which is
> supposed to include system call function pointer and support of
> syscall reverse.
>
> Regards,
> Oza.
>
>
>
> On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>>
>> Thanks Yao,
>> Oza.
>>
>>
>> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>>> You need to add the following two lines in your board file to turn them on,
>>>>
>>>> set_board_info gdb,use_precord 1
>>>> set_board_info gdb,can_reverse 1
>>>>
>>>> It is good if you can post the test result in gdb.reverse so that we are
>>>> more confidient to your patch.
>>> ^^^^^^^^^^ typo "confident".
>>>
>>> I run test cases in gdb.reverse with my own board file [1], and get
>>> following result on x86:
>>>
>>> === gdb Summary ===
>>>
>>> # of expected passes 2774
>>> # of unexpected failures 22
>>>
>>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>>
>>> === gdb Summary ===
>>>
>>> # of expected passes 1180
>>> # of unexpected failures 1090
>>> # of expected failures 142
>>>
>>> I don't think these fails are all related to your arm-reverse patch.
>>> IMO, it means there are still some work to do, not only in arm bits, but
>>> also in gdb general parts and test cases. Sorry that I can't give any
>>> useful suggestion here.
>>>
>>> --
>>> Yao (齐尧)
>>>
>>> [1] My board file reverse.exp
>>>
>>> load_generic_config "unix"
>>> process_multilib_options ""
>>>
>>> # The default compiler for this target.
>>> set_board_info compiler "[find_gcc]"
>>>
>>> set_board_info gdb,can_reverse 1
>>> set_board_info gdb,use_precord 1
>>>
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-16 8:00 ` oza Pawandeep
@ 2011-10-16 8:44 ` oza Pawandeep
2011-10-17 4:25 ` Yao Qi
1 sibling, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-16 8:44 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi,
please find the updated patch with Yao's comments.
PATCH STARTS
--------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-10-16 10:25:10.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,1772 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+and execution state (before entry to decode_insn() ),
+contains list of to-be-modified registers and
+memory blocks (on return from decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (!opcode1 && (9 == opcode2))
+ {
+ ret = -1;
+ /* Handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
+ {
+ ret = -1;
+ /* Handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
+ && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* Record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ LONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof (u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
+ u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
+ u_buf[0].unsigned_regval;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &u_buf[0].signed_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
+ shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_buf[1].unsigned_regval);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR */
+ case 8:
+ case 12:
+ /* STR */
+ case 9:
+ case 13:
+ /* STRT */
+ case 1:
+ case 5:
+ /* STR */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB */
+ case 10:
+ case 14:
+ /* STRB */
+ case 11:
+ case 15:
+ /* STRBT */
+ case 3:
+ case 7:
+ /* STRB */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers and
dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) -
(register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here */
+ /* Note: BLX(1) doesnt fall here but instead it falls into extension space */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf[0].unsigned_regval);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] =
u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* Accorindly to high vector configuration PC is set accordingly. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is
useless. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* Yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+memory that will be changed in current instruction to "record_arch_list".
+Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> I have implemented your comments, and will be sending the patch soon.
>
> please find my comments below on some of your comments.
>
> 1) all the lines are truncated to < 80 chars now:
>
> 2) all the trailing spaces are deleted.
>
> 3) fixed indentation as much as I could find any.
>
> 4) Yao: arm_handle_brn_insn" is confusing, because there is no insn "brn". I
> would name this function as "arm_record_b_bl_blx
>
> Oza: the name is changed, and rest of the names are also changed as
> you suggested.
>
> 5)
> Yao:
> We don't have to record PS and LR for these three kinds of insns. For
> B, we don't have to do anything here. We only record LR for BL and
> record LS and PS for BLX.
>
> Oza: yes, but in that case we just need to handle BL insn.
> because BLX(1) reside in extension space which is/should be handled
> separately in function
> handle_instruction_space function.
>
> so, BLX(1) will not fall here at all.
>
> 6)
> Yao: It is not correct to me. Both thumb 16-bit and 32-bit insn are handled
> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>
> Oza: yes currently we have support for only 16 bit thumb.
> the moment we support 32 bit, we will have one more else case with
> THUMB_FULL_INSN_SIZE_BYTES 4
>
> it will look like this
>
> else if (ARM_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_INSN_SIZE_BYTES == insn_size)
> {
> }
> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
> {
> }
>
> name is just an example:
> if we want to handle thumb in same branch then could be changed
> easily, depending on the writer of the code.
> but as of now code doesnt support, so havent thought about it.
>
> 7) Yao: I don't see any function is installed on this function pointer.
>
> Oza: yes, because phase 3 implementation is still pending which is
> supposed to include system call function pointer and support of
> syscall reverse.
>
> Regards,
> Oza.
>
>
>
> On Sat, Oct 15, 2011 at 9:04 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>>
>> Thanks Yao,
>> Oza.
>>
>>
>> On Sat, Oct 15, 2011 at 6:02 PM, Yao Qi <yao@codesourcery.com> wrote:
>>> On 10/15/2011 05:31 PM, Yao Qi wrote:
>>>> I noticed that test cases in gdb.reverse are *not* enabled in default.
>>>> You need to add the following two lines in your board file to turn them on,
>>>>
>>>> set_board_info gdb,use_precord 1
>>>> set_board_info gdb,can_reverse 1
>>>>
>>>> It is good if you can post the test result in gdb.reverse so that we are
>>>> more confidient to your patch.
>>> ^^^^^^^^^^ typo "confident".
>>>
>>> I run test cases in gdb.reverse with my own board file [1], and get
>>> following result on x86:
>>>
>>> === gdb Summary ===
>>>
>>> # of expected passes 2774
>>> # of unexpected failures 22
>>>
>>> I also applied your patch, and run gdb.reverse test cases on arm natively:
>>>
>>> === gdb Summary ===
>>>
>>> # of expected passes 1180
>>> # of unexpected failures 1090
>>> # of expected failures 142
>>>
>>> I don't think these fails are all related to your arm-reverse patch.
>>> IMO, it means there are still some work to do, not only in arm bits, but
>>> also in gdb general parts and test cases. Sorry that I can't give any
>>> useful suggestion here.
>>>
>>> --
>>> Yao (齐尧)
>>>
>>> [1] My board file reverse.exp
>>>
>>> load_generic_config "unix"
>>> process_multilib_options ""
>>>
>>> # The default compiler for this target.
>>> set_board_info compiler "[find_gcc]"
>>>
>>> set_board_info gdb,can_reverse 1
>>> set_board_info gdb,use_precord 1
>>>
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-16 8:00 ` oza Pawandeep
2011-10-16 8:44 ` oza Pawandeep
@ 2011-10-17 4:25 ` Yao Qi
1 sibling, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-17 4:25 UTC (permalink / raw)
To: oza Pawandeep; +Cc: gdb-patches
On 10/16/2011 01:27 PM, oza Pawandeep wrote:
> Hi,
>
> please find the updated patch with Yao's comments.
First of all, do you plan to fix these test case fails I posted? Two
GDB internal errors make your arm-reversible patch unusable in some
cases. They should be fixed, IMO.
> On Sat, Oct 15, 2011 at 11:07 PM, oza Pawandeep
<oza.pawandeep@gmail.com> wrote:
>> Hi Yao,
>>
>> I have implemented your comments, and will be sending the patch soon.
>>
>> please find my comments below on some of your comments.
>>
>> 1) all the lines are truncated to < 80 chars now:
>>
>> 2) all the trailing spaces are deleted.
>>
>> 3) fixed indentation as much as I could find any.
>>
Looks like most of indentaiton of your 2nd line of comment is incorrect.
I'll point some of them out, but I may miss some.
I suggest that you can find some good editor which can highlight
trailing spaces and too-long line easily.
>> 6)
>> Yao: It is not correct to me. Both thumb 16-bit and 32-bit insn are
handled
>> here, so it is wrong to pass THUMB_INSN_SIZE_BYTES which is 2.
>>
>> Oza: yes currently we have support for only 16 bit thumb.
>> the moment we support 32 bit, we will have one more else case with
>> THUMB_FULL_INSN_SIZE_BYTES 4
Yes, only 16-bit thumb is supported, but you should report a warning or
error when encounter a 32-bit thumb insn, and skip it. In
arm_process_record, you assume that all thumb insns are 16-bit, which is
not correct. Please reference "thumb_process_displaced_insn".
>>
>> it will look like this
>>
>> else if (ARM_INSN_SIZE_BYTES == insn_size)
>> {
>> }
>> else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> {
>> }
>> else if (THUMB_WORD_INSN_SIZE_BYTES == insn_size)
>> {
>> }
>
> PATCH STARTS
> --------------------------------
>
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch, arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-10-16 10:25:10.000000000 +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -8821,3 +8823,1772 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn
> +and execution state (before entry to decode_insn() ),
> +contains list of to-be-modified registers and
> +memory blocks (on return from decode_insn() ). */
^^ incorrect indentation
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records */
> + uint32_t reg_rec_count; /* No of reg records */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to handle if later versions
> + define it. */
^^ incorrect indentation
> + }
> +
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (!opcode1 && (9 == opcode2))
> + {
> + ret = -1;
> + /* Handle arithmetic insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20))
> + {
> + ret = -1;
> + /* Handle control insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) \
You can put the condition in the next line if it is too long, but don't
need "\" here.
> + && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Handle load/store insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* To be done for ARMv5 and later; as of now we return -1. */
> + if (-1 == ret)
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is preccedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
^^ incorrect indentation
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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));
^^ incorrect indentation
> + return -1;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> +
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
^ "," should be in previous line.
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn, BKPT */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
^^ incorrect indentation
> + /* Accorindly to high vector configuration PC is set accordingly */
> + /* What if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
^^ incorrect indentation
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD)
> + let us begin according to addressing modes for store insns
> + STRH insn, addresing modes are taken following. */
^^ incorrect indentation
> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1,
> + &u_buf[0].unsigned_regval);
> + if (15 == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + offset_8 = (immed_high << 4) | immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
^ "," should be in previous line.
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
^ likewise.
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 = (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + /* DSP insns (e.g. LDRD) TBD. */
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
^^ incorrect indentation
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && (2 == bits (arm_insn_r->arm_insn, 20, 21))
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /*CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
^^ incorrect indentation
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
^^ incorrect indentation
> + if (ARM_PC_REGNUM != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Store, immediate offset, immediate pre-indexed,
> + immediate post-indexed. */
^^ incorrect indentation
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf.unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf.unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf.unsigned_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 4:
> + case 0:
> + record_buf_mem[0] = 4;
> + break;
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* We are handling pre-indexed mode; post-indexed mode;
> + where Rn is going to be changed. */
^^ incorrect indentation
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + LONGEST signed_word;
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + let us begin according to addressing modes for store insns
> + STRH insn. */
^^ incorrect indentation
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
^^ incorrect indentation
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and register pre-indexed,
> + register post-indexed. */
^^ incorrect indentation
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
> + u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval +
> + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval -
> + u_buf[0].unsigned_regval;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in pre-indexed mode and
> + post-indexed mode as well. */
^^ incorrect indentation
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset; scaled pre-indexed. */
> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + /* Get shift_imm. */
> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + regcache_raw_read_signed (reg_cache, reg_src1
> + , &u_buf[0].signed_word);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
^ "," should be in previous line.
> + /* Offset_12 used as shift. */
> + switch (offset_12)
> + {
> + case 0:
> + /* Offset_12 used as index. */
> + offset_12 = u_buf[0].unsigned_regval << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
^ ^^ spaces need between "?"
and ":".
> + shift_imm;
> + break;
> +
> + case 2:
> + if (!shift_imm)
> + {
> + if (bit (u_buf[0].unsigned_regval, 31))
> + {
> + offset_12 = 0xFFFFFFFF;
> + }
> + else
> + {
> + offset_12 = 0;
> + }
> + }
> + else
> + {
> + /* This is arithmetic shift. */
> + offset_12 = u_buf[0].signed_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> + regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> + , &u_buf[1].unsigned_regval);
> + /* Get C flag value and shift it by 31. */
> + offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31) \
> + | (u_buf[0].unsigned_regval) >> 1);
> + }
> + else
> + {
> + offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
> + | (u_buf[0].unsigned_regval <<
> + (sizeof(uint32_t) - shift_imm));
> + }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_buf[1].unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR */
> + case 8:
> + case 12:
> + /* STR */
> + case 9:
> + case 13:
> + /* STRT */
> + case 1:
> + case 5:
> + /* STR */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB */
> + case 10:
> + case 14:
> + /* STRB */
> + case 11:
> + case 15:
> + /* STRBT */
> + case 3:
> + case 7:
> + /* STRB */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
^^ incorrect indentation
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in register scaled pre-indexed
> + mode, and scaled post indexed mode. */
^^ incorrect indentation
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0, no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + /* This mode is exclusively for load and store multiple. */
> + /* Handle incremenrt after/before and decrment after.before mode;
> + Rn is changing depending on W bit, but as of now we store Rn too
^^ incorrect indentation
> + without optmization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
> +
> + if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> + else
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> +
> + /* Extra space for Base Register and CPSR; wihtout optmization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = register_count + 2;
> +
> + for (register_count = 0; register_count < no_of_regs; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + /* Register_count gives total no of registers and
> dually working
> + as reg number. */
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_buf[0].unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch (addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
> + start_address = (u_buf[0].unsigned_regval) -
> (register_count * 4) + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case 3:
> + start_address = u_buf[0].unsigned_regval + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + default:
> + return -1;
> + break;
> + }
> +
> + /* Base register also changes; based on condition and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_record_coproc (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
I don't understand why coproc insn is not handled for process record
here. is it in phase_3?
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_record_misc (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count + 2;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
> + , &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval - \
> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn. */
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* Accorindly to high vector configuration PC is set accordingly. */
> + /* FIX ME ? what if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter.. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* Save SPSR also; how?. */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb_insn_r->arm_insn,
> + paddress (thumb_insn_r->gdbarch,
> thumb_insn_r->this_addr));
Wrong indentation.
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> + {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_record_swi (insn_decode_record *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count + 1;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B(1), conditional branch is automatically taken care in process_record,
> + as PC is saved there. */
^^ wrong indentation.
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_record_branch (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> +
> + /* BL , BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + /* B(2) is automatically taken care in process_record, as PC is saved
> + there. */
^^ wrong indentation.
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction. */
> + static int (*const arm_handle_insn[8])
> + (insn_decode_record*) =
> + {
> + arm_record_data_proc_misc_ld_str, /* 000. */
> + arm_record_data_proc_imm, /* 001. */
> + arm_record_ld_st_imm_offset, /* 010. */
> + arm_record_ld_st_reg_offset, /* 011. */
> + arm_record_ld_st_multiple, /* 100. */
> + arm_record_b_bl, /* 101. */
> + arm_record_coproc, /* 110. */
> + arm_record_coproc_data_proc /* 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction. */
> + static int (*const thumb_handle_insn[8])
> + (insn_decode_record*) =
> + { \
> + thumb_record_shift_add_sub, /* 000. */
> + thumb_record_add_sub_cmp_mov, /* 001. */
> + thumb_record_ld_st_reg_offset, /* 010. */
> + thumb_record_ld_st_imm_offset, /* 011. */
> + thumb_record_ld_st_stack, /* 100. */
> + thumb_record_misc, /* 101. */
> + thumb_record_swi, /* 110. */
> + thumb_record_branch /* 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_INSN_SIZE_BYTES == insn_size)
> + {
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> + arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> + insn_id = bits (arm_record->arm_insn, 25, 27);
> + ret = (0x0F != arm_record->cond)
> + ? arm_handle_insn[insn_id] (arm_record)
> + : handle_extension_space (arm_record);
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes, following field is
> useless. */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
"," should be in previous line. Wrong indentaiton, and
> +
> + insn_id = bits (arm_record->arm_insn, 13, 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> + {
> + /* Yet to be implemented; handle thumb2 part here. */
> + printf_unfiltered (_("Process record does not support instruction 0x%0x "
> + "at address %s.\n"),
> + arm_record->arm_insn,
> + paddress (arm_record->gdbarch,
> arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
> +/* Parse the current instruction and record the values of the registers and
> +memory that will be changed in current instruction to "record_arch_list".
> +Return -1 if something is wrong.. */
We should not copy/paste such comment of gdbarch hook method. Please
replace it with
"/* This is the implementation of gdbarch method process_record. */"
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
^^ wrong indentation.
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one. */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
> + , &u_buf.unsigned_regval);
> +
> + if (!(u_buf.unsigned_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
If a 32-bit thumb-2 insn is red in, the following logic is wrong. As I
pointed out at the beginning.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 16:34 ` oza Pawandeep
2011-10-15 17:38 ` oza Pawandeep
@ 2011-10-17 3:18 ` Yao Qi
2011-10-17 4:28 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-10-17 3:18 UTC (permalink / raw)
To: oza Pawandeep; +Cc: gdb-patches
On 10/16/2011 12:34 AM, oza Pawandeep wrote:
> Hi Yao,
>
> first of all thank you for your comments, will be sending the patch
> soon with your comments incorporated as much as possible.
> thank you again for sending test results;
>
> I suppose failed test case might be including
>
> 1) system call support
> 2) signal support
> 3) any other linux ABI support
> 4) there are some programs on x86 assembly which needs to be written
> for ARM and put separately.
x86 assembly will not compiled and run for arm target, so they don't
make fails here. Beside these fails, I find there are some GDB internal
errors in test result:
stepi^M
../../gdb/gdb/breakpoint.c:12523: internal-error:
insert_single_step_breakpoint: Assertion `single_step_breakpoints[1] ==
NULL' failed.
stepi^M
../../gdb/gdb/infrun.c:1804: internal-error: resume: Assertion
`!(singlestep_breakpoints_inserted_p && step)' failed.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-17 3:18 ` Yao Qi
@ 2011-10-17 4:28 ` oza Pawandeep
2011-10-17 15:42 ` chandra krishnappa
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-17 4:28 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi Yao,
Thanks for your comments. please find my comments below.
1)
Yao: x86 assembly will not compiled and run for arm target, so they don't
> make fails here. Beside these fails, I find there are some GDB internal
> errors in test result
Oza: what I meant here was: x86 assembly might have failed to compile
even and gdb test results might be including that.
anyway, arm assembly has to be written separately, which I guess
Chandra K. might be doing.
2)
Yao:
Looks like most of indentaiton of your 2nd line of comment is incorrect.
I'll point some of them out, but I may miss some.
I suggest that you can find some good editor which can highlight
trailing spaces and too-long line easily.
Oza: this is one thing I have been struggling with, I have been moving
this patch back and forth from windows to linux and using
source insight, vi, xemacs
an d finally when I paste it to google mail the space gets distorted.
I need to find out what I can do.
sorry about repeating space mistakes.
3) Yes, only 16-bit thumb is supported, but you should report a warning or
error when encounter a 32-bit thumb insn, and skip it. In
arm_process_record, you assume that all thumb insns are 16-bit, which is
not correct. Please reference "thumb_process_displaced_insn".
Oza: I will include this logic.
4) Yao:
I don't understand why coproc insn is not handled for process record
here. is it in phase_3?
Oza: initially I had planned to put both coprocessor and
arm_extension_space insn in phase 3.
but I am going to update this patch with arm__extension_space insn atleast.
as far as coprocessor insns are concerned, I could not find any API
which could be used to read coprocessor register values.
I had sent email regarding the same long back: but I did not get
response, so I moved it to phase 3.
If you could point me out the way to read coprocessor register values:
I will try to implement on phase 2.
Thanks Yao,
Regards,
Oza.
On Mon, Oct 17, 2011 at 7:25 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 10/16/2011 12:34 AM, oza Pawandeep wrote:
>> Hi Yao,
>>
>> first of all thank you for your comments, will be sending the patch
>> soon with your comments incorporated as much as possible.
>> thank you again for sending test results;
>>
>> I suppose failed test case might be including
>>
>> 1) system call support
>> 2) signal support
>> 3) any other linux ABI support
>> 4) there are some programs on x86 assembly which needs to be written
>> for ARM and put separately.
>
> x86 assembly will not compiled and run for arm target, so they don't
> make fails here. Beside these fails, I find there are some GDB internal
> errors in test result:
>
> stepi^M
> ../../gdb/gdb/breakpoint.c:12523: internal-error:
> insert_single_step_breakpoint: Assertion `single_step_breakpoints[1] ==
> NULL' failed.
>
> stepi^M
> ../../gdb/gdb/infrun.c:1804: internal-error: resume: Assertion
> `!(singlestep_breakpoints_inserted_p && step)' failed.
>
> --
> Yao (齐尧)
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-17 4:28 ` oza Pawandeep
@ 2011-10-17 15:42 ` chandra krishnappa
0 siblings, 0 replies; 128+ messages in thread
From: chandra krishnappa @ 2011-10-17 15:42 UTC (permalink / raw)
To: Yao Qi, oza Pawandeep; +Cc: gdb-patches
Hi Yao and Oza,
Thanks for your comments and hints.. Yes, I wish to try test and submit test scripts soon. some hurdles to find time for testing.. will sort out and submit as soon as possible..
Thanks & Regards,
-Chandra K
--- On Mon, 10/17/11, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> From: oza Pawandeep <oza.pawandeep@gmail.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: "Yao Qi" <yao@codesourcery.com>
> Cc: gdb-patches@sourceware.org
> Date: Monday, October 17, 2011, 9:55 AM
> Hi Yao,
>
> Thanks for your comments. please find my comments below.
>
> 1)
> Yao: x86 assembly will not compiled and run for arm
> target, so they don't
> > make fails here. Beside these fails, I find
> there are some GDB internal
> > errors in test result
>
> Oza: what I meant here was: x86 assembly might have failed
> to compile
> even and gdb test results might be including that.
> anyway, arm assembly has to be written separately, which I
> guess
> Chandra K. might be doing.
>
> 2)
> Yao:
> Looks like most of indentaiton of your 2nd line of comment
> is incorrect.
> I'll point some of them out, but I may miss some.
>
> I suggest that you can find some good editor which can
> highlight
> trailing spaces and too-long line easily.
>
> Oza: this is one thing I have been struggling with, I have
> been moving
> this patch back and forth from windows to linux and using
> source insight, vi, xemacs
> an d finally when I paste it to google mail the space gets
> distorted.
> I need to find out what I can do.
> sorry about repeating space mistakes.
>
> 3) Yes, only 16-bit thumb is supported, but you should
> report a warning or
> error when encounter a 32-bit thumb insn, and skip
> it. In
> arm_process_record, you assume that all thumb insns are
> 16-bit, which is
> not correct. Please reference
> "thumb_process_displaced_insn".
>
> Oza: I will include this logic.
>
> 4) Yao:
> I don't understand why coproc insn is not handled for
> process record
> here. is it in phase_3?
>
> Oza: initially I had planned to put both coprocessor and
> arm_extension_space insn in phase 3.
> but I am going to update this patch with
> arm__extension_space insn atleast.
>
> as far as coprocessor insns are concerned, I could not find
> any API
> which could be used to read coprocessor register values.
> I had sent email regarding the same long back: but I did
> not get
> response, so I moved it to phase 3.
>
> If you could point me out the way to read coprocessor
> register values:
> I will try to implement on phase 2.
>
> Thanks Yao,
> Regards,
> Oza.
>
>
>
>
>
> On Mon, Oct 17, 2011 at 7:25 AM, Yao Qi <yao@codesourcery.com>
> wrote:
> > On 10/16/2011 12:34 AM, oza Pawandeep wrote:
> >> Hi Yao,
> >>
> >> first of all thank you for your comments, will be
> sending the patch
> >> soon with your comments incorporated as much as
> possible.
> >> thank you again for sending test results;
> >>
> >> I suppose failed test case might be including
> >>
> >> 1) system call support
> >> 2) signal support
> >> 3) any other linux ABI support
> >> 4) there are some programs on x86 assembly which
> needs to be written
> >> for ARM and put separately.
> >
> > x86 assembly will not compiled and run for arm target,
> so they don't
> > make fails here. Beside these fails, I find there
> are some GDB internal
> > errors in test result:
> >
> > stepi^M
> > ../../gdb/gdb/breakpoint.c:12523: internal-error:
> > insert_single_step_breakpoint: Assertion
> `single_step_breakpoints[1] ==
> > NULL' failed.
> >
> > stepi^M
> > ../../gdb/gdb/infrun.c:1804: internal-error: resume:
> Assertion
> > `!(singlestep_breakpoints_inserted_p && step)'
> failed.
> >
> > --
> > Yao (齐尧)
> >
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 9:32 ` Yao Qi
2011-10-15 13:33 ` Yao Qi
@ 2011-11-03 17:10 ` Tom Tromey
2011-11-04 16:27 ` Yao Qi
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:10 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:
Yao> I noticed that test cases in gdb.reverse are *not* enabled in default.
Do you know why that is? It seems to me that they should be enabled on
platforms where they are known to work. The current situation means
that any regressions are probably completely missed.
Yao> I am not an expert on record, so I don't have much comment on your code
Yao> logic. However, some of my cents below.
I think your review was quite helpful.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-03 17:10 ` Tom Tromey
@ 2011-11-04 16:27 ` Yao Qi
0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-11-04 16:27 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
On 11/04/2011 01:10 AM, Tom Tromey wrote:
>>>>>> "Yao" == Yao Qi <yao@codesourcery.com> writes:
>
> Yao> I noticed that test cases in gdb.reverse are *not* enabled in default.
>
> Do you know why that is? It seems to me that they should be enabled on
> platforms where they are known to work. The current situation means
> that any regressions are probably completely missed.
>
I don't know why, looks these cases are written in that way at the
beginning.
I have a sed script to convert "target_info exists gdb,use_precord" to a
proc "support_process_record" which returns true on x86-linux and
x86_64-linux. There are some fails running these tests in gdb.reverse
on x86-linux, IMO, we don't have to KFAIL them, because these fails are
unknown to us. I'll send out this patch later.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-15 3:46 ` paawan oza
2011-10-15 7:01 ` chandra krishnappa
2011-10-15 9:32 ` Yao Qi
@ 2011-10-16 23:32 ` Petr Hluzín
2011-10-22 15:42 ` oza Pawandeep
2011-11-03 17:38 ` Tom Tromey
2 siblings, 2 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-10-16 23:32 UTC (permalink / raw)
To: paawan oza; +Cc: Tom Tromey, gdb-patches, chandra krishnappa
On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
> please find the patch below.
I did not verify the style guidelines (spaces etc.), I am not familiar enough.
However some places have a comma ',' at the beginning of new line - I
think the "operator at newline" guideline does not apply to commas.
I did not check ARM semantics. It looks plausible, though.
The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
Only the assertion thing got worse:
In arm_handle_ld_st_imm_offset_insn()
>+ switch (arm_insn_r->opcode)
In arm_handle_ld_st_reg_offset_insn():
>+ switch (arm_insn_r->opcode)
>+ switch (offset_12)
>+ switch (arm_insn_r->opcode)
In arm_handle_ld_st_multiple_insn()
>+ switch (addr_mode)
These switches seem to have `return -1;' in cases which are not
reachable, therefore shoudl have gdb_assert_not_reached().
The guideline - which I think Tom was reffering to - is that
impossible states and coding bugs in gdb should trigger assertions
however user's input (no matter how malformed) should trigger warning
or error messages.
(This would mean to turn the lines with `default:' to the previous
revision. I understand this sucks.)
Some situations are difficult to decide whether they are trigger-able
by user input or not.
If my code is not coded or intended to handle such situations I prefer
to kill the process (or whatever are assertions configured to do) and
get feedback from user.
I am not familiar with GDB customs, though. Tom?
Oza> + gdb_assert_not_reached ("no decoding pattern found");
>
Tom> It seems wrong to use an assert in this code. At least, it is not
Tom> obvious to me that this represents a logic error in gdb as opposed to a
Tom> merely unrecognized instruction. An unrecognized instruction can occur
Tom> for many reasons, e.g., a bad jump.
The switch variable `arm_insn_r->opcode' cannot be initialized to any
value different from 0..15 because of the expression:
arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
The switch variable `offset_12' cannot be initialized to any value
different from 0..3 because of the expression: offset_12 = bits
(arm_insn_r->arm_insn, 5, 6).
The switch variable `addr_mode' cannot be initialized to any value
different from 0..3 because of the expression: addr_mode = bits
(arm_insn_r->arm_insn, 23, 24).
It would be bit easier to see that if the variables were local (as I suggested).
Other values are not possible to create, even with corrupted input or
unrecognized instructions.
Paawan: If Tom and I give you contradicting suggestions then you
should complain.
Issues remaining from my previous reviews:
In arm_handle_coproc_data_proc_insn()
+ if (15 == arm_insn_r->opcode)
...
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
...
+ return -1;
The function still returns -1 even when the instruction was recognized
(15) and OS syscall support function is not NULL.
Yes, there is no way to set it to non-NULL value yet but when it is
implemented then you would have to do this change anyway:
- tdep->arm_swi_record(reg_cache);
+ return tdep->arm_swi_record(reg_cache);
I guess the function should use `arm_insn_r' argument to record the
changes - which is missing.
In thumb_handle_swi_insn() the situation is the opposite: it returns 0
no matter what the arm_swi_record() returns.
In arm_handle_data_proc_misc_ld_str_insn()
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>>
>> You can get the same result (and simpler code) with
>> ULONGEST u_buf[2];
>> or maybe also better name with
>> ULONGEST u_regvals[2];
>>
>> The same applies to other functions.
>
> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
> and I fixed Tom’s review comments for endianness. I will change this, but pelase
> do not mind if it is not there in the immediate versions of patch, eventually
> after testing it will be changed.
This is still true.
> Oza: please report as I don’t have any automated tool which reports them, if it
> is not effort for you please report all if possible. Gcc also give some warning
> about unused one, but not sure about gdb warning suppression.
Unused local variables, as requested:
arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
reg_src2, addr_mode, start_address
thumb_handle_ld_st_imm_offset_insn: reg_val1
thumb_handle_ld_st_stack_insn: reg_val1
thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
opcode)', immed_8, immed_5
thumb_handle_swi_insn: reg_val1
thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5
Typos:
preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
addresing -> addressing, optmization -> optimization, Wihtout
optmization -> Without optimization,
Otherwise the patch looks good.
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-16 23:32 ` Petr Hluzín
@ 2011-10-22 15:42 ` oza Pawandeep
2011-10-23 10:17 ` oza Pawandeep
2011-11-03 17:38 ` Tom Tromey
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-10-22 15:42 UTC (permalink / raw)
To: Petr Hluzín; +Cc: paawan oza, Tom Tromey, gdb-patches, chandra krishnappa
Hi Petr,
Thanks for your comments again.
I have tried to take care of all your comments except
1) there is contradiction between yours and Tom's comment about
gdb_assert_not_reached.
I have changed back and forth earlier.
currently it return -1, indirectly gdb throws __error which results
into record stop completely.
2) the local variable usage as you sueggsted definately improves cache
line usage and performance
I want to leave it to regression probably in phase - 3; because other
changes from Yao and you have taken good amount of time.
please excuse me If you have to repeat he comments:
as this patch has grown too much that I miss something some or the other thing
the next patch update include the implementation of arm_extension_space insn.
Regards,
Oza.
On Mon, Oct 17, 2011 at 2:32 AM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
> On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
>> please find the patch below.
>
> I did not verify the style guidelines (spaces etc.), I am not familiar enough.
> However some places have a comma ',' at the beginning of new line - I
> think the "operator at newline" guideline does not apply to commas.
>
> I did not check ARM semantics. It looks plausible, though.
>
> The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
> Only the assertion thing got worse:
>
> In arm_handle_ld_st_imm_offset_insn()
>>+ switch (arm_insn_r->opcode)
> In arm_handle_ld_st_reg_offset_insn():
>>+ switch (arm_insn_r->opcode)
>>+ switch (offset_12)
>>+ switch (arm_insn_r->opcode)
> In arm_handle_ld_st_multiple_insn()
>>+ switch (addr_mode)
>
> These switches seem to have `return -1;' in cases which are not
> reachable, therefore shoudl have gdb_assert_not_reached().
> The guideline - which I think Tom was reffering to - is that
> impossible states and coding bugs in gdb should trigger assertions
> however user's input (no matter how malformed) should trigger warning
> or error messages.
> (This would mean to turn the lines with `default:' to the previous
> revision. I understand this sucks.)
>
> Some situations are difficult to decide whether they are trigger-able
> by user input or not.
> If my code is not coded or intended to handle such situations I prefer
> to kill the process (or whatever are assertions configured to do) and
> get feedback from user.
> I am not familiar with GDB customs, though. Tom?
>
> Oza> + gdb_assert_not_reached ("no decoding pattern found");
>>
> Tom> It seems wrong to use an assert in this code. At least, it is not
> Tom> obvious to me that this represents a logic error in gdb as opposed to a
> Tom> merely unrecognized instruction. An unrecognized instruction can occur
> Tom> for many reasons, e.g., a bad jump.
>
> The switch variable `arm_insn_r->opcode' cannot be initialized to any
> value different from 0..15 because of the expression:
> arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
> The switch variable `offset_12' cannot be initialized to any value
> different from 0..3 because of the expression: offset_12 = bits
> (arm_insn_r->arm_insn, 5, 6).
> The switch variable `addr_mode' cannot be initialized to any value
> different from 0..3 because of the expression: addr_mode = bits
> (arm_insn_r->arm_insn, 23, 24).
> It would be bit easier to see that if the variables were local (as I suggested).
> Other values are not possible to create, even with corrupted input or
> unrecognized instructions.
>
> Paawan: If Tom and I give you contradicting suggestions then you
> should complain.
>
>
> Issues remaining from my previous reviews:
>
> In arm_handle_coproc_data_proc_insn()
> + if (15 == arm_insn_r->opcode)
> ...
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> ...
> + return -1;
>
> The function still returns -1 even when the instruction was recognized
> (15) and OS syscall support function is not NULL.
> Yes, there is no way to set it to non-NULL value yet but when it is
> implemented then you would have to do this change anyway:
> - tdep->arm_swi_record(reg_cache);
> + return tdep->arm_swi_record(reg_cache);
>
> I guess the function should use `arm_insn_r' argument to record the
> changes - which is missing.
> In thumb_handle_swi_insn() the situation is the opposite: it returns 0
> no matter what the arm_swi_record() returns.
>
>
> In arm_handle_data_proc_misc_ld_str_insn()
>>> + struct
>>> + {
>>> + ULONGEST unsigned_regval;
>>> + } u_buf[2];
>>>
>>> You can get the same result (and simpler code) with
>>> ULONGEST u_buf[2];
>>> or maybe also better name with
>>> ULONGEST u_regvals[2];
>>>
>>> The same applies to other functions.
>>
>> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
>> and I fixed Tom’s review comments for endianness. I will change this, but pelase
>> do not mind if it is not there in the immediate versions of patch, eventually
>> after testing it will be changed.
>
> This is still true.
>
>
>> Oza: please report as I don’t have any automated tool which reports them, if it
>> is not effort for you please report all if possible. Gcc also give some warning
>> about unused one, but not sure about gdb warning suppression.
>
> Unused local variables, as requested:
> arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
> arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
> arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
> arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
> reg_src2, addr_mode, start_address
> thumb_handle_ld_st_imm_offset_insn: reg_val1
> thumb_handle_ld_st_stack_insn: reg_val1
> thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
> opcode)', immed_8, immed_5
> thumb_handle_swi_insn: reg_val1
> thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5
>
> Typos:
> preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
> addresing -> addressing, optmization -> optimization, Wihtout
> optmization -> Without optimization,
>
> Otherwise the patch looks good.
>
> --
> Petr Hluzin
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-22 15:42 ` oza Pawandeep
@ 2011-10-23 10:17 ` oza Pawandeep
2011-10-24 7:43 ` Petr Hluzín
` (2 more replies)
0 siblings, 3 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-10-23 10:17 UTC (permalink / raw)
To: Petr Hluzín, Tom Tromey, gdb-patches, chandra krishnappa
Hi all,
please find the updated patch attached.
check: this patch includes ARM extension space insn.
@Yao: I have tried to take care of formatting as much as possible in
xemacs editor, execuse me with identation problems and trailing space
problems.
I ahev tried to correct it; but not sure it has fallen righlty.
@Petr: tried to implement most of your comments: (please wait for some
variable to be made local, which will be done later,I have that in
mind).
@Chandra: please take this patch and run your tests on this. (it is
integrated with gdb7.3)
PATCH STARTS
-----------------------
diff -wurN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -wurN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-10-22 17:48:05.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,2005 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+while (0)
+
+#define INSN_RECORDED(ARM_RECORD) \
+ ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn() ),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn() ). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records */
+ uint32_t reg_rec_count; /* No of reg records */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+}arm_record_strx_t;
+
+static int
+arm_record_strx(insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ if (15 == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1=0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ /* handle unconditional insn extension space */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode1 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, cprocessor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && (9 == opcode2) && (1 != arm_insn_r->cond) &&
+ !(INSN_RECORDED(arm_insn_r)))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if ((0 <= insn_op1) && (3 >= insn_op1))
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= insn_op1) && (15 >= insn_op1))
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20) &&
+ (1 != arm_insn_r->cond) && !(INSN_RECORDED(arm_insn_r)))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SPSR is going to be changed. */
+ /* FIX ME: 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)) ||
+ (10 == bits (arm_insn_r->arm_insn, 4, 7)) ||
+ (12 == bits (arm_insn_r->arm_insn, 4, 7)) ||
+ (14 == bits (arm_insn_r->arm_insn, 4, 7))
+ )
+ {
+ if ((0 == insn_op1) || (1 == insn_op1))
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* we dont do optimization for SMULW<y> where we
need only Rd */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SPSR is going to be changed. */
+ /* FIX ME: 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) &&
+ bit (arm_insn_r->arm_insn, 4) && (1 != arm_insn_r->cond) &&
+ !(INSN_RECORDED(arm_insn_r)))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == insn_op1) && (!bit(arm_insn_r->arm_insn, 20)))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if ((2 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((3 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit(arm_insn_r->arm_insn, 20) && (insn_op1 <= 3))
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21) &&
+ !(INSN_RECORDED(arm_insn_r)))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] +
+ u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] -
+ u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+ default:
+ return -1;
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ And dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ return -1;
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also;how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ arm_record_extension_space (arm_record);
+ /* if this insn has fallen into extension space then we need
not decode it anymore. */
+ if (!INSN_RECORDED(arm_record))
+ {
+ arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, we set negatiive. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ printf_unfiltered (_("Process record does not support thumb32 "
+ "instruction 0x%0x at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_regval);
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -wurN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
Regards,
Oza.
On Sat, Oct 22, 2011 at 8:18 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Petr,
>
> Thanks for your comments again.
>
> I have tried to take care of all your comments except
>
> 1) there is contradiction between yours and Tom's comment about
> gdb_assert_not_reached.
> I have changed back and forth earlier.
> currently it return -1, indirectly gdb throws __error which results
> into record stop completely.
>
> 2) the local variable usage as you sueggsted definately improves cache
> line usage and performance
> I want to leave it to regression probably in phase - 3; because other
> changes from Yao and you have taken good amount of time.
>
> please excuse me If you have to repeat he comments:
> as this patch has grown too much that I miss something some or the other thing
>
> the next patch update include the implementation of arm_extension_space insn.
>
> Regards,
> Oza.
>
> On Mon, Oct 17, 2011 at 2:32 AM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
>> On 15 October 2011 05:45, paawan oza <paawan1982@yahoo.com> wrote:
>>> please find the patch below.
>>
>> I did not verify the style guidelines (spaces etc.), I am not familiar enough.
>> However some places have a comma ',' at the beginning of new line - I
>> think the "operator at newline" guideline does not apply to commas.
>>
>> I did not check ARM semantics. It looks plausible, though.
>>
>> The current patch (2011-10-15) is definitely an improvement to 2011-05-12.
>> Only the assertion thing got worse:
>>
>> In arm_handle_ld_st_imm_offset_insn()
>>>+ switch (arm_insn_r->opcode)
>> In arm_handle_ld_st_reg_offset_insn():
>>>+ switch (arm_insn_r->opcode)
>>>+ switch (offset_12)
>>>+ switch (arm_insn_r->opcode)
>> In arm_handle_ld_st_multiple_insn()
>>>+ switch (addr_mode)
>>
>> These switches seem to have `return -1;' in cases which are not
>> reachable, therefore shoudl have gdb_assert_not_reached().
>> The guideline - which I think Tom was reffering to - is that
>> impossible states and coding bugs in gdb should trigger assertions
>> however user's input (no matter how malformed) should trigger warning
>> or error messages.
>> (This would mean to turn the lines with `default:' to the previous
>> revision. I understand this sucks.)
>>
>> Some situations are difficult to decide whether they are trigger-able
>> by user input or not.
>> If my code is not coded or intended to handle such situations I prefer
>> to kill the process (or whatever are assertions configured to do) and
>> get feedback from user.
>> I am not familiar with GDB customs, though. Tom?
>>
>> Oza> + gdb_assert_not_reached ("no decoding pattern found");
>>>
>> Tom> It seems wrong to use an assert in this code. At least, it is not
>> Tom> obvious to me that this represents a logic error in gdb as opposed to a
>> Tom> merely unrecognized instruction. An unrecognized instruction can occur
>> Tom> for many reasons, e.g., a bad jump.
>>
>> The switch variable `arm_insn_r->opcode' cannot be initialized to any
>> value different from 0..15 because of the expression:
>> arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24).
>> The switch variable `offset_12' cannot be initialized to any value
>> different from 0..3 because of the expression: offset_12 = bits
>> (arm_insn_r->arm_insn, 5, 6).
>> The switch variable `addr_mode' cannot be initialized to any value
>> different from 0..3 because of the expression: addr_mode = bits
>> (arm_insn_r->arm_insn, 23, 24).
>> It would be bit easier to see that if the variables were local (as I suggested).
>> Other values are not possible to create, even with corrupted input or
>> unrecognized instructions.
>>
>> Paawan: If Tom and I give you contradicting suggestions then you
>> should complain.
>>
>>
>> Issues remaining from my previous reviews:
>>
>> In arm_handle_coproc_data_proc_insn()
>> + if (15 == arm_insn_r->opcode)
>> ...
>> + /* Handle arm syscall insn. */
>> + if (tdep->arm_swi_record != NULL)
>> + {
>> + tdep->arm_swi_record(reg_cache);
>> + }
>> ...
>> + return -1;
>>
>> The function still returns -1 even when the instruction was recognized
>> (15) and OS syscall support function is not NULL.
>> Yes, there is no way to set it to non-NULL value yet but when it is
>> implemented then you would have to do this change anyway:
>> - tdep->arm_swi_record(reg_cache);
>> + return tdep->arm_swi_record(reg_cache);
>>
>> I guess the function should use `arm_insn_r' argument to record the
>> changes - which is missing.
>> In thumb_handle_swi_insn() the situation is the opposite: it returns 0
>> no matter what the arm_swi_record() returns.
>>
>>
>> In arm_handle_data_proc_misc_ld_str_insn()
>>>> + struct
>>>> + {
>>>> + ULONGEST unsigned_regval;
>>>> + } u_buf[2];
>>>>
>>>> You can get the same result (and simpler code) with
>>>> ULONGEST u_buf[2];
>>>> or maybe also better name with
>>>> ULONGEST u_regvals[2];
>>>>
>>>> The same applies to other functions.
>>>
>>> Oza: It is correct, it was mis-evolved as inistially it was union with 2 members
>>> and I fixed Tom’s review comments for endianness. I will change this, but pelase
>>> do not mind if it is not there in the immediate versions of patch, eventually
>>> after testing it will be changed.
>>
>> This is still true.
>>
>>
>>> Oza: please report as I don’t have any automated tool which reports them, if it
>>> is not effort for you please report all if possible. Gcc also give some warning
>>> about unused one, but not sure about gdb warning suppression.
>>
>> Unused local variables, as requested:
>> arm_handle_ld_st_imm_offset_insn: reg_src2, immed_high, immed_low
>> arm_handle_ld_st_reg_offset_insn: immed_high, immed_low
>> arm_handle_ld_st_multiple_insn: shift_imm, reg_src2
>> arm_handle_coproc_data_proc_insn - all of them: shift_imm, reg_src1,
>> reg_src2, addr_mode, start_address
>> thumb_handle_ld_st_imm_offset_insn: reg_val1
>> thumb_handle_ld_st_stack_insn: reg_val1
>> thumb_handle_misc_insn: reg_val1, reg_src1 - write-only in case `(2 ==
>> opcode)', immed_8, immed_5
>> thumb_handle_swi_insn: reg_val1
>> thumb_handle_branch_insn: reg_val1, reg_src1, opcode, immed_5
>>
>> Typos:
>> preccedded -> precceded (3x), Accorindly -> Accordingly (2x),
>> addresing -> addressing, optmization -> optimization, Wihtout
>> optmization -> Without optimization,
>>
>> Otherwise the patch looks good.
>>
>> --
>> Petr Hluzin
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-23 10:17 ` oza Pawandeep
@ 2011-10-24 7:43 ` Petr Hluzín
2011-10-25 7:20 ` Yao Qi
2011-11-03 17:41 ` Tom Tromey
2 siblings, 0 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-10-24 7:43 UTC (permalink / raw)
To: oza Pawandeep; +Cc: Tom Tromey, gdb-patches, chandra krishnappa
Hi Oza, hi folks
On 22 October 2011 17:41, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> @Chandra: please take this patch and run your tests on this. (it is
> integrated with gdb7.3)
You probably meant to say the patch should be applied to gdb-7.3. It
is not there yet.
> +
> +#define INSN_RECORDED(ARM_RECORD) \
> + ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))
Is it supposed to return a boolean-like value? If yes then it would be
more descriptive to use INSN_IS_RECORDED. However I do not know if GDB
uses this convention. Tom?
Also there are extra parentheses. There should be parentheses around
ARM_RECORD argument.
Consider adding `== NULL' to the two tests to make it clear the fields
are pointers, not integers or booleans, and that the || is supposed to
be logical, not bit-wise. (I have heard few people have tools good
enough to tell them the types.)
In arm_record_strx:
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
The same here and several more places in this function. Search for "*("
In arm_record_extension_space:
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
> + opcode1 = bits (arm_insn_r->arm_insn, 4, 7);
> + if (arm_insn_r->cond)
> + {
> + /* PLD has no affect on architectural state, it just affects
> the caches. */
> + if (5 == ((opcode1 & 0xE0) >> 5))
This condition is never true because `opcode1 = bits
(arm_insn_r->arm_insn, 4, 7)' is value in range 0..15 therefore
`opcode1 & 0xE0' is always zero. I think.
> + {
> + /* BLX(1) */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, cprocessor insn. */
Typo cprocessor.
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21) &&
> + !(INSN_RECORDED(arm_insn_r)))
Operators should go to beginning of a new line, not at the end of previous line.
I.e.
if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21)
&& !(INSN_RECORDED(arm_insn_r)))
It is on multiple places involving the macro.
> + if (!INSN_RECORDED(arm_record))
> + {
> + arm_handle_insn[insn_id] (arm_record);
> + }
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes, we set negatiive. */
Typo negatiive.
In function arm_record_extension_space:
The function stores some values in local variable `uint32_t
record_buf[8]' but these values are never read. I suspect you forgot
to add calls to:
+ 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);
In function arm_record_extension_space:
The calls to INSN_RECORDED(arm_insn_r) will always return false,
because the fields referenced by the macro are always 0 at entry to
arm_record_extension_space() and the function does not modify them.
The missing calls to REG_ALLOC() & MEM_ALLOC() would modify them in
the end but it would be late anyway. I guess you will have to either
add a local flag variable or alter control flow - either way the
INSN_RECORDED seems like going to be unused.
(Function arm_record_strx() works differently and is not affected.)
In function arm_record_extension_space:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' at the
beginning of the function. That way it will be easy to understand
which part of code does change the state.
In function decode_insn:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' just before
call to arm_record_extension_space. That way it will be easy to
understand which part of code does change the state. Or use return
value from arm_record_extension_space() - this would make the
understanding even faster.
In function decode_insn:
Consider adding these assertions at the exit:
+ gdb_assert (arm_record->mem_rec_count == 0 || arm_record->arm_mems != NULL);
+ gdb_assert (arm_record->reg_rec_count == 0 || arm_record->arm_regs != NULL);
This would catch the missing REG_ALLOC calls in arm_record_extension_space().
Issues remaining since the previous revision:
Tom Tromey or someone should decide whether to use gdb_assert or not
(in the situation described in [1]).
Probably turn field `decode' & friends in insn_decode_record_t to
local variables. (Phase 3?)
[1] http://sourceware.org/ml/gdb-patches/2011-10/msg00449.html
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-23 10:17 ` oza Pawandeep
2011-10-24 7:43 ` Petr Hluzín
@ 2011-10-25 7:20 ` Yao Qi
2011-11-03 17:41 ` Tom Tromey
2 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-10-25 7:20 UTC (permalink / raw)
To: gdb-patches
On 10/22/2011 11:41 PM, oza Pawandeep wrote:
>
> @Yao: I have tried to take care of formatting as much as possible in
> xemacs editor, execuse me with identation problems and trailing space
> problems.
> I ahev tried to correct it; but not sure it has fallen righlty.
Yeah, it looks much better. I still have some comments below.
>
>
> PATCH STARTS
> -----------------------
> diff -wurN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-10-22 17:48:05.000000000 +0530
> @@ -8821,3 +8823,2005 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +
> +
> +
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
macro THUMB2_INSN_SIZE_BYTES is never used. Please remove it.
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
^ space before "(" and ",".
> +do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
^ ^ spaces are needed before "(" and ",".
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define INSN_RECORDED(ARM_RECORD) \
> + ((ARM_RECORD->arm_regs || ARM_RECORD->arm_mems))
> +
> +/* ARM instruction record contains opcode of current insn
> + and execution state (before entry to decode_insn() ),
> + contains list of to-be-modified registers and
> + memory blocks (on return from decode_insn() ). */
> +
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records */
> + uint32_t reg_rec_count; /* No of reg records */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
This function is used to match opcode for instructions. Why don't
you use bit operation (AND and OR) and logic operation to match
instruction? Bit operation and logic operation are widely used in
gdb. It is efficient and easy to read. I suggest to replace
sbo_sbz by bit/logical operation when matching instruction.
> +typedef enum
> +{
> + ARM_RECORD_STRH=1,
> + ARM_RECORD_STRD
> +}arm_record_strx_t;
> +
> +static int
> +arm_record_strx(insn_decode_record *arm_insn_r, uint32_t *record_buf,
^ space is missing
> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
^ wrong indentation.
> +{
> +
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + ULONGEST u_regval[2]= {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> +
> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
"," should be in previous line here and somewhere else.
> + if (15 == reg_src1)
^^ 15 is a magic number here and somewhere else.
Please use ARM_PC_REGNUM.
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + offset_8 = (immed_high << 4) | immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 = (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + return 0;
> +}
[...]
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> + ULONGEST u_regval[2] = {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precceded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> +
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_regval[0];
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* According to high vector configuration PC is set. */
> + /* What if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
^ space is required.
> + ARM_RECORD_STRH);
> + /* DSP insns (e.g. LDRD) TBD. */
Comment here is confusing. STRH (register) and STRH (immediate) are
handled here, but comment doesn't reflect this.
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_record_swi (insn_decode_record *thumb_insn_r)
The name of function is incorrect. Better to name it
"thumb_record_ldm_stm_swi", or something similar.
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t ret = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + ULONGEST u_regval = 0;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count + 1;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + ret = tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B(1), conditional branch is automatically taken care in process_record,
> + as PC is saved there. */
Redundant comments?
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return ret;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_record_branch (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> +
> + /* BL , BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> +
Again, don't have to store register PS for BL.
> + /* B(2) is automatically taken care in process_record, as PC is saved
> + there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction. */
> + static int (*const arm_handle_insn[8])
> + (insn_decode_record*) =
> + {
> + arm_record_data_proc_misc_ld_str, /* 000. */
> + arm_record_data_proc_imm, /* 001. */
> + arm_record_ld_st_imm_offset, /* 010. */
> + arm_record_ld_st_reg_offset, /* 011. */
> + arm_record_ld_st_multiple, /* 100. */
> + arm_record_b_bl, /* 101. */
> + arm_record_coproc, /* 110. */
> + arm_record_coproc_data_proc /* 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction. */
> + static int (*const thumb_handle_insn[8])
> + (insn_decode_record*) =
> + { \
> + thumb_record_shift_add_sub, /* 000. */
> + thumb_record_add_sub_cmp_mov, /* 001. */
> + thumb_record_ld_st_reg_offset, /* 010. */
> + thumb_record_ld_st_imm_offset, /* 011. */
> + thumb_record_ld_st_stack, /* 100. */
> + thumb_record_misc, /* 101. */
> + thumb_record_swi, /* 110. */
> + thumb_record_branch /* 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_INSN_SIZE_BYTES == insn_size)
> + {
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> + arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> + insn_id = bits (arm_record->arm_insn, 25, 27);
> + arm_record_extension_space (arm_record);
> + /* if this insn has fallen into extension space then we need
> not decode it anymore. */
> + if (!INSN_RECORDED(arm_record))
> + {
> + arm_handle_insn[insn_id] (arm_record);
> + }
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes, we set negatiive. */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> +
> + insn_id = bits (arm_record->arm_insn, 11, 15);
> + /* is it thumb2 insn? */
> + if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
> + {
> + printf_unfiltered (_("Process record does not support thumb32 "
> + "instruction 0x%0x at address %s.\n"),
> + arm_record->arm_insn,
> + paddress (arm_record->gdbarch,
> arm_record->this_addr));
> + ret = -1;
> + }
> + insn_id = bits (arm_record->arm_insn, 13, 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
This kind of design leaves thumb2-32 bit support difficult in the
future. We can let the caller, arm_process_record, to differentiate
arm/thumb 16bit/thumb 32bit, and call different decode routines
respectively, like this,
int
arm_process_record
{
if (!(u_regval & t_bit))
{
/* We are decoding arm insn. */
ret = arm_record_decode_arm (&arm_record);
}
else
{
insn = read_memory_unsigned_integer (start, 2, byte_order_for_code);
if (thumb_insn_size (insn) == 4)
ret = arm_record_decode_thumb_32bit (&arm_record);
else
ret = arm_record_decode_thumb_16bit (&arm_record);
}
....
}
In arm_record_decode_thumb_32bit, just print a warning like what we
have now. It makes future work easier.
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-23 10:17 ` oza Pawandeep
2011-10-24 7:43 ` Petr Hluzín
2011-10-25 7:20 ` Yao Qi
@ 2011-11-03 17:41 ` Tom Tromey
2011-11-05 17:36 ` Petr Hluzín
2 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:41 UTC (permalink / raw)
To: oza Pawandeep; +Cc: Petr Hluzín, gdb-patches
>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
Oza> please find the updated patch attached.
Oza> check: this patch includes ARM extension space insn.
Thanks for persevering through the review process.
I read the whole thread and I think at this point there are still some
unaddressed comments. If I am incorrect, could you point me to the most
up-to-date version of the patch? Then I will review it. Otherwise I
will wait for your next mail. Thanks.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-10-16 23:32 ` Petr Hluzín
2011-10-22 15:42 ` oza Pawandeep
@ 2011-11-03 17:38 ` Tom Tromey
2011-11-05 17:35 ` Petr Hluzín
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-03 17:38 UTC (permalink / raw)
To: Petr Hluzín; +Cc: paawan oza, gdb-patches, chandra krishnappa
>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
Petr> The guideline - which I think Tom was reffering to - is that
Petr> impossible states and coding bugs in gdb should trigger assertions
Petr> however user's input (no matter how malformed) should trigger warning
Petr> or error messages.
Yes, I think that rule makes the most sense.
Petr> Some situations are difficult to decide whether they are trigger-able
Petr> by user input or not.
Petr> If my code is not coded or intended to handle such situations I prefer
Petr> to kill the process (or whatever are assertions configured to do) and
Petr> get feedback from user.
Petr> I am not familiar with GDB customs, though. Tom?
I think crashing gdb should be limited to "can't happen" scenarios
arising from the internal logic.
Tripping across an unrecognized instruction or the like should just
result in an ordinary gdb error -- something the user can reasonably
recover from.
If the error message is informative enough about what went wrong, it
will result in a bug report :-)
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-03 17:38 ` Tom Tromey
@ 2011-11-05 17:35 ` Petr Hluzín
2011-11-07 15:39 ` Tom Tromey
0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-11-05 17:35 UTC (permalink / raw)
To: Tom Tromey; +Cc: paawan oza, gdb-patches, chandra krishnappa
On 3 November 2011 18:38, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
>
> Petr> The guideline - which I think Tom was reffering to - is that
> Petr> impossible states and coding bugs in gdb should trigger assertions
> Petr> however user's input (no matter how malformed) should trigger warning
> Petr> or error messages.
>
> Yes, I think that rule makes the most sense.
>
> Petr> Some situations are difficult to decide whether they are trigger-able
> Petr> by user input or not.
> Petr> If my code is not coded or intended to handle such situations I prefer
> Petr> to kill the process (or whatever are assertions configured to do) and
> Petr> get feedback from user.
> Petr> I am not familiar with GDB customs, though. Tom?
>
> I think crashing gdb should be limited to "can't happen" scenarios
> arising from the internal logic.
How strong is the "can't happen" requirement? Is programmer required
to prove the assertion cannot be triggered? The difficulty in general
case would be equivalent to proving a code is bug-free - i.e. it is
impossible. At my job we try to verify an assumption until we have a
sort-of-proof or the search becomes difficult and no clue/indication
to the contrary has been found yet.
I am asking because GDB code contains surprisingly few assertions.
> Tripping across an unrecognized instruction or the like should just
> result in an ordinary gdb error -- something the user can reasonably
> recover from.
>
> If the error message is informative enough about what went wrong, it
> will result in a bug report :-)
Well, when user gets a message "assertion failed" (and the user had
not messed with gdb sources) then the user knows its a bug in gdb. The
user does not have to understand what code broke - application
programmers generally do not have the knowledge anyway (symbols, ELF
internals, debugging hooks etc).
Anyway, the patch had used assertions correctly because expression
`bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
matter how bogus X value. Yes, all 2^32 values map to 0..15. The
assertions satisfy the guideline. (This is not even the hard-to-prove
case I was speculating above.)
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-05 17:35 ` Petr Hluzín
@ 2011-11-07 15:39 ` Tom Tromey
2011-11-08 6:02 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-11-07 15:39 UTC (permalink / raw)
To: Petr Hluzín; +Cc: paawan oza, gdb-patches, chandra krishnappa
>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
Petr> How strong is the "can't happen" requirement? Is programmer required
Petr> to prove the assertion cannot be triggered? The difficulty in general
Petr> case would be equivalent to proving a code is bug-free - i.e. it is
Petr> impossible. At my job we try to verify an assumption until we have a
Petr> sort-of-proof or the search becomes difficult and no clue/indication
Petr> to the contrary has been found yet.
Petr> I am asking because GDB code contains surprisingly few assertions.
I don't think there is a hard-and-fast rule in gdb. I am not completely
sure though.
I think in gdb it is best to error instead of assert if there is any
doubt. That's because I think when people turn to gdb they are already
a bit frustrated, and then if gdb itself fails, this is extremely
irritating. That's certainly been the case for me in the past.
I realize you can sort of recover from internal_error (and hence
assertions). But my impression is that internal_error is treated like
"not an exception-thrower" in gdb, leading to cleanup problems and the
like.
Petr> Anyway, the patch had used assertions correctly because expression
Petr> `bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
Petr> matter how bogus X value. Yes, all 2^32 values map to 0..15. The
Petr> assertions satisfy the guideline. (This is not even the hard-to-prove
Petr> case I was speculating above.)
Yeah, my review was wrong here.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-07 15:39 ` Tom Tromey
@ 2011-11-08 6:02 ` oza Pawandeep
2011-11-08 10:17 ` Yao Qi
2011-11-09 5:28 ` oza Pawandeep
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-08 6:02 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi All,
sorry for delay in reply. was on vacation.
I have already addressed the comments from both Petr and Yao in the next patch.
the comments which I have not fixed please find the explanation below.
Petr >>
Is it supposed to return a boolean-like value? If yes then it would be
more descriptive to use INSN_IS_RECORDED. However I do not know if GDB
uses this convention. Tom?
Also there are extra parentheses. There should be parentheses around
ARM_RECORD argument.
Consider adding `== NULL' to the two tests to make it clear the fields
are pointers, not integers or booleans, and that the || is supposed to
be logical, not bit-wise. (I have heard few people have tools good
enough to tell them the types.)
Oza >> I have changed the condition itself now.
you were right; after changing now it makes sense.
Petr >>
Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
Oza >> because calling function takes care of REG_ALLOC routine calls.
I did not want ALLOC calls to be scattered into any other function
other than main decoding functions.
Petr >>
This condition is never true because `opcode1 = bits
(arm_insn_r->arm_insn, 4, 7)' is value in range 0..15 therefore
`opcode1 & 0xE0' is always zero. I think.
Oza >> you are right, I fixed it now.
Oza >> typo mistakes are corrected.
Petr >> Operators should go to beginning of a new line, not at the end
of previous line.
Oza >> corrected.
Petr >>
In function arm_record_extension_space:
The function stores some values in local variable `uint32_t
record_buf[8]' but these values are never read. I suspect you forgot
to add calls to:
+ 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);
Oza >> yes, thanks for this comment, I added them now.
Petr >> n function arm_record_extension_space:
The calls to INSN_RECORDED(arm_insn_r) will always return false,
because the fields referenced by the macro are always 0 at entry to
arm_record_extension_space() and the function does not modify them.
The missing calls to REG_ALLOC() & MEM_ALLOC() would modify them in
the end but it would be late anyway. I guess you will have to either
add a local flag variable or alter control flow - either way the
INSN_RECORDED seems like going to be unused.
(Function arm_record_strx() works differently and is not affected.)
In function arm_record_extension_space:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' at the
beginning of the function. That way it will be easy to understand
which part of code does change the state.
In function decode_insn:
Consider adding `gdb_assert (!INSN_RECORDED(arm_insn_r))' just before
call to arm_record_extension_space. That way it will be easy to
understand which part of code does change the state. Or use return
value from arm_record_extension_space() - this would make the
understanding even faster.
In function decode_insn:
Consider adding these assertions at the exit:
+ gdb_assert (arm_record->mem_rec_count == 0 || arm_record->arm_mems != NULL);
+ gdb_assert (arm_record->reg_rec_count == 0 || arm_record->arm_regs != NULL);
This would catch the missing REG_ALLOC calls in arm_record_extension_space().
Oza >> the whole logic is falling in place now, everything is taken
care with the change of the MACRO IS_INSN_RECORDED.
Yao >> macro THUMB2_INSN_SIZE_BYTES is never used. Please remove it.
Oza >> it is intropduced again as required in the logic which you have proposed.
Yao >> This function is used to match opcode for instructions. Why don't
you use bit operation (AND and OR) and logic operation to match
instruction? Bit operation and logic operation are widely used in
gdb. It is efficient and easy to read. I suggest to replace
sbo_sbz by bit/logical operation when matching instruction.
Oza >> I am not sure what you meant by re-writting sbo_sbz function.
as there is already '&' and '!' and '>>' which all are bit operators.
Yao >> 15 is a magic number here and somewhere else.
Please use ARM_PC_REGNUM.
Oza >> corrected.
Yao >> Comment here is confusing. STRH (register) and STRH (immediate) are
handled here, but comment doesn't reflect this.
Oza >> done
Yao >> The name of function is incorrect. Better to name it
"thumb_record_ldm_stm_swi", or something similar.
Oza >> done
Yao >> Again, don't have to store register PS for BL.
Oza >> done
Yao >> This kind of design leaves thumb2-32 bit support difficult in the
future. We can let the caller, arm_process_record, to differentiate
arm/thumb 16bit/thumb 32bit, and call different decode routines
respectively, like this,
Oza >> proposed logic incorporated in caller.
Regards,
Oza.
On Mon, Nov 7, 2011 at 9:08 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Petr" == Petr Hluzín <petr.hluzin@gmail.com> writes:
>
> Petr> How strong is the "can't happen" requirement? Is programmer required
> Petr> to prove the assertion cannot be triggered? The difficulty in general
> Petr> case would be equivalent to proving a code is bug-free - i.e. it is
> Petr> impossible. At my job we try to verify an assumption until we have a
> Petr> sort-of-proof or the search becomes difficult and no clue/indication
> Petr> to the contrary has been found yet.
> Petr> I am asking because GDB code contains surprisingly few assertions.
>
> I don't think there is a hard-and-fast rule in gdb. I am not completely
> sure though.
>
> I think in gdb it is best to error instead of assert if there is any
> doubt. That's because I think when people turn to gdb they are already
> a bit frustrated, and then if gdb itself fails, this is extremely
> irritating. That's certainly been the case for me in the past.
>
> I realize you can sort of recover from internal_error (and hence
> assertions). But my impression is that internal_error is treated like
> "not an exception-thrower" in gdb, leading to cleanup problems and the
> like.
>
> Petr> Anyway, the patch had used assertions correctly because expression
> Petr> `bits (X, 21, 24)' yields value in range 0..15 for any value of X - no
> Petr> matter how bogus X value. Yes, all 2^32 values map to 0..15. The
> Petr> assertions satisfy the guideline. (This is not even the hard-to-prove
> Petr> case I was speculating above.)
>
> Yeah, my review was wrong here.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-08 6:02 ` oza Pawandeep
@ 2011-11-08 10:17 ` Yao Qi
2011-11-08 10:45 ` oza Pawandeep
2011-11-09 5:28 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-11-08 10:17 UTC (permalink / raw)
To: gdb-patches
On 11/08/2011 02:01 PM, oza Pawandeep wrote:
> Yao >> This function is used to match opcode for instructions. Why don't
> you use bit operation (AND and OR) and logic operation to match
> instruction? Bit operation and logic operation are widely used in
> gdb. It is efficient and easy to read. I suggest to replace
> sbo_sbz by bit/logical operation when matching instruction.
>
>
> Oza >> I am not sure what you meant by re-writting sbo_sbz function.
> as there is already '&' and '!' and '>>' which all are bit operators.
I suggested to remove sbo_sbz function, to decode instructions with
macros bits/bit, and to match using if/else/switch etc.
Please reference arm_get_next_pc_raw, arm_process_displaced_insn and
thumb_process_displaced_insn to see how instructions are decoded and
matched.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-08 10:17 ` Yao Qi
@ 2011-11-08 10:45 ` oza Pawandeep
0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-08 10:45 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches
Hi Yao,
the function sbo_sbz is generic function, which checks whether alll
the bits are 1 or all are 0 ?
the position of starting bit could be anything and ending bit could be anything.
this function accepts any position (between 0-31) and any length.
I looked at the functions which you suggested;
they seem to be working on specific insns.
I could not find a better way other than ANDing all the bits to find
out whether they all are 1 or 0.
I could be easily wrong here or still might not be getting the angle
which you are trying to bring in.
Regards,
Oza.
On Tue, Nov 8, 2011 at 3:46 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 11/08/2011 02:01 PM, oza Pawandeep wrote:
>> Yao >> This function is used to match opcode for instructions. Why don't
>> you use bit operation (AND and OR) and logic operation to match
>> instruction? Bit operation and logic operation are widely used in
>> gdb. It is efficient and easy to read. I suggest to replace
>> sbo_sbz by bit/logical operation when matching instruction.
>>
>>
>> Oza >> I am not sure what you meant by re-writting sbo_sbz function.
>> as there is already '&' and '!' and '>>' which all are bit operators.
>
> I suggested to remove sbo_sbz function, to decode instructions with
> macros bits/bit, and to match using if/else/switch etc.
>
> Please reference arm_get_next_pc_raw, arm_process_displaced_insn and
> thumb_process_displaced_insn to see how instructions are decoded and
> matched.
>
> --
> Yao (齐尧)
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-08 6:02 ` oza Pawandeep
2011-11-08 10:17 ` Yao Qi
@ 2011-11-09 5:28 ` oza Pawandeep
2011-11-09 6:08 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-09 5:28 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Thanks Tom, Petr and Yao for your comments.
I will be reintroducing assert_not_reached.
apart from that some unanswered questions of Petr and Yao as below.
Petr >> is the code integrated to gdb 7.3 ?
Oza >> not yet, what I meant was, the patch could be directly applied
on gdb-7.3.
Petr >> what about making opcode and other global variable to local
variable. in phase 3 ?
Oza >> yes, would like to take it in phase 3.
Yao >> some gdb.reverse tests are failing; are you planning to address those ?
Oza >> I ahve changed the code after that to soem extent, and more
over I am waiting for Chandra K to respond on his test case matter.
please let me know apart from that If any question remained unanswered.
next mail will contain the latest patch.
Regards,
Oza.
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-09 5:28 ` oza Pawandeep
@ 2011-11-09 6:08 ` oza Pawandeep
2011-11-17 9:24 ` oza Pawandeep
2011-11-17 20:40 ` Tom Tromey
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-11-09 6:08 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi,
please find the latest patch below.
PATCH STARTS
--------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-11-09 11:31:46.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,2039 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+while (0)
+
+#define INSN_RECORDED(ARM_RECORD) \
+ ((0 != ARM_RECORD->reg_rec_count) || (0 != ARM_RECORD->mem_rec_count))
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn() ),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn() ). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+}arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+}record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1=0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ /* handle unconditional insn extension space */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && (9 == opcode2) && (1 != arm_insn_r->cond)
+ && !(INSN_RECORDED(arm_insn_r)))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if ((0 <= insn_op1) && (3 >= insn_op1))
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= insn_op1) && (15 >= insn_op1))
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20)
+ && (1 != arm_insn_r->cond) && !(INSN_RECORDED(arm_insn_r)))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SPSR is going to be changed. */
+ /* FIX ME: 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)) ||
+ (10 == bits (arm_insn_r->arm_insn, 4, 7)) ||
+ (12 == bits (arm_insn_r->arm_insn, 4, 7)) ||
+ (14 == bits (arm_insn_r->arm_insn, 4, 7))
+ )
+ {
+ if ((0 == insn_op1) || (1 == insn_op1))
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* we dont do optimization for SMULW<y> where we
need only Rd */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SPSR is going to be changed. */
+ /* FIX ME: 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7) &&
+ bit (arm_insn_r->arm_insn, 4) && (1 != arm_insn_r->cond)
+ && !(INSN_RECORDED(arm_insn_r)))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == insn_op1) && (!bit(arm_insn_r->arm_insn, 20)))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if ((2 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((3 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit(arm_insn_r->arm_insn, 20) && (insn_op1 <= 3))
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21)
+ && !(INSN_RECORDED(arm_insn_r)))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* To be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* What if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] +
+ u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] -
+ u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ And dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0;
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* Save SPSR also;how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == record_type)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ arm_record_extension_space (arm_record);
+ /* if this insn has fallen into extension space then we need
not decode it anymore. */
+ if (!INSN_RECORDED(arm_record))
+ {
+ arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
(arm_record->gdbarch));
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_regval);
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
THUMB_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ , (arm_record.arm_regs[no_of_rec])))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-09 6:08 ` oza Pawandeep
@ 2011-11-17 9:24 ` oza Pawandeep
2011-11-17 9:52 ` Yao Qi
2011-11-17 20:40 ` Tom Tromey
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-17 9:24 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Petr and Yao,
It has been a while since I have heard from you.
Can I assume that there are no more review comments ?
Regards,
Oza.
On Wed, Nov 9, 2011 at 11:37 AM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi,
>
> please find the latest patch below.
>
> PATCH STARTS
> --------------------------------
>
>
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
> @@ -1025,6 +1025,9 @@
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch, arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1054,6 +1057,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-11-09 11:31:46.000000000 +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -8821,3 +8823,2039 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +
> +
> +
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
> +do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
> + } \
> + } \
> +while (0)
> +
> +#define INSN_RECORDED(ARM_RECORD) \
> + ((0 != ARM_RECORD->reg_rec_count) || (0 != ARM_RECORD->mem_rec_count))
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn
> + and execution state (before entry to decode_insn() ),
> + contains list of to-be-modified registers and
> + memory blocks (on return from decode_insn() ). */
> +
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records. */
> + uint32_t reg_rec_count; /* No of reg records. */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +typedef enum
> +{
> + ARM_RECORD_STRH=1,
> + ARM_RECORD_STRD
> +}arm_record_strx_t;
> +
> +typedef enum
> +{
> + ARM_RECORD=1,
> + THUMB_RECORD,
> + THUMB2_RECORD
> +}record_type_t;
> +
> +
> +static int
> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
> +{
> +
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + ULONGEST u_regval[2]= {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> +
> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1,
> + &u_regval[0]);
> + if (ARM_PC_REGNUM == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + offset_8 = (immed_high << 4) | immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 = (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + *(record_buf_mem) = 2;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + *(record_buf_mem) = 4;
> + *(record_buf_mem + 1) = tgt_mem_addr;
> + *(record_buf_mem + 2) = 4;
> + *(record_buf_mem + 3) = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + return 0;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +arm_record_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, insn_op1=0;
> + uint32_t record_buf[8], record_buf_mem[8];
> + uint32_t reg_src1 = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + ULONGEST u_regval = 0;
> +
> + /* handle unconditional insn extension space */
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> + if (arm_insn_r->cond)
> + {
> + /* PLD has no affect on architectural state, it just affects
> the caches. */
> + if (5 == ((opcode1 & 0xE0) >> 5))
> + {
> + /* BLX(1) */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
> + }
> +
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to handle if later versions
> + define it. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> + insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
> +
> + /* Handle arithmetic insn extension space. */
> + if (!opcode1 && (9 == opcode2) && (1 != arm_insn_r->cond)
> + && !(INSN_RECORDED(arm_insn_r)))
> + {
> + /* Handle MLA(S) and MUL(S). */
> + if ((0 <= insn_op1) && (3 >= insn_op1))
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= insn_op1) && (15 >= insn_op1))
> + {
> + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> + insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
> +
> + /* Handle control insn extension space. */
> +
> + if (!opcode1 && (2 == opcode2) && !bit (arm_insn_r->arm_insn, 20)
> + && (1 != arm_insn_r->cond) && !(INSN_RECORDED(arm_insn_r)))
> + {
> + if (!bit (arm_insn_r->arm_insn,25))
> + {
> + if (!bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + if ((0 == insn_op1) || (2 == insn_op1))
> + {
> + /* MRS. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == insn_op1)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* SPSR is going to be changed. */
> + /* FIX ME: 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;
> + }
> + }
> + else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + if (1 == insn_op1)
> + {
> + /* BX. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* BLX. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* QADD, QSUB, QDADD, QDSUB */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* BKPT. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)) ||
> + (10 == bits (arm_insn_r->arm_insn, 4, 7)) ||
> + (12 == bits (arm_insn_r->arm_insn, 4, 7)) ||
> + (14 == bits (arm_insn_r->arm_insn, 4, 7))
> + )
> + {
> + if ((0 == insn_op1) || (1 == insn_op1))
> + {
> + /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
> + /* we dont do optimization for SMULW<y> where we
> need only Rd */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (2 == insn_op1)
> + {
> + /* SMLAL<x><y>. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (3 == insn_op1)
> + {
> + /* SMUL<x><y>. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> + else
> + {
> + /* MSR : immediate form. */
> + if (1 == insn_op1)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* SPSR is going to be changed. */
> + /* FIX ME: 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;
> + }
> + }
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
> + insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
> +
> + /* Handle load/store insn extension space. */
> +
> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7) &&
> + bit (arm_insn_r->arm_insn, 4) && (1 != arm_insn_r->cond)
> + && !(INSN_RECORDED(arm_insn_r)))
> + {
> + /* SWP/SWPB. */
> + if (0 == insn_op1)
> + {
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == insn_op1) && (!bit(arm_insn_r->arm_insn, 20)))
> + {
> + /* STRH. */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRH);
> + }
> + else if ((2 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
> + {
> + /* LDRD. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = record_buf[0] + 1;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((3 == insn_op1) && !bit(arm_insn_r->arm_insn, 20))
> + {
> + /* STRD. */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRD);
> + }
> + else if (bit(arm_insn_r->arm_insn, 20) && (insn_op1 <= 3))
> + {
> + /* LDRH, LDRSB, LDRSH. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && bit (arm_insn_r->arm_insn, 21)
> + && !(INSN_RECORDED(arm_insn_r)))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* To be done for ARMv5 and later; as of now we return -1. */
> + if (-1 == ret)
> + 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));
> +
> +
> + 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);
> +
> + return ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> + ULONGEST u_regval[2] = {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precceded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> +
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_regval[0];
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* According to high vector configuration PC is set. */
> + /* What if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
> +
> + /* Handle str(x) insn */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRH);
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
> + && (2 == bits (arm_insn_r->arm_insn, 20, 21))
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + ULONGEST u_regval = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (ARM_PC_REGNUM != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Store, immediate offset, immediate pre-indexed,
> + immediate post-indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 4:
> + case 0:
> + record_buf_mem[0] = 4;
> + break;
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* We are handling pre-indexed mode; post-indexed mode;
> + where Rn is going to be changed. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + LONGEST s_word;
> + ULONGEST u_regval[2];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + let us begin according to addressing modes for store insns
> + STRH insn. */
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and register pre-indexed,
> + register post-indexed. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval[0] +
> + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] -
> + u_regval[0];
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in pre-indexed mode and
> + post-indexed mode as well. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset; scaled pre-indexed. */
> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + /* Get shift_imm. */
> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_signed (reg_cache, reg_src1
> + , &s_word);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + /* Offset_12 used as shift. */
> + switch (offset_12)
> + {
> + case 0:
> + /* Offset_12 used as index. */
> + offset_12 = u_regval[0] << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
> + break;
> +
> + case 2:
> + if (!shift_imm)
> + {
> + if (bit (u_regval[0], 31))
> + {
> + offset_12 = 0xFFFFFFFF;
> + }
> + else
> + {
> + offset_12 = 0;
> + }
> + }
> + else
> + {
> + /* This is arithmetic shift. */
> + offset_12 = s_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> + regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> + , &u_regval[1]);
> + /* Get C flag value and shift it by 31. */
> + offset_12 = (((bit (u_regval[1], 29)) << 31) \
> + | (u_regval[0]) >> 1);
> + }
> + else
> + {
> + offset_12 = (u_regval[0] >> shift_imm) \
> + | (u_regval[0] <<
> + (sizeof(uint32_t) - shift_imm));
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + /* bit U set. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval[1] + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in register scaled pre-indexed
> + mode, and scaled post indexed mode. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
> + uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + ULONGEST u_regval[2] = {0};
> +
> + /* This mode is exclusively for load and store multiple. */
> + /* Handle incremenrt after/before and decrment after.before mode;
> + Rn is changing depending on W bit, but as of now we store Rn too
> + without optimization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
> +
> + if (bit (arm_insn_r->arm_insn,20) && !bit (arm_insn_r->arm_insn,22))
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> + else
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> +
> + /* Extra space for Base Register and CPSR; wihtout optimization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = register_count + 2;
> +
> + for (register_count = 0; register_count < no_of_regs; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + /* Register_count gives total no of registers
> + And dually working as reg number. */
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch (addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
> + start_address = (u_regval[0]) - (register_count * 4) + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address = u_regval[0];
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address = (u_regval[0]) - (register_count * 4);
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case 3:
> + start_address = u_regval[0] + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> +
> + /* Base register also changes; based on condition and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +arm_record_b_bl (insn_decode_record *arm_insn_r)
> +{
> +
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* B simply branches so we do nothing here. */
> + /* Note: BLX(1) doesnt fall here but instead it falls into
> extension space. */
> + if (bit (arm_insn_r->arm_insn, 24))
> + {
> + record_buf[0] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_record_coproc (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t ret = 0;
> +
> + /* Handle SWI insn; system call would be handled over here. */
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
> + if (15 == arm_insn_r->opcode)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + ret = tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + ret = -1;
> + }
> + }
> +
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
> +
> + ULONGEST u_regval[2] = {0};
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
> +
> + if (bit (thumb_insn_r->arm_insn, 12))
> + {
> + /* Handle load/store register offset. */
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
> + if ((opcode2 >= 12) && (opcode2 <= 15))
> + {
> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
> + reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if ((opcode2 >= 8) && (opcode2 <= 10))
> + {
> + /* STR(2), STRB(2), STRH(2) . */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + if (8 == opcode2)
> + record_buf_mem[0] = 4; /* STR (2). */
> + else if (10 == opcode2)
> + record_buf_mem[0] = 1; /* STRB (2). */
> + else if (9 == opcode2)
> + record_buf_mem[0] = 2; /* STRH (2). */
> + record_buf_mem[1] = u_regval[0] + u_regval[1];
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + }
> + else if (bit (thumb_insn_r->arm_insn, 11))
> + {
> + /* Handle load from literal pool. */
> + /* LDR(3). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode1)
> + {
> + opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
> + opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if ((3 == opcode2) && (!opcode3))
> + {
> + /* Branch with exchange. */
> + record_buf[0] = ARM_PS_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + 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;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Format 5; data processing insns. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if (bit (thumb_insn_r->arm_insn, 7))
> + {
> + reg_src1 = reg_src1 + 8;
> + }
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (opcode)
> + {
> + /* LDR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* STR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_regval + (immed_5 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (3 == opcode)
> + {
> + /* LDR(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == opcode)
> + {
> + /* LDRH(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* STR(3). */
> + immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
> + , &u_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_regval + (immed_8 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + else if (0 == opcode)
> + {
> + /* STRH(1). */
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval);
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = u_regval + (immed_5 * 2);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_record_misc (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> + uint32_t reg_src1;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count + 2;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
> + , &u_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_regval - \
> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn. */
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* According to high vector configuration PC is set. */
> + /* FIX ME ? what if user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* Save SPSR also;how?. */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb_insn_r->arm_insn,
> + paddress (thumb_insn_r->gdbarch,
> thumb_insn_r->this_addr));
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> + {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t ret = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + ULONGEST u_regval = 0;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count + 1;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + ret = tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B (1), conditional branch is automatically taken care in process_record,
> + as PC is saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return ret;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_record_branch (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t bits_h = 0;
> +
> + bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (2 == bits_h || 3 == bits_h)
> + {
> + /* BL */
> + record_buf[0] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == bits_h)
> + {
> + /* BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + /* B(2) is automatically taken care in process_record, as PC is saved
> + there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> + uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction. */
> + static int (*const arm_handle_insn[8])
> + (insn_decode_record*) =
> + {
> + arm_record_data_proc_misc_ld_str, /* 000. */
> + arm_record_data_proc_imm, /* 001. */
> + arm_record_ld_st_imm_offset, /* 010. */
> + arm_record_ld_st_reg_offset, /* 011. */
> + arm_record_ld_st_multiple, /* 100. */
> + arm_record_b_bl, /* 101. */
> + arm_record_coproc, /* 110. */
> + arm_record_coproc_data_proc /* 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction. */
> + static int (*const thumb_handle_insn[8])
> + (insn_decode_record*) =
> + { \
> + thumb_record_shift_add_sub, /* 000. */
> + thumb_record_add_sub_cmp_mov, /* 001. */
> + thumb_record_ld_st_reg_offset, /* 010. */
> + thumb_record_ld_st_imm_offset, /* 011. */
> + thumb_record_ld_st_stack, /* 100. */
> + thumb_record_misc, /* 101. */
> + thumb_record_ldm_stm_swi, /* 110. */
> + thumb_record_branch /* 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_RECORD == record_type)
> + {
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
> + arm_record->cond = bits (arm_record->arm_insn, 28, 31);
> + insn_id = bits (arm_record->arm_insn, 25, 27);
> + arm_record_extension_space (arm_record);
> + /* if this insn has fallen into extension space then we need
> not decode it anymore. */
> + if (!INSN_RECORDED(arm_record))
> + {
> + arm_handle_insn[insn_id] (arm_record);
> + }
> + }
> + else if (THUMB_RECORD == record_type)
> + {
> + /* As thumb does not have condition codes, we set negative. */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order
> (arm_record->gdbarch));
> + insn_id = bits (arm_record->arm_insn, 13, 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_RECORD == record_type)
> + {
> + printf_unfiltered (_("Process record doesnt support thumb32 instruction "
> + "0x%0x at address %s.\n"),
> + arm_record->arm_insn,
> + paddress (arm_record->gdbarch,
> arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to "record_arch_list".
> + Return -1 if something is wrong. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0, insn_id = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + insn_decode_record arm_record;
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one. */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
> + , &u_regval);
> +
> + if (!(u_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + insn_id = bits (arm_record.arm_insn, 11, 15);
> + /* is it thumb2 insn? */
> + if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
> + {
> + ret = decode_insn (&arm_record, THUMB2_RECORD,
> THUMB_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_RECORD,
> THUMB2_INSN_SIZE_BYTES);
> + }
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_reg (arm_record.regcache \
> + , (arm_record.arm_regs[no_of_rec])))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> + arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
> +++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
> @@ -201,6 +201,9 @@
> /* Return the expected next PC if FRAME is stopped at a syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
> /* Structures used for displaced stepping. */
> @@ -331,6 +334,8 @@
> instruction? */
> extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> + struct regcache *regcache, CORE_ADDR addr);
> /* Functions exported from armbsd-tdep.h. */
>
> /* Return the appropriate register set for the core section identified
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-09 6:08 ` oza Pawandeep
2011-11-17 9:24 ` oza Pawandeep
@ 2011-11-17 20:40 ` Tom Tromey
2011-11-18 3:18 ` oza Pawandeep
2011-11-19 9:43 ` oza Pawandeep
1 sibling, 2 replies; 128+ messages in thread
From: Tom Tromey @ 2011-11-17 20:40 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
oza> please find the latest patch below.
No ChangeLog entry.
No NEWS entry.
Patch got mangled by your mailer again.
oza> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
Wrong spacing.
oza> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
Likewise.
oza> +}arm_record_strx_t;
Spacing.
oza> +}record_type_t;
Again.
oza> +
oza> +static int
oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
oza> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
Indentation.
oza> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
Too many parens.
oza> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
Again.
oza> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
oza> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
Again, plus indentation.
oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
oza> + , &u_regval[0]);
Formatting -- "," is on the wrong line.
I see most of these issues multiple times. Please go over the entire
patch and fix them all. I feel like I asked this before.
oza> + /* FIX ME: How to read SPSR value? */
We try not to put FIXME comments into new code.
Nobody ever fixes them.
You can just write an informative comment instead: "We have no way to
read the SPSR value". Assuming that is accurate.
The enclosing function, arm_record_extension_space, takes care to return
a value, but (1) the meaning of the return value is not documented in
the function's introductory comment (this problems affects many of the
new functions), and (2) the only caller does not check it.
What happens if the user hits an instruction which is not handled?
Right now a message is printed. But shouldn't it abort the operation in
some other way? That is, is emitting a message really sufficient?
oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
oza> dispatch it. */
oza> +
oza> +static int
oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
oza> + uint32_t insn_size)
E.g., here the return value should be documented.
oza> + static int (*const arm_handle_insn[8])
oza> + (insn_decode_record*) =
Formatting looks weird.
A typedef for the function type would probably make this look less
strange.
oza> + /* if this insn has fallen into extension space then we need
oza> not decode it anymore. */
oza> + if (!INSN_RECORDED(arm_record))
oza> + {
oza> + arm_handle_insn[insn_id] (arm_record);
... it seems like there should be a check of the return value here.
I don't understand this.
oza> + if (record_arch_list_add_mem \
No need for this backslash.
oza> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
oza> + arm_record.arm_mems[no_of_rec].len))
Really messed up formatting.
oza> + if (arm_record.arm_regs)
oza> + xfree (arm_record.arm_regs);
oza> + if (arm_record.arm_mems)
oza> + xfree (arm_record.arm_mems);
This is fine as long as you have proved that nothing in any possible
call path here can throw an exception. If anything throws an exception,
then you are leaking memory and should instead use a cleanup.
oza> + /* Parse swi insn args, sycall record. */
oza> + int (*arm_swi_record) (struct regcache *regcache);
Since this is only used in your Phase 3 patch, it belongs there.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-17 20:40 ` Tom Tromey
@ 2011-11-18 3:18 ` oza Pawandeep
2011-11-18 17:22 ` Tom Tromey
2011-11-19 9:43 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-18 3:18 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
Thanks for the comments. I am confused over formatting and I have been
trying to fix all the time but it always falls apart.
what I have been doing is:
change the code in windows,
and then take it to linux.
make sure it compiles.
then edit it in xemacs editor.
make the formatting right.
then use diff -urN command to get diff.
open the diff file in xemacs (here also again I see some formatting problems)
and then from linux I open google and paste everything.
but when I check the sent mail in yahoo, some formatting seem to be lost.
I have no idea what is the best way to maintain formatting right from
the editing of file to the diff of files to the mails.
Regards,
Oza.
On Fri, Nov 18, 2011 at 1:10 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the latest patch below.
>
> No ChangeLog entry.
>
> No NEWS entry.
>
> Patch got mangled by your mailer again.
>
> oza> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>
> Wrong spacing.
>
> oza> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>
> Likewise.
>
> oza> +}arm_record_strx_t;
>
> Spacing.
>
> oza> +}record_type_t;
>
> Again.
>
> oza> +
> oza> +static int
> oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> oza> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
>
> Indentation.
>
> oza> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>
> Too many parens.
>
> oza> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>
> Again.
>
> oza> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> oza> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>
> Again, plus indentation.
>
> oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
> oza> + , &u_regval[0]);
>
> Formatting -- "," is on the wrong line.
>
> I see most of these issues multiple times. Please go over the entire
> patch and fix them all. I feel like I asked this before.
>
> oza> + /* FIX ME: How to read SPSR value? */
>
> We try not to put FIXME comments into new code.
> Nobody ever fixes them.
>
> You can just write an informative comment instead: "We have no way to
> read the SPSR value". Assuming that is accurate.
>
> The enclosing function, arm_record_extension_space, takes care to return
> a value, but (1) the meaning of the return value is not documented in
> the function's introductory comment (this problems affects many of the
> new functions), and (2) the only caller does not check it.
>
> What happens if the user hits an instruction which is not handled?
> Right now a message is printed. But shouldn't it abort the operation in
> some other way? That is, is emitting a message really sufficient?
>
> oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> oza> dispatch it. */
> oza> +
> oza> +static int
> oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> oza> + uint32_t insn_size)
>
> E.g., here the return value should be documented.
>
> oza> + static int (*const arm_handle_insn[8])
> oza> + (insn_decode_record*) =
>
> Formatting looks weird.
> A typedef for the function type would probably make this look less
> strange.
>
> oza> + /* if this insn has fallen into extension space then we need
> oza> not decode it anymore. */
> oza> + if (!INSN_RECORDED(arm_record))
> oza> + {
> oza> + arm_handle_insn[insn_id] (arm_record);
>
> ... it seems like there should be a check of the return value here.
> I don't understand this.
>
> oza> + if (record_arch_list_add_mem \
>
> No need for this backslash.
>
> oza> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> oza> + arm_record.arm_mems[no_of_rec].len))
>
> Really messed up formatting.
>
> oza> + if (arm_record.arm_regs)
> oza> + xfree (arm_record.arm_regs);
> oza> + if (arm_record.arm_mems)
> oza> + xfree (arm_record.arm_mems);
>
> This is fine as long as you have proved that nothing in any possible
> call path here can throw an exception. If anything throws an exception,
> then you are leaking memory and should instead use a cleanup.
>
> oza> + /* Parse swi insn args, sycall record. */
> oza> + int (*arm_swi_record) (struct regcache *regcache);
>
> Since this is only used in your Phase 3 patch, it belongs there.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-18 3:18 ` oza Pawandeep
@ 2011-11-18 17:22 ` Tom Tromey
0 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-11-18 17:22 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
Oza> Thanks for the comments. I am confused over formatting and I have been
Oza> trying to fix all the time but it always falls apart.
Yeah, it is a bit of a pain. I wish we had a tool that could reformat
the code according to our standards. Then we would basically never have
to review the formatting.
Oza> change the code in windows,
Oza> and then take it to linux.
Oza> make sure it compiles.
Oza> then edit it in xemacs editor.
Oza> make the formatting right.
Ouch! That sounds quite painful.
I try to do the formatting correctly from the start.
Doing it later is too error-prone.
Oza> I have no idea what is the best way to maintain formatting right from
Oza> the editing of file to the diff of files to the mails.
Me neither, sorry. It depends on the mailer.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-17 20:40 ` Tom Tromey
2011-11-18 3:18 ` oza Pawandeep
@ 2011-11-19 9:43 ` oza Pawandeep
2011-11-19 11:39 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-19 9:43 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
I have fixed most of your comments.
as far as formatting is concerned, I am still trying to hard to get it
right. but at the end mailer ends up messing it up :(
following are the comments.
We try not to put FIXME comments into new code.
Nobody ever fixes them.
You can just write an informative comment instead: "We have no way to
read the SPSR value". Assuming that is accurate.
Oza >> removed FIX ME comments and put appropriate comments.
The enclosing function, arm_record_extension_space, takes care to return
a value, but (1) the meaning of the return value is not documented in
the function's introductory comment (this problems affects many of the
new functions), and (2) the only caller does not check it.
oza >> thanks for pointing that out, I have added descirption and
caler must be checking return value which I have corrected.
What happens if the user hits an instruction which is not handled?
Right now a message is printed. But shouldn't it abort the operation in
some other way? That is, is emitting a message really sufficient?
Oza >> I have chaged the description a bit, the abort message is
printed, but at the same time return value is -1, which will cause gdb
standard stack unwinding, with error(...) symentics.
Formatting looks weird.
A typedef for the function type would probably make this look less
strange.
oza >> converted to typedef defination, it looks simpler now.
No need for this backslash.
Oza >> removed.
oza> + if (arm_record.arm_regs)
oza> + xfree (arm_record.arm_regs);
oza> + if (arm_record.arm_mems)
oza> + xfree (arm_record.arm_mems);
This is fine as long as you have proved that nothing in any possible
call path here can throw an exception. If anything throws an exception,
then you are leaking memory and should instead use a cleanup.
Oza >> I have added a new function deallocate_reg_arm....
the design is in such a way, that any function goes for allocation
until and unless it supports the insn; otherwise memory is always
local/cache, so in case of exception it simply unwinds wihtout
affecting dymanic memory.
and in case we have allocated memory, we make sure that we come to the
end of the process_record funntion and we free them irrespective of
success or failure;
oza> + /* Parse swi insn args, sycall record. */
oza> + int (*arm_swi_record) (struct regcache *regcache);
Since this is only used in your Phase 3 patch, it belongs there.
Oza >> In my thinking, it was necessary to add this function pointer
because I had already added logic of decoding insn in phase 2, where I
am just checking if this fp is NULL.
where this fp was initialised to NULL, which will be replaced with
valid fp in phase 3.
wihtout including this, phase 2 would have missed on insn decoding.
Regards,
Oza.
On Fri, Nov 18, 2011 at 2:10 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the latest patch below.
>
> No ChangeLog entry.
>
> No NEWS entry.
>
> Patch got mangled by your mailer again.
>
> oza> + memcpy(®S[0],&RECORD_BUF[0],sizeof(uint32_t)*LENGTH); \
>
> Wrong spacing.
>
> oza> + memcpy(&MEMS->len,&RECORD_BUF[0],sizeof(struct arm_mem_r) * LENGTH); \
>
> Likewise.
>
> oza> +}arm_record_strx_t;
>
> Spacing.
>
> oza> +}record_type_t;
>
> Again.
>
> oza> +
> oza> +static int
> oza> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> oza> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
>
> Indentation.
>
> oza> + if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
>
> Too many parens.
>
> oza> + else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
>
> Again.
>
> oza> + else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
> oza> + || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
>
> Again, plus indentation.
>
> oza> + regcache_raw_read_unsigned (reg_cache, reg_src1
> oza> + , &u_regval[0]);
>
> Formatting -- "," is on the wrong line.
>
> I see most of these issues multiple times. Please go over the entire
> patch and fix them all. I feel like I asked this before.
>
> oza> + /* FIX ME: How to read SPSR value? */
>
> We try not to put FIXME comments into new code.
> Nobody ever fixes them.
>
> You can just write an informative comment instead: "We have no way to
> read the SPSR value". Assuming that is accurate.
>
> The enclosing function, arm_record_extension_space, takes care to return
> a value, but (1) the meaning of the return value is not documented in
> the function's introductory comment (this problems affects many of the
> new functions), and (2) the only caller does not check it.
>
> What happens if the user hits an instruction which is not handled?
> Right now a message is printed. But shouldn't it abort the operation in
> some other way? That is, is emitting a message really sufficient?
>
> oza> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> oza> dispatch it. */
> oza> +
> oza> +static int
> oza> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> oza> + uint32_t insn_size)
>
> E.g., here the return value should be documented.
>
> oza> + static int (*const arm_handle_insn[8])
> oza> + (insn_decode_record*) =
>
> Formatting looks weird.
> A typedef for the function type would probably make this look less
> strange.
>
> oza> + /* if this insn has fallen into extension space then we need
> oza> not decode it anymore. */
> oza> + if (!INSN_RECORDED(arm_record))
> oza> + {
> oza> + arm_handle_insn[insn_id] (arm_record);
>
> ... it seems like there should be a check of the return value here.
> I don't understand this.
>
> oza> + if (record_arch_list_add_mem \
>
> No need for this backslash.
>
> oza> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> oza> + arm_record.arm_mems[no_of_rec].len))
>
> Really messed up formatting.
>
> oza> + if (arm_record.arm_regs)
> oza> + xfree (arm_record.arm_regs);
> oza> + if (arm_record.arm_mems)
> oza> + xfree (arm_record.arm_mems);
>
> This is fine as long as you have proved that nothing in any possible
> call path here can throw an exception. If anything throws an exception,
> then you are leaking memory and should instead use a cleanup.
>
> oza> + /* Parse swi insn args, sycall record. */
> oza> + int (*arm_swi_record) (struct regcache *regcache);
>
> Since this is only used in your Phase 3 patch, it belongs there.
>
> Tom
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-19 9:43 ` oza Pawandeep
@ 2011-11-19 11:39 ` oza Pawandeep
2011-12-02 18:36 ` Tom Tromey
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-11-19 11:39 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
please find the updated patch; I have tried my level best to take care
the most to get formatting right.
And also, all extra parentheses removed.
please have a look. (hope mailer does not do anything)
PATCH STARTS
------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-07-28 09:41:06.000000000 +0530
@@ -1025,6 +1025,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1054,6 +1057,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.c 2011-11-19 16:57:58.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -8821,3 +8823,2060 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0],
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != ARM_RECORD->reg_rec_count) || 0 != ARM_RECORD->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ /* handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* we dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode) || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode) || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode) || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode) || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode) || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode) || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1
+ , &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
+ , &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ And dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ xtension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM
+ , &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM
+ , &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* we need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == record_type)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ 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))
+ {
+ arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* cleans up local record registers and memory allocations. */
+void deallocate_reg_mem(insn_decode_record *record)
+{
+ if (record->arm_regs)
+ xfree (record->arm_regs);
+ if (record->arm_mems)
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM
+ , &u_regval);
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
THUMB_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-07-28 09:40:19.000000000 +0530
+++ arm_new/arm-tdep.h 2011-07-28 09:41:06.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -331,6 +334,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-11-19 11:39 ` oza Pawandeep
@ 2011-12-02 18:36 ` Tom Tromey
2011-12-03 8:20 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-12-02 18:36 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
oza> please find the updated patch; I have tried my level best to take care
oza> the most to get formatting right.
oza> And also, all extra parentheses removed.
Thanks.
oza> please have a look. (hope mailer does not do anything)
Your mailer is still screwed up.
You didn't write a ChangeLog entry or a NEWS entry.
Please do this. I have asked at least once now. These are just
baseline things for getting patches into gdb; if you don't respond to
these requests it makes me tend to prioritize other patches over yours.
FYI.
oza> + /* if this insn has fallen into extension space
oza> + then we need not decode it anymore. */
oza> + if (ret != -1 && !INSN_RECORDED(arm_record))
oza> + {
oza> + arm_handle_insn[insn_id] (arm_record);
Still not checking the return value.
oza> +/* cleans up local record registers and memory allocations. */
Should start with a capital letter.
Blank line between comment and function.
oza> +void deallocate_reg_mem(insn_decode_record *record)
Newline after void.
Space before open paren.
oza> +{
oza> + if (record->arm_regs)
oza> + xfree (record->arm_regs);
oza> + if (record->arm_mems)
oza> + xfree (record->arm_mems);
oza> +}
You can call xfree on a NULL pointer. Just remove those ifs.
oza> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
oza> no_of_rec++)
oza> + {
Brace indentation looks wrong.
There are still other minor formatting issues. I saw 21 places where
there is a comma at the start of a line, please fix all of these.
I think there were some other problems, too, but at this point I have
stopped caring.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-02 18:36 ` Tom Tromey
@ 2011-12-03 8:20 ` oza Pawandeep
2011-12-03 14:18 ` oza Pawandeep
` (2 more replies)
0 siblings, 3 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 8:20 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
Thanks for the comments.
1) I have been trying to fix all formatting, it looks better now and
fixed all comments you had.
I am sorry that on formatting both of our efforts are going;
excuse me as every time mailer spoils the things; probably copy from
xemacs editor to chrome/firefox in plain text and the other mailer
gets it. though I am not sure.
2) I could not write changelog entry because I have been getting
commments, and moreover I was not sure whether I should get changelog
entry from latest gdb 7.3 or latest current working version of gdb ? I
think later is true in my understanding.
I will include changelog this time; sorry for having you point it out
in all reviews.
3) will post the latest patch, with possible correction of formatting
issues; and will include changelog from current branch.
Regards,
Oza.
On Sat, Dec 3, 2011 at 12:06 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> please find the updated patch; I have tried my level best to take care
> oza> the most to get formatting right.
> oza> And also, all extra parentheses removed.
>
> Thanks.
>
> oza> please have a look. (hope mailer does not do anything)
>
> Your mailer is still screwed up.
>
> You didn't write a ChangeLog entry or a NEWS entry.
> Please do this. I have asked at least once now. These are just
> baseline things for getting patches into gdb; if you don't respond to
> these requests it makes me tend to prioritize other patches over yours.
> FYI.
>
> oza> + /* if this insn has fallen into extension space
> oza> + then we need not decode it anymore. */
> oza> + if (ret != -1 && !INSN_RECORDED(arm_record))
> oza> + {
> oza> + arm_handle_insn[insn_id] (arm_record);
>
> Still not checking the return value.
>
> oza> +/* cleans up local record registers and memory allocations. */
>
> Should start with a capital letter.
> Blank line between comment and function.
>
> oza> +void deallocate_reg_mem(insn_decode_record *record)
>
> Newline after void.
> Space before open paren.
>
> oza> +{
> oza> + if (record->arm_regs)
> oza> + xfree (record->arm_regs);
> oza> + if (record->arm_mems)
> oza> + xfree (record->arm_mems);
> oza> +}
>
> You can call xfree on a NULL pointer. Just remove those ifs.
>
> oza> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
> oza> no_of_rec++)
> oza> + {
>
> Brace indentation looks wrong.
>
> There are still other minor formatting issues. I saw 21 places where
> there is a comma at the start of a line, please fix all of these.
> I think there were some other problems, too, but at this point I have
> stopped caring.
>
> Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 8:20 ` oza Pawandeep
@ 2011-12-03 14:18 ` oza Pawandeep
2011-12-03 16:32 ` Petr Hluzín
2011-12-03 15:06 ` oza Pawandeep
2011-12-20 19:05 ` Tom Tromey
2 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 14:18 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
please find the updated patch below.
note: have derived this patch and Changelog from gdb-7.3.50.20111203.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-03 18:10:34.000000000 +0530
@@ -1,3 +1,8 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+ * arm-linux-tdep.c: Added arm-reversible and process record
+ * arm-tdep.c: arm-reversible-debugging implementation
+ * arm-tdep.h: arm-reversible data structures
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-03 17:52:28.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2041 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != ARM_RECORD->reg_rec_count || 0 != ARM_RECORD->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == record_type)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ ARM_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
THUMB_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 14:18 ` oza Pawandeep
@ 2011-12-03 16:32 ` Petr Hluzín
2011-12-03 18:46 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-12-03 16:32 UTC (permalink / raw)
To: oza Pawandeep; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa
I did not review the 2011-11-19 nor 2011-11-09 patch.
Tom:
> Yeah, it is a bit of a pain. I wish we had a tool that could reformat
> the code according to our standards.
I guess 'indent' could do that. Its default settings formats using GNU
guidelines.
Some editors can be configured to automatically format new lines and
have a button to reformat existing lines. I suppose no editor can
autodetect the style from file yet.
Review of the 2011-11-03 patch:
In arm_process_record():
Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
of `arm_record.arm_insn'
which is always zero. When you moved the test from decode_insn() I
guess forgot to copy these lines:
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));
Remaining from previous reviews:
Macro INSN_RECORDED:
I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
Tromey did not comment on that, Oza left the name as is. Well, it is
not a big deal.
However arguments of macros should be surrounded by parentheses - like this:
(ARM_RECORD)->reg_rec_count
This is necessary if INSN_RECORDED() is passed more complex expression
when the order of evaluation matters. This is a common C issue and
customary solution, it is not GDB specific.
> Petr >>In arm_record_strx()
> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>
> because calling function takes care of REG_ALLOC routine calls.
> I did not want ALLOC calls to be scattered into any other function
> other than main decoding functions.
The lines can be converted from `*(record_buf_mem + 1)' to
`record_buf_mem[1]' with no changes to REG_ALLOC() calls. The
allocation calls would remain unscattered in main decoding functions.
The code is correct, but I do not understand why you use the unusual
syntax.
Have you considered adding the assertions I suggested in [2]? They are
not necessary but they improve understanding of code.
[2] http://sourceware.org/ml/gdb-patches/2011-10/msg00617.html
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 16:32 ` Petr Hluzín
@ 2011-12-03 18:46 ` oza Pawandeep
2011-12-03 19:02 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 18:46 UTC (permalink / raw)
To: Petr Hluzín; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa
Hi Petr,
I have updated the patch with your comments; please find the explanation below.
> In arm_process_record():
> Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
> of `arm_record.arm_insn'
> which is always zero. When you moved the test from decode_insn() I
> guess forgot to copy these lines:
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer
> (&u_buf.buf[0],
> + THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));
>
>
Oza : done, corrected, thanks for this comment.
> Macro INSN_RECORDED:
> I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
> Tromey did not comment on that, Oza left the name as is. Well, it is
> not a big deal.
> However arguments of macros should be surrounded by parentheses - like this:
> (ARM_RECORD)->reg_rec_count
> This is necessary if INSN_RECORDED() is passed more complex expression
> when the order of evaluation matters. This is a common C issue and
> customary solution, it is not GDB specific.
Oza: have taken care of parenthesis stuff and added; and comment is
also added to make it more clear.
>> Petr >>In arm_record_strx()
>> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>>
>> because calling function takes care of REG_ALLOC routine calls.
>> I did not want ALLOC calls to be scattered into any other function
>> other than main decoding functions.
oza: Ahhhh.....I got you now; I have changed, but personally my coding
style have never let me think that pointer style is unusual as
pointers make the things more clear in my mind. because it always
reminds me when i look at the code after a long time that I am playing
with address : ) [of course your array syntax is also nothing but
address, but probably its just my mind thinks that way)
I have changed it as you suggested.
>
> Have you considered adding the assertions I suggested in [2]? They are
> not necessary but they improve understanding of code.
Oza: yes I have added assert as you suggested.
arm_record_extension_space already returns positive/negative value
and decode_insn already catching the return value, and one more point
is some insns may not be supported so in that case the code must reach
back to process_record and its caller to throw correct record error.
PS: next mail will contain the latest patch
Regards,
Oza.
On Sat, Dec 3, 2011 at 10:01 PM, Petr Hluzín <petr.hluzin@gmail.com> wrote:
> I did not review the 2011-11-19 nor 2011-11-09 patch.
>
> Tom:
>> Yeah, it is a bit of a pain. I wish we had a tool that could reformat
>> the code according to our standards.
>
> I guess 'indent' could do that. Its default settings formats using GNU
> guidelines.
> Some editors can be configured to automatically format new lines and
> have a button to reformat existing lines. I suppose no editor can
> autodetect the style from file yet.
>
>
> Review of the 2011-11-03 patch:
>
> In arm_process_record():
> Expression `insn_id = bits (arm_record.arm_insn, 11, 15);' uses value
> of `arm_record.arm_insn'
> which is always zero. When you moved the test from decode_insn() I
> guess forgot to copy these lines:
> + arm_record->arm_insn = (uint32_t) extract_unsigned_integer
> (&u_buf.buf[0],
> + THUMB_INSN_SIZE_BYTES, gdbarch_byte_order (arm_record->gdbarch));
>
>
> Remaining from previous reviews:
>
> Macro INSN_RECORDED:
> I suggested INSN_IS_RECORDED to make it clear it is boolean, Tom
> Tromey did not comment on that, Oza left the name as is. Well, it is
> not a big deal.
> However arguments of macros should be surrounded by parentheses - like this:
> (ARM_RECORD)->reg_rec_count
> This is necessary if INSN_RECORDED() is passed more complex expression
> when the order of evaluation matters. This is a common C issue and
> customary solution, it is not GDB specific.
>
>> Petr >>In arm_record_strx()
>> Petr >>Why don't you use `record_buf_mem[0]' and `record_buf_mem[1]' syntax?
>>
>> because calling function takes care of REG_ALLOC routine calls.
>> I did not want ALLOC calls to be scattered into any other function
>> other than main decoding functions.
>
> The lines can be converted from `*(record_buf_mem + 1)' to
> `record_buf_mem[1]' with no changes to REG_ALLOC() calls. The
> allocation calls would remain unscattered in main decoding functions.
> The code is correct, but I do not understand why you use the unusual
> syntax.
>
> Have you considered adding the assertions I suggested in [2]? They are
> not necessary but they improve understanding of code.
>
> [2] http://sourceware.org/ml/gdb-patches/2011-10/msg00617.html
>
> --
> Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 18:46 ` oza Pawandeep
@ 2011-12-03 19:02 ` oza Pawandeep
2011-12-03 20:30 ` Petr Hluzín
2011-12-04 1:47 ` Yao Qi
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 19:02 UTC (permalink / raw)
To: Petr Hluzín; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa
Hi Tom and Petr,
This patch includes both of your comments; I have worked both on
formatting and comments, and try to make the patch look ok.
the patch is derived from gdb-7.3.50.20111203 current snapshot.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-03 19:48:56.000000000 +0530
@@ -1,3 +1,9 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c: Added arm-reversible and process record
+ * arm-tdep.c: arm-reversible-debugging implementation
+ * arm-tdep.h: arm-reversible data structures
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-03 22:11:33.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2053 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == record_type)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ ARM_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ struct
+ {
+ gdb_byte buf[2];
+ } u_buf;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+ arm_record.arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record.gdbarch));
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 19:02 ` oza Pawandeep
@ 2011-12-03 20:30 ` Petr Hluzín
[not found] ` <1322975560.12415.YahooMailNeo@web112518.mail.gq1.yahoo.com>
2011-12-04 1:47 ` Yao Qi
1 sibling, 1 reply; 128+ messages in thread
From: Petr Hluzín @ 2011-12-03 20:30 UTC (permalink / raw)
To: oza Pawandeep; +Cc: Tom Tromey, paawan oza, gdb-patches, chandra krishnappa
On 3 December 2011 20:01, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Tom and Petr,
>
> This patch includes both of your comments; I have worked both on
> formatting and comments, and try to make the patch look ok.
> the patch is derived from gdb-7.3.50.20111203 current snapshot.
>
In function decode_insn:
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
I wonder why is there a `struct u_buf'. Having local variable
`buf[insn_size];' would be sufficient and obvious. I am sorry to not
discover that earlier. The same thing applies to arm_process_record().
In arm_process_record ()
> +
> + struct
> + {
> + gdb_byte buf[2];
> + } u_buf;
> +
> + ...
> +
> + arm_record.arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0],
> + THUMB_INSN_SIZE_BYTES ,
> + gdbarch_byte_order (arm_record.gdbarch));
Well, when I said that you probably forgot to copy
extract_unsigned_integer() I should have also said that you should
have also copied the line
target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size)
Right now extract_unsigned_integer() reads an uninitialized buffer. :-T
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 19:02 ` oza Pawandeep
2011-12-03 20:30 ` Petr Hluzín
@ 2011-12-04 1:47 ` Yao Qi
2011-12-04 8:26 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04 1:47 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
On 12/04/2011 03:01 AM, oza Pawandeep wrote:
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog 2011-12-03 19:48:56.000000000 +0530
> @@ -1,3 +1,9 @@
> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
> +
> + * arm-linux-tdep.c: Added arm-reversible and process record
> + * arm-tdep.c: arm-reversible-debugging implementation
> + * arm-tdep.h: arm-reversible data structures
> +
ChangeLog like this is not accurate to reflect your changes. "Add
reverse debugging and process record for ARM" is sort of summary of your
patch, but in ChangeLog, we usually need more details on function level.
Please read other ChangeLog entries in ChangeLog, and see how it is
written. Or, you can read this
http://www.gnu.org/prep/standards/standards.html#Change-Logs
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 1:47 ` Yao Qi
@ 2011-12-04 8:26 ` oza Pawandeep
2011-12-04 11:33 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04 8:26 UTC (permalink / raw)
To: Yao Qi
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
Hi Yao and Tom,
please have a look at sample changlog below.
let me know whether this much detailed explanation is sufficient ?
2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
* arm-linux-tdep.c: arm_linux_init_abi modified to include
arm reversible debugging feature.
registered arm_process_record to gdb_arch
syscall pointer initialization.
* arm-tdep.c: arm-reversible-debugging implementation.
newly added functions are as follows.
> arm_process_record: handles basic initialization and record
summarisation, decodes basic insn ids, on which it hands over
controls to decode_insn.
> deallocate_reg_mem : clean up function
> decode_insn: Decodes arm/thumb insn and calls appropriate
decoding routine to record the change.
> thumb_record_branch: branch insn reording (thumb)
> thumb_record_ldm_stm_swi: load, store and sycall insn
recoding (thumb)
> thumb_record_misc: misc insn recording (thumb)
> thumb_record_ld_st_stack: store and stack insn recording (thumb)
> thumb_record_ld_st_imm_offset: load, store with immediate offset
insn recording (thumb)
> thumb_record_ld_st_reg_offset: load, store with register offset
recording (thumb)
> thumb_record_add_sub_cmp_mov: addition, subtractation, compare
and move insn recording (thumb)
> thumb_record_shift_add_sub: shift, add and sub insn recording
(thumb)
> arm_record_coproc_data_proc: coprocessor and data processing
recording (partially implemented) (arm)
> arm_record_coproc: coprocessor insn recording
(partially implemented) (arm)
> arm_record_b_bl: branch insn recording (arm)
> arm_record_ld_st_multiple: load and store multiple insn recording
(arm)
> arm_record_ld_st_reg_offset: load and store reg offset recording
(arm)
> arm_record_ld_st_imm_offset: load and store immediate offset
recording (arm)
> arm_record_data_proc_imm: data processing insn recording (arm)
> arm_record_data_proc_misc_ld_str: data processing, misc, load and
store insn recording (arm)
> arm_record_extension_space:arm extension space insn recording
(arm)
> arm_record_strx: str(X) type insn recording (arm)
> sbo_sbz: checks for mendatory sbo and sbz fields in insn,
added new data structures:
> insn_decode_record_t: local record structure which contains insn's
record, which includes both reg and memory.
REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
in local record which is finally processed by arm_rocess_record.
* arm-tdep.h: arm-reversible data structures
> modified gdbarch_tdep: added member (function pointer) arm_swi_record
which is supposed to be recording system calls
> arm_process_record externed.
Regards,
Oza.
On Sun, Dec 4, 2011 at 7:16 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 12/04/2011 03:01 AM, oza Pawandeep wrote:
>> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
>> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
>> +++ arm_new/ChangeLog 2011-12-03 19:48:56.000000000 +0530
>> @@ -1,3 +1,9 @@
>> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
>> +
>> + * arm-linux-tdep.c: Added arm-reversible and process record
>> + * arm-tdep.c: arm-reversible-debugging implementation
>> + * arm-tdep.h: arm-reversible data structures
>> +
>
> ChangeLog like this is not accurate to reflect your changes. "Add
> reverse debugging and process record for ARM" is sort of summary of your
> patch, but in ChangeLog, we usually need more details on function level.
>
> Please read other ChangeLog entries in ChangeLog, and see how it is
> written. Or, you can read this
>
> http://www.gnu.org/prep/standards/standards.html#Change-Logs
>
> --
> Yao (齐尧)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 8:26 ` oza Pawandeep
@ 2011-12-04 11:33 ` oza Pawandeep
2011-12-04 13:29 ` Petr Hluzín
2011-12-04 14:46 ` Yao Qi
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04 11:33 UTC (permalink / raw)
To: Yao Qi, Petr Hluzín, Tom Tromey
Cc: paawan oza, gdb-patches, chandra krishnappa
Hi,
Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
Change log is elaborated; I am looking forwarding to adding more
details if need. seeking for your feedback on the same.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-04 16:45:00.000000000 +0530
@@ -1,3 +1,65 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c: arm_linux_init_abi modified to include
+ arm reversible debugging feature.
+ registered arm_process_record to gdb_arch
+ syscall pointer initialization.
+
+ * arm-tdep.c: arm-reversible-debugging implementation.
+ newly added functions are as follows.
+
+ > arm_process_record: handles basic initialization and record
+ summarisation, decodes basic insn ids, on which it hands over
+ controls to decode_insn.
+ > deallocate_reg_mem : clean up function
+ > decode_insn: Decodes arm/thumb insn and calls appropriate
+ decoding routine to record the change.
+ > thumb_record_branch: branch insn reording (thumb)
+ > thumb_record_ldm_stm_swi: load, store and sycall insn
+ recoding (thumb)
+ > thumb_record_misc: misc insn recording (thumb)
+ > thumb_record_ld_st_stack: store and stack insn recording (thumb)
+ > thumb_record_ld_st_imm_offset: load, store with immediate offset
+ insn recording (thumb)
+ > thumb_record_ld_st_reg_offset: load, store with register offset
+ recording (thumb)
+ > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
+ and move insn recording (thumb)
+ > thumb_record_shift_add_sub: shift, add and sub insn recording
+ (thumb)
+ > arm_record_coproc_data_proc: coprocessor and data processing
+ recording (partially implemented) (arm)
+ > arm_record_coproc: coprocessor insn recording
+ (partially implemented) (arm)
+ > arm_record_b_bl: branch insn recording (arm)
+ > arm_record_ld_st_multiple: load and store multiple insn recording
+ (arm)
+ > arm_record_ld_st_reg_offset: load and store reg offset recording
+ (arm)
+ > arm_record_ld_st_imm_offset: load and store immediate offset
+ recording (arm)
+ > arm_record_data_proc_imm: data processing insn recording (arm)
+ > arm_record_data_proc_misc_ld_str: data processing, misc, load and
+ store insn recording (arm)
+ > arm_record_extension_space:arm extension space insn recording
+ (arm)
+ > arm_record_strx: str(X) type insn recording (arm)
+ > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
+
+ added new data structures:
+ > insn_decode_record_t: local record structure which contains insn's
+ record, which includes both reg and memory.
+
+ REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
+ in local record which is finally processed by arm_rocess_record.
+
+ * arm-tdep.h: arm-reversible data structures
+
+ > modified gdbarch_tdep: added member (function pointer) arm_swi_record
+ which is supposed to be recording system calls
+ > arm_process_record externed.
+
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-04 13:02:15.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
0 on success
+and positive val on fauilure. */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+ gdb_byte buf[insn_size];
+
+ memset (&buf[0], 0, insn_size);
+
+ if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+ return 1;
+ insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size,
+ gdbarch_byte_order (insn_record->gdbarch));
+ return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ uint32_t ret = 0; /* return value: negative>failure 0>success. */
+ uint32_t insn_id = 0;
+
+ if (extract_arm_insn (arm_record, insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ if (extract_arm_insn (&arm_record, 2))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
+ return -1;
+ }
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 11:33 ` oza Pawandeep
@ 2011-12-04 13:29 ` Petr Hluzín
2011-12-04 14:46 ` Yao Qi
1 sibling, 0 replies; 128+ messages in thread
From: Petr Hluzín @ 2011-12-04 13:29 UTC (permalink / raw)
To: oza Pawandeep
Cc: Yao Qi, Tom Tromey, paawan oza, gdb-patches, chandra krishnappa
2011/12/4 oza Pawandeep <oza.pawandeep@gmail.com>:
> Hi,
>
> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
> Change log is elaborated; I am looking forwarding to adding more
> details if need. seeking for your feedback on the same.
>
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog 2011-12-04 16:45:00.000000000 +0530
> @@ -1,3 +1,65 @@
> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
> +
> + * arm-linux-tdep.c: arm_linux_init_abi modified to include
> + arm reversible debugging feature.
> + registered arm_process_record to gdb_arch
> + syscall pointer initialization.
> +
> + * arm-tdep.c: arm-reversible-debugging implementation.
> + newly added functions are as follows.
> +
> + > arm_process_record: handles basic initialization and record
> + summarisation, decodes basic insn ids, on which it hands over
> + controls to decode_insn.
> + > deallocate_reg_mem : clean up function
> + > decode_insn: Decodes arm/thumb insn and calls appropriate
> + decoding routine to record the change.
> + > thumb_record_branch: branch insn reording (thumb)
> + > thumb_record_ldm_stm_swi: load, store and sycall insn
> + recoding (thumb)
> + > thumb_record_misc: misc insn recording (thumb)
> + > thumb_record_ld_st_stack: store and stack insn recording (thumb)
> + > thumb_record_ld_st_imm_offset: load, store with immediate offset
> + insn recording (thumb)
> + > thumb_record_ld_st_reg_offset: load, store with register offset
> + recording (thumb)
> + > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
> + and move insn recording (thumb)
> + > thumb_record_shift_add_sub: shift, add and sub insn recording
> + (thumb)
> + > arm_record_coproc_data_proc: coprocessor and data processing
> + recording (partially implemented) (arm)
> + > arm_record_coproc: coprocessor insn recording
> + (partially implemented) (arm)
> + > arm_record_b_bl: branch insn recording (arm)
> + > arm_record_ld_st_multiple: load and store multiple insn recording
> + (arm)
> + > arm_record_ld_st_reg_offset: load and store reg offset recording
> + (arm)
> + > arm_record_ld_st_imm_offset: load and store immediate offset
> + recording (arm)
> + > arm_record_data_proc_imm: data processing insn recording (arm)
> + > arm_record_data_proc_misc_ld_str: data processing, misc, load and
> + store insn recording (arm)
> + > arm_record_extension_space:arm extension space insn recording
> + (arm)
> + > arm_record_strx: str(X) type insn recording (arm)
> + > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
> +
> + added new data structures:
> + > insn_decode_record_t: local record structure which contains insn's
> + record, which includes both reg and memory.
> +
> + REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
> + in local record which is finally processed by arm_rocess_record.
> +
> + * arm-tdep.h: arm-reversible data structures
> +
> + > modified gdbarch_tdep: added member (function pointer) arm_swi_record
> + which is supposed to be recording system calls
> + > arm_process_record externed.
> +
> +
WOW, thats a lot of text. Other people's changelog entries are more
terse. For example the GNU guidelines say "For example, “New function”
is enough for the change log when you add a function, because there
should be a comment before the function definition to explain what it
does."
In function decode_insn():
> +
> + if (extract_arm_insn (arm_record, insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
If the extract_arm_insn() call fails then the function returns only if
`record_debug' is true. This is strange. Enabling debugging traces
usually expected to only affect printing, here it affects behavior of
the decode_insn() function. Plus the rest of the function seems to
misbehave if it is passed failed result in `arm_record'. I guess the
`return -1;' statement should be moved outside of body of condition
`if (record_debug)'. Unortunatelly I did not notice that earlier.
In arm_process_record():
> +
> + if (extract_arm_insn (&arm_record, 2))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record.gdbarch,
> + arm_record.this_addr), 2);
> + return -1;
> + }
> + }
The same applies here.
Except the one last thing the patch looks good to me now. My previous
suggestions have been resolved.
As always, I did not check whitespace, ARM semantics and Changelog entries.
--
Petr Hluzin
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 11:33 ` oza Pawandeep
2011-12-04 13:29 ` Petr Hluzín
@ 2011-12-04 14:46 ` Yao Qi
2011-12-04 17:00 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04 14:46 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
On 12/04/2011 07:32 PM, oza Pawandeep wrote:
> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
> Change log is elaborated; I am looking forwarding to adding more
> details if need. seeking for your feedback on the same.
>
The format of ChangeLog looks odd to me. Some comments below,
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog 2011-12-04 16:45:00.000000000 +0530
> @@ -1,3 +1,65 @@
> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
> +
> + * arm-linux-tdep.c: arm_linux_init_abi modified to include
> + arm reversible debugging feature.
> + registered arm_process_record to gdb_arch
> + syscall pointer initialization.
It can be
* arm-linux-tdep.c (arm_linux_init_abi): Call
set_gdbarch_process_record.
Initialize `arm_swi_record' field.
Please care about the format of changelog entry, usually it is like this,
[tab] * file-you-modified.c (function-you-modified): What is your
[tab] Change.
Note that we write "what is changed" in ChangeLog, instead of "why is
changed".
> +
> + * arm-tdep.c: arm-reversible-debugging implementation.
> + newly added functions are as follows.
> +
> + > arm_process_record: handles basic initialization and record
> + summarisation, decodes basic insn ids, on which it hands over
> + controls to decode_insn.
So, we don't need so much details in changelog like this, we can write
it in this way,
* arm-tdep.c (arm_process_record): New.
There are still many new added functions, and I think they can
documented in ChangeLog in the same way.
> + > deallocate_reg_mem : clean up function
> + > decode_insn: Decodes arm/thumb insn and calls appropriate
> + decoding routine to record the change.
> + > thumb_record_branch: branch insn reording (thumb)
> + > thumb_record_ldm_stm_swi: load, store and sycall insn
> + recoding (thumb)
> + > thumb_record_misc: misc insn recording (thumb)
> + > thumb_record_ld_st_stack: store and stack insn recording (thumb)
> + > thumb_record_ld_st_imm_offset: load, store with immediate offset
> + insn recording (thumb)
> + > thumb_record_ld_st_reg_offset: load, store with register offset
> + recording (thumb)
> + > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
> + and move insn recording (thumb)
> + > thumb_record_shift_add_sub: shift, add and sub insn recording
> + (thumb)
> + > arm_record_coproc_data_proc: coprocessor and data processing
> + recording (partially implemented) (arm)
> + > arm_record_coproc: coprocessor insn recording
> + (partially implemented) (arm)
> + > arm_record_b_bl: branch insn recording (arm)
> + > arm_record_ld_st_multiple: load and store multiple insn recording
> + (arm)
> + > arm_record_ld_st_reg_offset: load and store reg offset recording
> + (arm)
> + > arm_record_ld_st_imm_offset: load and store immediate offset
> + recording (arm)
> + > arm_record_data_proc_imm: data processing insn recording (arm)
> + > arm_record_data_proc_misc_ld_str: data processing, misc, load and
> + store insn recording (arm)
> + > arm_record_extension_space:arm extension space insn recording
> + (arm)
> + > arm_record_strx: str(X) type insn recording (arm)
> + > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
> +
> + added new data structures:
> + > insn_decode_record_t: local record structure which contains insn's
> + record, which includes both reg and memory.
> +
> + REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
> + in local record which is finally processed by arm_rocess_record.
> +
> + * arm-tdep.h: arm-reversible data structures
> +
> + > modified gdbarch_tdep: added member (function pointer) arm_swi_record
> + which is supposed to be recording system calls
This can be written in this way,
* arm-tdep.h (struct gdbarch_tdep): New field `arm_swi_record'.
> + > arm_process_record externed.
> +
> +
Again, reading other existing changelog entries must be helpful for you
to write your own in a correct way/format. :)
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 14:46 ` Yao Qi
@ 2011-12-04 17:00 ` oza Pawandeep
2011-12-04 23:46 ` Yao Qi
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-04 17:00 UTC (permalink / raw)
To: Yao Qi
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
Hi Yao,
I have modified it; please have a look below.
I have observed that some people have given little description about
functions: but some places its missing.
I think it is better to give small description:
2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
* arm-linux-tdep.c (arm_linux_init_abi): Call
set_gdbarch_process_record.
Initialize `arm_swi_record' field.
* arm-tdep.c (arm_process_record): New function.
(deallocate_reg_mem): New function.
(decode_insn): New function.
(thumb_record_branch): New function.
(thumb_record_ldm_stm_swi(): New function.
(thumb_record_misc): New function.
(thumb_record_ld_st_stack): New function.
(thumb_record_ld_st_imm_offset): New function.
(thumb_record_ld_st_reg_offset(): New function.
(thumb_record_add_sub_cmp_mov): New function.
(thumb_record_shift_add_sub): New function.
(arm_record_coproc_data_proc): New function.
(arm_record_coproc): New function.
(arm_record_b_bl): New function.
(arm_record_ld_st_multiple): New function.
(arm_record_ld_st_reg_offset): New function.
(arm_record_ld_st_imm_offset): New function.
(arm_record_data_proc_imm): New function.
(arm_record_data_proc_misc_ld_str): New function.
(arm_record_extension_space): New function.
(arm_record_strx): New function.
(sbo_sbz): New function.
(struct insn_decode_record): New Structure. arm insn record
(REG_ALLOC): New Macros. use it for reg allocations
(MEM_ALLOC): New Macros. use it for memory allocations
* arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
Regards,
Oza.
On Sun, Dec 4, 2011 at 8:15 PM, Yao Qi <yao@codesourcery.com> wrote:
> On 12/04/2011 07:32 PM, oza Pawandeep wrote:
>> Updated patch contains all the 3 review comments fixed (Tom, Petr and Yao).
>> Change log is elaborated; I am looking forwarding to adding more
>> details if need. seeking for your feedback on the same.
>>
>
> The format of ChangeLog looks odd to me. Some comments below,
>
>> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
>> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
>> +++ arm_new/ChangeLog 2011-12-04 16:45:00.000000000 +0530
>> @@ -1,3 +1,65 @@
>> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
>> +
>> + * arm-linux-tdep.c: arm_linux_init_abi modified to include
>> + arm reversible debugging feature.
>> + registered arm_process_record to gdb_arch
>> + syscall pointer initialization.
>
> It can be
>
> * arm-linux-tdep.c (arm_linux_init_abi): Call
> set_gdbarch_process_record.
> Initialize `arm_swi_record' field.
>
> Please care about the format of changelog entry, usually it is like this,
>
> [tab] * file-you-modified.c (function-you-modified): What is your
> [tab] Change.
>
> Note that we write "what is changed" in ChangeLog, instead of "why is
> changed".
>
>> +
>> + * arm-tdep.c: arm-reversible-debugging implementation.
>> + newly added functions are as follows.
>> +
>> + > arm_process_record: handles basic initialization and record
>> + summarisation, decodes basic insn ids, on which it hands over
>> + controls to decode_insn.
>
> So, we don't need so much details in changelog like this, we can write
> it in this way,
>
> * arm-tdep.c (arm_process_record): New.
>
> There are still many new added functions, and I think they can
> documented in ChangeLog in the same way.
>
>> + > deallocate_reg_mem : clean up function
>> + > decode_insn: Decodes arm/thumb insn and calls appropriate
>> + decoding routine to record the change.
>> + > thumb_record_branch: branch insn reording (thumb)
>> + > thumb_record_ldm_stm_swi: load, store and sycall insn
>> + recoding (thumb)
>> + > thumb_record_misc: misc insn recording (thumb)
>> + > thumb_record_ld_st_stack: store and stack insn recording (thumb)
>> + > thumb_record_ld_st_imm_offset: load, store with immediate offset
>> + insn recording (thumb)
>> + > thumb_record_ld_st_reg_offset: load, store with register offset
>> + recording (thumb)
>> + > thumb_record_add_sub_cmp_mov: addition, subtractation, compare
>> + and move insn recording (thumb)
>> + > thumb_record_shift_add_sub: shift, add and sub insn recording
>> + (thumb)
>> + > arm_record_coproc_data_proc: coprocessor and data processing
>> + recording (partially implemented) (arm)
>> + > arm_record_coproc: coprocessor insn recording
>> + (partially implemented) (arm)
>> + > arm_record_b_bl: branch insn recording (arm)
>> + > arm_record_ld_st_multiple: load and store multiple insn recording
>> + (arm)
>> + > arm_record_ld_st_reg_offset: load and store reg offset recording
>> + (arm)
>> + > arm_record_ld_st_imm_offset: load and store immediate offset
>> + recording (arm)
>> + > arm_record_data_proc_imm: data processing insn recording (arm)
>> + > arm_record_data_proc_misc_ld_str: data processing, misc, load and
>> + store insn recording (arm)
>> + > arm_record_extension_space:arm extension space insn recording
>> + (arm)
>> + > arm_record_strx: str(X) type insn recording (arm)
>> + > sbo_sbz: checks for mendatory sbo and sbz fields in insn,
>> +
>> + added new data structures:
>> + > insn_decode_record_t: local record structure which contains insn's
>> + record, which includes both reg and memory.
>> +
>> + REG_ALLOC and MEM_ALLOC macros takes care of actual memory allocation
>> + in local record which is finally processed by arm_rocess_record.
>> +
>> + * arm-tdep.h: arm-reversible data structures
>> +
>> + > modified gdbarch_tdep: added member (function pointer) arm_swi_record
>> + which is supposed to be recording system calls
>
> This can be written in this way,
>
> * arm-tdep.h (struct gdbarch_tdep): New field `arm_swi_record'.
>
>> + > arm_process_record externed.
>> +
>> +
>
> Again, reading other existing changelog entries must be helpful for you
> to write your own in a correct way/format. :)
>
> --
> Yao (齐尧)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 17:00 ` oza Pawandeep
@ 2011-12-04 23:46 ` Yao Qi
2011-12-05 5:35 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-04 23:46 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
On 12/05/2011 01:00 AM, oza Pawandeep wrote:
> (struct insn_decode_record): New Structure. arm insn record
ChangeLog entry can not be a sentence, but it should be ended with "."
We can say "New structure for arm insn record" or just "New".
> (REG_ALLOC): New Macros. use it for reg allocations
"New macro for reg allocations."
> (MEM_ALLOC): New Macros. use it for memory allocations
"New macro for memory allocations."
The rest of ChangeLog looks right to me, so I don't have any other
comments on ChangeLog.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-04 23:46 ` Yao Qi
@ 2011-12-05 5:35 ` oza Pawandeep
2011-12-05 8:12 ` Yao Qi
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-05 5:35 UTC (permalink / raw)
To: Yao Qi
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
Hi Tom, Yao and Petr,
This patch includes your final comments implemented; and Change log
corrected as well.
If there are any more formatting issues, I will be happy to correct them.
please find the last patch below.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c (arm_linux_init_abi): Call
+ set_gdbarch_process_record.
+ Initialize `arm_swi_record' field.
+
+ * arm-tdep.c (arm_process_record): New function.
+ (deallocate_reg_mem): New function.
+ (decode_insn): New function.
+ (thumb_record_branch): New function.
+ (thumb_record_ldm_stm_swi(): New function.
+ (thumb_record_misc): New function.
+ (thumb_record_ld_st_stack): New function.
+ (thumb_record_ld_st_imm_offset): New function.
+ (thumb_record_ld_st_reg_offset(): New function.
+ (thumb_record_add_sub_cmp_mov): New function.
+ (thumb_record_shift_add_sub): New function.
+ (arm_record_coproc_data_proc): New function.
+ (arm_record_coproc): New function.
+ (arm_record_b_bl): New function.
+ (arm_record_ld_st_multiple): New function.
+ (arm_record_ld_st_reg_offset): New function.
+ (arm_record_ld_st_imm_offset): New function.
+ (arm_record_data_proc_imm): New function.
+ (arm_record_data_proc_misc_ld_str): New function.
+ (arm_record_extension_space): New function.
+ (arm_record_strx): New function.
+ (sbo_sbz): New function.
+ (struct insn_decode_record): New Structure for arm insn record.
+ (REG_ALLOC): New Macro for reg allocations.
+ (MEM_ALLOC): New Macro for memory allocations.
+
+ * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
0 on success
+and positive val on fauilure. */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+ gdb_byte buf[insn_size];
+
+ memset (&buf[0], 0, insn_size);
+
+ if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+ return 1;
+ insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size,
+ gdbarch_byte_order (insn_record->gdbarch));
+ return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ uint32_t ret = 0; /* return value: negative>failure 0>success. */
+ uint32_t insn_id = 0;
+
+ if (extract_arm_insn (arm_record, insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr),
insn_size);
+ }
+ return -1;
+ }
+ else if (ARM_RECORD == 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ if (extract_arm_insn (&arm_record, 2))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
+ }
+ return -1;
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-05 5:35 ` oza Pawandeep
@ 2011-12-05 8:12 ` Yao Qi
2011-12-05 16:02 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Yao Qi @ 2011-12-05 8:12 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
On 12/05/2011 01:35 PM, oza Pawandeep wrote:
> + (struct insn_decode_record): New Structure for arm insn record.
> + (REG_ALLOC): New Macro for reg allocations.
> + (MEM_ALLOC): New Macro for memory allocations.
Any reason to capitalize "S" in "Structure" and "M" in "Macro"? I think
they should be lower-case'ed.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-05 8:12 ` Yao Qi
@ 2011-12-05 16:02 ` oza Pawandeep
2011-12-19 6:26 ` oza Pawandeep
2011-12-20 19:11 ` Tom Tromey
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-05 16:02 UTC (permalink / raw)
To: Yao Qi
Cc: Petr Hluzín, Tom Tromey, paawan oza, gdb-patches,
chandra krishnappa
Hi Yao,
here is the latest patch with Changelog comment fixed.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c (arm_linux_init_abi): Call
+ set_gdbarch_process_record.
+ Initialize `arm_swi_record' field.
+
+ * arm-tdep.c (arm_process_record): New function.
+ (deallocate_reg_mem): New function.
+ (decode_insn): New function.
+ (thumb_record_branch): New function.
+ (thumb_record_ldm_stm_swi(): New function.
+ (thumb_record_misc): New function.
+ (thumb_record_ld_st_stack): New function.
+ (thumb_record_ld_st_imm_offset): New function.
+ (thumb_record_ld_st_reg_offset(): New function.
+ (thumb_record_add_sub_cmp_mov): New function.
+ (thumb_record_shift_add_sub): New function.
+ (arm_record_coproc_data_proc): New function.
+ (arm_record_coproc): New function.
+ (arm_record_b_bl): New function.
+ (arm_record_ld_st_multiple): New function.
+ (arm_record_ld_st_reg_offset): New function.
+ (arm_record_ld_st_imm_offset): New function.
+ (arm_record_data_proc_imm): New function.
+ (arm_record_data_proc_misc_ld_str): New function.
+ (arm_record_extension_space): New function.
+ (arm_record_strx): New function.
+ (sbo_sbz): New function.
+ (struct insn_decode_record): New structure for arm insn record.
+ (REG_ALLOC): New macro for reg allocations.
+ (MEM_ALLOC): New macro for memory allocations.
+
+ * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
0 on success
+and positive val on fauilure. */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+ gdb_byte buf[insn_size];
+
+ memset (&buf[0], 0, insn_size);
+
+ if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+ return 1;
+ insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size,
+ gdbarch_byte_order (insn_record->gdbarch));
+ return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ uint32_t ret = 0; /* return value: negative>failure 0>success. */
+ uint32_t insn_id = 0;
+
+ if (extract_arm_insn (arm_record, insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr),
insn_size);
+ }
+ return -1;
+ }
+ else if (ARM_RECORD == 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ if (extract_arm_insn (&arm_record, 2))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
+ }
+ return -1;
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-05 16:02 ` oza Pawandeep
@ 2011-12-19 6:26 ` oza Pawandeep
2011-12-20 19:11 ` Tom Tromey
1 sibling, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-19 6:26 UTC (permalink / raw)
To: Tom Tromey
Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa, Yao Qi
Hi Tom,
I suppose you have no more comment for the latest patch, and rest of
the comments are closed
too. Changelog is attached too.
please let me know the next step;
Regards,
Oza.
On Mon, Dec 5, 2011 at 9:05 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> Hi Yao,
>
> here is the latest patch with Changelog comment fixed.
>
> diff -urN arm_orig/ChangeLog arm_new/ChangeLog
> --- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
> +++ arm_new/ChangeLog 2011-12-04 23:36:50.000000000 +0530
> @@ -1,3 +1,37 @@
> +2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
> +
> + * arm-linux-tdep.c (arm_linux_init_abi): Call
> + set_gdbarch_process_record.
> + Initialize `arm_swi_record' field.
> +
> + * arm-tdep.c (arm_process_record): New function.
> + (deallocate_reg_mem): New function.
> + (decode_insn): New function.
> + (thumb_record_branch): New function.
> + (thumb_record_ldm_stm_swi(): New function.
> + (thumb_record_misc): New function.
> + (thumb_record_ld_st_stack): New function.
> + (thumb_record_ld_st_imm_offset): New function.
> + (thumb_record_ld_st_reg_offset(): New function.
> + (thumb_record_add_sub_cmp_mov): New function.
> + (thumb_record_shift_add_sub): New function.
> + (arm_record_coproc_data_proc): New function.
> + (arm_record_coproc): New function.
> + (arm_record_b_bl): New function.
> + (arm_record_ld_st_multiple): New function.
> + (arm_record_ld_st_reg_offset): New function.
> + (arm_record_ld_st_imm_offset): New function.
> + (arm_record_data_proc_imm): New function.
> + (arm_record_data_proc_misc_ld_str): New function.
> + (arm_record_extension_space): New function.
> + (arm_record_strx): New function.
> + (sbo_sbz): New function.
> + (struct insn_decode_record): New structure for arm insn record.
> + (REG_ALLOC): New macro for reg allocations.
> + (MEM_ALLOC): New macro for memory allocations.
> +
> + * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
> +
> 2011-11-09 Roland McGrath <mcgrathr@google.com>
>
> * configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
> diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
> @@ -1148,8 +1148,14 @@
> simple_displaced_step_free_closure);
> set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
>
> + /* Reversible debugging, process record. */
> + set_gdbarch_process_record (gdbarch, arm_process_record);
> +
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + /* Syscall record. */
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
> +++ arm_new/arm-tdep.c 2011-12-04 22:04:36.000000000 +0530
> @@ -55,6 +55,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
> #include "features/arm-with-iwmmxt.c"
> #include "features/arm-with-vfpv2.c"
> @@ -10175,3 +10177,2063 @@
> NULL, /* FIXME: i18n: "ARM debugging is %s. */
> &setdebuglist, &showdebuglist);
> }
> +
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
> + memcpy(&MEMS->len, &RECORD_BUF[0], \
> + sizeof(struct arm_mem_r) * LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +/* Checks whether insn is already recorded or yet to be decoded.
> (boolean expression). */
> +#define INSN_RECORDED(ARM_RECORD) \
> + (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn
> + and execution state (before entry to decode_insn()),
> + contains list of to-be-modified registers and
> + memory blocks (on return from decode_insn()). */
> +
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the insn being decoded. */
> + uint32_t arm_insn; /* Should accommodate thumb. */
> + uint32_t cond; /* Condition code. */
> + uint32_t opcode; /* Insn opcode. */
> + uint32_t decode; /* Insn decode bits. */
> + uint32_t mem_rec_count; /* No of mem records. */
> + uint32_t reg_rec_count; /* No of reg records. */
> + uint32_t *arm_regs; /* Registers to be saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mandatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if (!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +typedef enum
> +{
> + ARM_RECORD_STRH=1,
> + ARM_RECORD_STRD
> +} arm_record_strx_t;
> +
> +typedef enum
> +{
> + ARM_RECORD=1,
> + THUMB_RECORD,
> + THUMB2_RECORD
> +} record_type_t;
> +
> +
> +static int
> +arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
> + uint32_t *record_buf_mem, arm_record_strx_t str_type)
> +{
> +
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + ULONGEST u_regval[2]= {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> +
> + if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
> + {
> + /* 1) Handle misc store, immediate offset. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1,
> + &u_regval[0]);
> + if (ARM_PC_REGNUM == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + offset_8 = (immed_high << 4) | immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = tgt_mem_addr;
> + record_buf_mem[2] = 4;
> + record_buf_mem[3] = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = tgt_mem_addr;
> + record_buf_mem[2] = 4;
> + record_buf_mem[3] = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + }
> + else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
> + || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0, 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8, 11);
> + offset_8 = (immed_high << 4) | immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[0] - offset_8;
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = tgt_mem_addr;
> + record_buf_mem[2] = 4;
> + record_buf_mem[3] = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
> + || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> + if (ARM_RECORD_STRH == str_type)
> + {
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if (ARM_RECORD_STRD == str_type)
> + {
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = tgt_mem_addr;
> + record_buf_mem[2] = 4;
> + record_buf_mem[3] = tgt_mem_addr + 4;
> + arm_insn_r->mem_rec_count = 2;
> + }
> + /* Record Rn also as it changes. */
> + *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + return 0;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +arm_record_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
> + uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> + uint32_t reg_src1 = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + ULONGEST u_regval = 0;
> +
> + gdb_assert (!INSN_RECORDED(arm_insn_r));
> + /* Handle unconditional insn extension space. */
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> + if (arm_insn_r->cond)
> + {
> + /* PLD has no affect on architectural state, it just affects
> + the caches. */
> + if (5 == ((opcode1 & 0xE0) >> 5))
> + {
> + /* BLX(1) */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
> + }
> +
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to handle if later
> + versions define it. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> + insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
> +
> + /* Handle arithmetic insn extension space. */
> + if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
> + && !INSN_RECORDED(arm_insn_r))
> + {
> + /* Handle MLA(S) and MUL(S). */
> + if (0 <= insn_op1 && 3 >= insn_op1)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (4 <= insn_op1 && 15 >= insn_op1)
> + {
> + /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> + insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
> +
> + /* Handle control insn extension space. */
> +
> + if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
> + && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
> + {
> + if (!bit (arm_insn_r->arm_insn,25))
> + {
> + if (!bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + if ((0 == insn_op1) || (2 == insn_op1))
> + {
> + /* MRS. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == insn_op1)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* 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;
> + }
> + }
> + else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + if (1 == insn_op1)
> + {
> + /* BX. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* BLX. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* QADD, QSUB, QDADD, QDSUB */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
> + {
> + /* BKPT. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + || 10 == bits (arm_insn_r->arm_insn, 4, 7)
> + || 12 == bits (arm_insn_r->arm_insn, 4, 7)
> + || 14 == bits (arm_insn_r->arm_insn, 4, 7)
> + )
> + {
> + if (0 == insn_op1 || 1 == insn_op1)
> + {
> + /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
> + /* We dont do optimization for SMULW<y> where we
> + need only Rd. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (2 == insn_op1)
> + {
> + /* SMLAL<x><y>. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (3 == insn_op1)
> + {
> + /* SMUL<x><y>. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> + else
> + {
> + /* MSR : immediate form. */
> + if (1 == insn_op1)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == insn_op1)
> + {
> + /* 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;
> + }
> + }
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
> + insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
> +
> + /* Handle load/store insn extension space. */
> +
> + if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
> + && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
> + && !INSN_RECORDED(arm_insn_r))
> + {
> + /* SWP/SWPB. */
> + if (0 == insn_op1)
> + {
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
> + {
> + /* STRH. */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRH);
> + }
> + else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
> + {
> + /* LDRD. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = record_buf[0] + 1;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
> + {
> + /* STRD. */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRD);
> + }
> + else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
> + {
> + /* LDRH, LDRSB, LDRSH. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
> + && !INSN_RECORDED(arm_insn_r))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* 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));
> +
> +
> + 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);
> +
> + return ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> + ULONGEST u_regval[2] = {0};
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if (9 == arm_insn_r->decode
> + && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
> + {
> + /* Handle misc load insns, as 20th bit (L = 1). */
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precceded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. I am not sure this is right
> + place; as opcode = 010 LDR insn make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
> + && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if (9 == arm_insn_r->decode
> + && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insn, changes register and memory as well. */
> + /* SWP or SWPB insn. */
> +
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_regval[0];
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (3 == arm_insn_r->decode && 0x12 == opcode1
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
> + and R14 stores the return address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (7 == arm_insn_r->decode && 0x12 == opcode1)
> + {
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* According to high vector configuration PC is set. */
> + /* user hit breakpoint and type reverse, in
> + that case, we need to go back with previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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
> + && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
> +
> + /* Handle str(x) insn */
> + arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
> + ARM_RECORD_STRH);
> + }
> + else if (1 == arm_insn_r->decode && 0x12 == opcode1
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == arm_insn_r->decode && 0x16 == opcode1
> + && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
> + && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
> + && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
> + && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
> + && 2 == bits (arm_insn_r->arm_insn, 20, 21)
> + && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
> + )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn modifies destination
> + register, which is specified by 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + return -1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + ULONGEST u_regval = 0;
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (ARM_PC_REGNUM != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Store, immediate offset, immediate pre-indexed,
> + immediate post-indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 4:
> + case 0:
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
> + || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
> + || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
> + || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
> + || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
> + || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
> + )
> + {
> + /* We are handling pre-indexed mode; post-indexed mode;
> + where Rn is going to be changed. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + LONGEST s_word;
> + ULONGEST u_regval[2];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + order begins according to addressing modes for store insns
> + STRH insn. */
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn having Rn as R15
> + in that case, it emulates branch and link insn, and hence we
> + need to save CSPR and PC as well. */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and register pre-indexed,
> + register post-indexed. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + , &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2
> + , &u_regval[1]);
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current PC+8. */
> + /* Pre-indexed mode doesnt reach here ; illegal insn. */
> + u_regval[0] = u_regval[0] + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval[0] + u_regval[1];
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - u_regval[0];
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
> + || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
> + || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
> + || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
> + || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
> + || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
> + )
> + {
> + /* Rn is going to be changed in pre-indexed mode and
> + post-indexed mode as well. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset; scaled pre-indexed. */
> + offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
> + /* Get shift_imm. */
> + shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
> + regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
> + /* Offset_12 used as shift. */
> + switch (offset_12)
> + {
> + case 0:
> + /* Offset_12 used as index. */
> + offset_12 = u_regval[0] << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
> + break;
> +
> + case 2:
> + if (!shift_imm)
> + {
> + if (bit (u_regval[0], 31))
> + {
> + offset_12 = 0xFFFFFFFF;
> + }
> + else
> + {
> + offset_12 = 0;
> + }
> + }
> + else
> + {
> + /* This is arithmetic shift. */
> + offset_12 = s_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> + regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
> + &u_regval[1]);
> + /* Get C flag value and shift it by 31. */
> + offset_12 = (((bit (u_regval[1], 29)) << 31) \
> + | (u_regval[0]) >> 1);
> + }
> + else
> + {
> + offset_12 = (u_regval[0] >> shift_imm) \
> + | (u_regval[0] <<
> + (sizeof(uint32_t) - shift_imm));
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
> + /* bit U set. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_regval[1] + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_regval[1] - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + /* STR. */
> + case 8:
> + case 12:
> + /* STR. */
> + case 9:
> + case 13:
> + /* STRT. */
> + case 1:
> + case 5:
> + /* STR. */
> + case 0:
> + case 4:
> + record_buf_mem[0] = 4;
> + break;
> +
> + /* STRB. */
> + case 10:
> + case 14:
> + /* STRB. */
> + case 11:
> + case 15:
> + /* STRBT. */
> + case 3:
> + case 7:
> + /* STRB. */
> + case 2:
> + case 6:
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
> + || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
> + || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
> + || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
> + || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
> + || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
> + )
> + {
> + /* Rn is going to be changed in register scaled pre-indexed
> + mode,and scaled post indexed mode. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
> + uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + ULONGEST u_regval[2] = {0};
> +
> + /* This mode is exclusively for load and store multiple. */
> + /* Handle incremenrt after/before and decrment after.before mode;
> + Rn is changing depending on W bit, but as of now we store Rn too
> + without optimization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR too. */
> +
> + if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> + else
> + {
> + register_bits = bits (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> +
> + /* Extra space for Base Register and CPSR; wihtout optimization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = register_count + 2;
> +
> + for (register_count = 0; register_count < no_of_regs; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + /* Register_count gives total no of registers
> + and dually working as reg number. */
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0, 15);
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch (addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
> + start_address = (u_regval[0]) - (register_count * 4) + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address = u_regval[0];
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address = (u_regval[0]) - (register_count * 4);
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case 3:
> + start_address = u_regval[0] + 4;
> + arm_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached ("no decoding pattern found");
> + break;
> + }
> +
> + /* Base register also changes; based on condition and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +arm_record_b_bl (insn_decode_record *arm_insn_r)
> +{
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* B simply branches so we do nothing here. */
> + /* Note: BLX(1) doesnt fall here but instead it falls into
> + extension space. */
> + if (bit (arm_insn_r->arm_insn, 24))
> + {
> + record_buf[0] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_record_coproc (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t ret = 0; /* function return value: -1:record failure ;
> 0:success */
> +
> + /* Handle SWI insn; system call would be handled over here. */
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
> + if (15 == arm_insn_r->opcode)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + ret = tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + ret = -1;
> + }
> + }
> +
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
> +
> + ULONGEST u_regval[2] = {0};
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
> +
> + if (bit (thumb_insn_r->arm_insn, 12))
> + {
> + /* Handle load/store register offset. */
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
> + if (opcode2 >= 12 && opcode2 <= 15)
> + {
> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
> + reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode2 >= 8 && opcode2 <= 10)
> + {
> + /* STR(2), STRB(2), STRH(2) . */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
> + regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
> + if (8 == opcode2)
> + record_buf_mem[0] = 4; /* STR (2). */
> + else if (10 == opcode2)
> + record_buf_mem[0] = 1; /* STRB (2). */
> + else if (9 == opcode2)
> + record_buf_mem[0] = 2; /* STRH (2). */
> + record_buf_mem[1] = u_regval[0] + u_regval[1];
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + }
> + else if (bit (thumb_insn_r->arm_insn, 11))
> + {
> + /* Handle load from literal pool. */
> + /* LDR(3). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode1)
> + {
> + opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
> + opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if ((3 == opcode2) && (!opcode3))
> + {
> + /* Branch with exchange. */
> + record_buf[0] = ARM_PS_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + 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;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Format 5; data processing insns. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + if (bit (thumb_insn_r->arm_insn, 7))
> + {
> + reg_src1 = reg_src1 + 8;
> + }
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (opcode)
> + {
> + /* LDR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* STR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_regval + (immed_5 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (3 == opcode)
> + {
> + /* LDR(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == opcode)
> + {
> + /* LDRH(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* STR(3). */
> + immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_regval + (immed_8 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + else if (0 == opcode)
> + {
> + /* STRH(1). */
> + immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = u_regval + (immed_5 * 2);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_record_misc (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> + uint32_t reg_src1;
> +
> + ULONGEST u_regval = 0;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count + 2;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_regval - \
> + (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn. */
> + /* Handle enhanced software breakpoint insn, BKPT. */
> + /* CPSR is changed to be executed in ARM state, disabling normal
> + interrupts, entering abort mode. */
> + /* According to high vector configuration PC is set. */
> + /* User hits breakpoint and type reverse, in that case, we need
> to go back with
> + previous CPSR and Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* We need to save SPSR value, which is not yet done. */
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),
> + thumb_insn_r->arm_insn,
> + paddress (thumb_insn_r->gdbarch,
> + thumb_insn_r->this_addr));
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> + {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache = thumb_insn_r->regcache;
> +
> + uint32_t ret = 0; /* function return value: -1:record failure ;
> 0:success */
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0, start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + ULONGEST u_regval = 0;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count + 1;
> + for (register_count = 0; register_count < 8; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] = start_address;
> + record_buf_mem[(register_count * 2) - 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + ret = tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record support\n"));
> + return -1;
> + }
> + }
> +
> + /* B (1), conditional branch is automatically taken care in process_record,
> + as PC is saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
> + record_buf_mem);
> +
> + return ret;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_record_branch (insn_decode_record *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t bits_h = 0;
> +
> + bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (2 == bits_h || 3 == bits_h)
> + {
> + /* BL */
> + record_buf[0] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == bits_h)
> + {
> + /* BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + /* B(2) is automatically taken care in process_record, as PC is
> + saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
> 0 on success
> +and positive val on fauilure. */
> +
> +static int
> +extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
> +{
> + gdb_byte buf[insn_size];
> +
> + memset (&buf[0], 0, insn_size);
> +
> + if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
> + return 1;
> + insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
> + insn_size,
> + gdbarch_byte_order (insn_record->gdbarch));
> + return 0;
> +}
> +
> +typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
> +
> +/* Decode arm/thumb insn depending on condition cods and opcodes; and
> + dispatch it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, record_type_t record_type,
> + uint32_t insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
> instruction. */
> + static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
> + {
> + arm_record_data_proc_misc_ld_str, /* 000. */
> + arm_record_data_proc_imm, /* 001. */
> + arm_record_ld_st_imm_offset, /* 010. */
> + arm_record_ld_st_reg_offset, /* 011. */
> + arm_record_ld_st_multiple, /* 100. */
> + arm_record_b_bl, /* 101. */
> + arm_record_coproc, /* 110. */
> + arm_record_coproc_data_proc /* 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
> instruction. */
> + static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
> + { \
> + thumb_record_shift_add_sub, /* 000. */
> + thumb_record_add_sub_cmp_mov, /* 001. */
> + thumb_record_ld_st_reg_offset, /* 010. */
> + thumb_record_ld_st_imm_offset, /* 011. */
> + thumb_record_ld_st_stack, /* 100. */
> + thumb_record_misc, /* 101. */
> + thumb_record_ldm_stm_swi, /* 110. */
> + thumb_record_branch /* 111. */
> + };
> +
> + uint32_t ret = 0; /* return value: negative>failure 0>success. */
> + uint32_t insn_id = 0;
> +
> + if (extract_arm_insn (arm_record, insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record->gdbarch, arm_record->this_addr),
> insn_size);
> + }
> + return -1;
> + }
> + else if (ARM_RECORD == 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))
> + {
> + ret = arm_handle_insn[insn_id] (arm_record);
> + }
> + }
> + else if (THUMB_RECORD == record_type)
> + {
> + /* As thumb does not have condition codes, we set negative. */
> + arm_record->cond = -1;
> + insn_id = bits (arm_record->arm_insn, 13, 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_RECORD == record_type)
> + {
> + printf_unfiltered (_("Process record doesnt support thumb32 instruction "
> + "0x%0x at address %s.\n"),arm_record->arm_insn,
> + paddress (arm_record->gdbarch,
> + arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert (0);
> + }
> +
> + return ret;
> +}
> +
> +
> +/* Cleans up local record registers and memory allocations. */
> +
> +static void
> +deallocate_reg_mem (insn_decode_record *record)
> +{
> + xfree (record->arm_regs);
> + xfree (record->arm_mems);
> +}
> +
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to record_arch_list".
> + Return -1 if something is wrong. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
> + ULONGEST t_bit = 0, insn_id = 0;
> +
> + ULONGEST u_regval = 0;
> +
> + insn_decode_record arm_record;
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + if (extract_arm_insn (&arm_record, 2))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error reading memory at "
> + "addr %s len = %d.\n"),
> + paddress (arm_record.gdbarch,
> + arm_record.this_addr), 2);
> + }
> + return -1;
> + }
> +
> + /* Check the insn, whether it is thumb or arm one. */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
> +
> +
> + if (!(u_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + insn_id = bits (arm_record.arm_insn, 11, 15);
> + /* is it thumb2 insn? */
> + if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
> + {
> + ret = decode_insn (&arm_record, THUMB2_RECORD,
> + THUMB2_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
> + }
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_reg (arm_record.regcache ,
> + arm_record.arm_regs[no_of_rec]))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_mem
> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> + arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> +
> + deallocate_reg_mem (&arm_record);
> +
> + return ret;
> +}
> +
> +
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
> +++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
> @@ -201,6 +201,9 @@
> /* Return the expected next PC if FRAME is stopped at a syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
> /* Structures used for displaced stepping. */
> @@ -330,6 +333,8 @@
> instruction? */
> extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> + struct regcache *regcache, CORE_ADDR addr);
> /* Functions exported from armbsd-tdep.h. */
>
> /* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-05 16:02 ` oza Pawandeep
2011-12-19 6:26 ` oza Pawandeep
@ 2011-12-20 19:11 ` Tom Tromey
2011-12-28 12:43 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2011-12-20 19:11 UTC (permalink / raw)
To: oza Pawandeep
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
Oza> here is the latest patch with Changelog comment fixed.
One last little nit...
Oza> + gdb_assert (0);
Please change this to gdb_assert_not_reached.
This is ok with this change.
Could you write a NEWS entry for this change?
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-20 19:11 ` Tom Tromey
@ 2011-12-28 12:43 ` oza Pawandeep
2012-01-05 11:01 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2011-12-28 12:43 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
Thank you for your feedback;
I have fixed your comment, and also written NEWS entry; please have a look.
PATCH STARTS
--------------------------
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c (arm_linux_init_abi): Call
+ set_gdbarch_process_record.
+ Initialize `arm_swi_record' field.
+
+ * arm-tdep.c (arm_process_record): New function.
+ (deallocate_reg_mem): New function.
+ (decode_insn): New function.
+ (thumb_record_branch): New function.
+ (thumb_record_ldm_stm_swi(): New function.
+ (thumb_record_misc): New function.
+ (thumb_record_ld_st_stack): New function.
+ (thumb_record_ld_st_imm_offset): New function.
+ (thumb_record_ld_st_reg_offset(): New function.
+ (thumb_record_add_sub_cmp_mov): New function.
+ (thumb_record_shift_add_sub): New function.
+ (arm_record_coproc_data_proc): New function.
+ (arm_record_coproc): New function.
+ (arm_record_b_bl): New function.
+ (arm_record_ld_st_multiple): New function.
+ (arm_record_ld_st_reg_offset): New function.
+ (arm_record_ld_st_imm_offset): New function.
+ (arm_record_data_proc_imm): New function.
+ (arm_record_data_proc_misc_ld_str): New function.
+ (arm_record_extension_space): New function.
+ (arm_record_strx): New function.
+ (sbo_sbz): New function.
+ (struct insn_decode_record): New structure for arm insn record.
+ (REG_ALLOC): New macro for reg allocations.
+ (MEM_ALLOC): New macro for memory allocations.
+
+ * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/NEWS arm_new/NEWS
--- arm_orig/NEWS 2011-12-28 12:25:47.000000000 +0530
+++ arm_new/NEWS 2011-12-28 12:32:10.000000000 +0530
@@ -3,6 +3,10 @@
*** Changes since GDB 7.3.1
+* GDB now supports reversible debugging on ARM, it allows you to
+ debug basic ARM and THUMB instructions, and provides
+ record/replay support.
+
* GDB now allows you to skip uninteresting functions and files when
stepping with the "skip function" and "skip file" commands.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-04 22:04:36.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
0 on success
+and positive val on fauilure. */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+ gdb_byte buf[insn_size];
+
+ memset (&buf[0], 0, insn_size);
+
+ if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+ return 1;
+ insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size,
+ gdbarch_byte_order (insn_record->gdbarch));
+ return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ uint32_t ret = 0; /* return value: negative>failure 0>success. */
+ uint32_t insn_id = 0;
+
+ if (extract_arm_insn (arm_record, insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr),
insn_size);
+ }
+ return -1;
+ }
+ else if (ARM_RECORD == 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert_not_reached ("not a valid arm instruction, could not decode");
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ if (extract_arm_insn (&arm_record, 2))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
+ }
+ return -1;
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-28 12:43 ` oza Pawandeep
@ 2012-01-05 11:01 ` oza Pawandeep
2012-01-05 12:03 ` Eli Zaretskii
2012-01-05 16:17 ` Tom Tromey
0 siblings, 2 replies; 128+ messages in thread
From: oza Pawandeep @ 2012-01-05 11:01 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
Latest patch after own review.
PATCH STARTS
------------------------
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-04 23:36:50.000000000 +0530
@@ -1,3 +1,37 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c (arm_linux_init_abi): Call
+ set_gdbarch_process_record.
+ Initialize `arm_swi_record' field.
+
+ * arm-tdep.c (arm_process_record): New function.
+ (deallocate_reg_mem): New function.
+ (decode_insn): New function.
+ (thumb_record_branch): New function.
+ (thumb_record_ldm_stm_swi(): New function.
+ (thumb_record_misc): New function.
+ (thumb_record_ld_st_stack): New function.
+ (thumb_record_ld_st_imm_offset): New function.
+ (thumb_record_ld_st_reg_offset(): New function.
+ (thumb_record_add_sub_cmp_mov): New function.
+ (thumb_record_shift_add_sub): New function.
+ (arm_record_coproc_data_proc): New function.
+ (arm_record_coproc): New function.
+ (arm_record_b_bl): New function.
+ (arm_record_ld_st_multiple): New function.
+ (arm_record_ld_st_reg_offset): New function.
+ (arm_record_ld_st_imm_offset): New function.
+ (arm_record_data_proc_imm): New function.
+ (arm_record_data_proc_misc_ld_str): New function.
+ (arm_record_extension_space): New function.
+ (arm_record_strx): New function.
+ (sbo_sbz): New function.
+ (struct insn_decode_record): New structure for arm insn record.
+ (REG_ALLOC): New macro for reg allocations.
+ (MEM_ALLOC): New macro for memory allocations.
+
+ * arm-tdep.h (struct gdbarch_tdep): New field 'arm_swi_record'
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/NEWS arm_new/NEWS
--- arm_orig/NEWS 2011-12-28 12:25:47.000000000 +0530
+++ arm_new/NEWS 2011-12-28 12:32:10.000000000 +0530
@@ -3,6 +3,10 @@
*** Changes since GDB 7.3.1
+* GDB now supports reversible debugging on ARM, it allows you to
+ debug basic ARM and THUMB instructions, and provides
+ record/replay support.
+
* GDB now allows you to skip uninteresting functions and files when
stepping with the "skip function" and "skip file" commands.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2012-01-05 16:24:25.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2063 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* Checks whether insn is already recorded or yet to be decoded.
(boolean expression). */
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != (ARM_RECORD)->reg_rec_count || 0 != (ARM_RECORD)->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = tgt_mem_addr;
+ record_buf_mem[2] = 4;
+ record_buf_mem[3] = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ gdb_assert (!INSN_RECORDED(arm_insn_r));
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Extracts arm/thumb/thumb2 insn depending on the size, and returns
0 on success
+and positive val on fauilure. */
+
+static int
+extract_arm_insn (insn_decode_record *insn_record, uint32_t insn_size)
+{
+ gdb_byte buf[insn_size];
+
+ memset (&buf[0], 0, insn_size);
+
+ if (target_read_memory (insn_record->this_addr, &buf[0], insn_size))
+ return 1;
+ insn_record->arm_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size,
+ gdbarch_byte_order (insn_record->gdbarch));
+ return 0;
+}
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ uint32_t ret = 0; /* return value: negative:failure 0:success. */
+ uint32_t insn_id = 0;
+
+ if (extract_arm_insn (arm_record, insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr),
insn_size);
+ }
+ return -1;
+ }
+ else if (ARM_RECORD == 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert_not_reached ("not a valid instruction, could not decode");
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* return value: -1:record failure ; 0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ if (extract_arm_insn (&arm_record, 2))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record.gdbarch,
+ arm_record.this_addr), 2);
+ }
+ return -1;
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
+ THUMB2_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD, THUMB_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-05 11:01 ` oza Pawandeep
@ 2012-01-05 12:03 ` Eli Zaretskii
2012-01-05 16:17 ` Tom Tromey
1 sibling, 0 replies; 128+ messages in thread
From: Eli Zaretskii @ 2012-01-05 12:03 UTC (permalink / raw)
To: oza Pawandeep
Cc: tromey, yao, petr.hluzin, paawan1982, gdb-patches, chandra_roadking
> Date: Thu, 5 Jan 2012 16:30:26 +0530
> From: oza Pawandeep <oza.pawandeep@gmail.com>
> Cc: Yao Qi <yao@codesourcery.com>, Petr HluzÃn <petr.hluzin@gmail.com>, paawan oza <paawan1982@yahoo.com>, "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, chandra krishnappa <chandra_roadking@yahoo.com>
>
> diff -urN arm_orig/NEWS arm_new/NEWS
> --- arm_orig/NEWS 2011-12-28 12:25:47.000000000 +0530
> +++ arm_new/NEWS 2011-12-28 12:32:10.000000000 +0530
> @@ -3,6 +3,10 @@
>
> *** Changes since GDB 7.3.1
>
> +* GDB now supports reversible debugging on ARM, it allows you to
> + debug basic ARM and THUMB instructions, and provides
> + record/replay support.
> +
> * GDB now allows you to skip uninteresting functions and files when
> stepping with the "skip function" and "skip file" commands.
This part is OK. Thanks.
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-05 11:01 ` oza Pawandeep
2012-01-05 12:03 ` Eli Zaretskii
@ 2012-01-05 16:17 ` Tom Tromey
2012-01-05 18:17 ` oza Pawandeep
1 sibling, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-05 16:17 UTC (permalink / raw)
To: oza Pawandeep
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
oza> Latest patch after own review.
Great, you can commit it now.
Thanks for persevering.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-05 16:17 ` Tom Tromey
@ 2012-01-05 18:17 ` oza Pawandeep
2012-01-06 8:06 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-05 18:17 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
My last patch was committed by Michael Snyder.
I believe neither do I have a way nor have an access for check-in.
please guide me with the same.
Regards,
Oza.
On Thu, Jan 5, 2012 at 9:47 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> Latest patch after own review.
>
> Great, you can commit it now.
>
> Thanks for persevering.
>
> Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-05 18:17 ` oza Pawandeep
@ 2012-01-06 8:06 ` oza Pawandeep
2012-01-06 19:13 ` Tom Tromey
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-06 8:06 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
If I understood you correctly, I should be submitting copyright
information, and changes.
Am I getting it right ?
Regards,
Oza.
On Thu, Jan 5, 2012 at 11:47 PM, oza Pawandeep <oza.pawandeep@gmail.com> wrote:
> My last patch was committed by Michael Snyder.
> I believe neither do I have a way nor have an access for check-in.
> please guide me with the same.
>
> Regards,
> Oza.
>
>
> On Thu, Jan 5, 2012 at 9:47 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>>
>> oza> Latest patch after own review.
>>
>> Great, you can commit it now.
>>
>> Thanks for persevering.
>>
>> Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-06 8:06 ` oza Pawandeep
@ 2012-01-06 19:13 ` Tom Tromey
2012-01-07 6:31 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-06 19:13 UTC (permalink / raw)
To: oza Pawandeep
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
Oza> If I understood you correctly, I should be submitting copyright
Oza> information, and changes.
Do you have paperwork on file with the FSF already?
You ought to, given that you have another patch in the tree; though
perhaps it was not big enough.
If you do not have paperwork, then you must file it before we can put
your change in.
If you do have paperwork, I can put it in soon.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-06 19:13 ` Tom Tromey
@ 2012-01-07 6:31 ` oza Pawandeep
2012-01-09 16:25 ` Tom Tromey
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-01-07 6:31 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
Yes, I have paperwork with FSF; as last change was considerably big enough.
Now I am in a process of getting disclaimer from my new firm;
Will post the things along with necessary paperwork.
Thanks for your quick response Tom.
PS: I will be taking phase 3 of the same soon.
Regards,
Oza.
On Fri, Jan 6, 2012 at 11:21 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> Oza> If I understood you correctly, I should be submitting copyright
> Oza> information, and changes.
>
> Do you have paperwork on file with the FSF already?
> You ought to, given that you have another patch in the tree; though
> perhaps it was not big enough.
>
> If you do not have paperwork, then you must file it before we can put
> your change in.
>
> If you do have paperwork, I can put it in soon.
>
> Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-07 6:31 ` oza Pawandeep
@ 2012-01-09 16:25 ` Tom Tromey
2012-02-02 6:29 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: Tom Tromey @ 2012-01-09 16:25 UTC (permalink / raw)
To: oza Pawandeep
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
oza> Yes, I have paperwork with FSF; as last change was considerably big enough.
oza> Now I am in a process of getting disclaimer from my new firm;
oza> Will post the things along with necessary paperwork.
Ok. In this case I think we can't put it in until your status is
cleared up. Please let us know when this happens.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2012-01-09 16:25 ` Tom Tromey
@ 2012-02-02 6:29 ` oza Pawandeep
[not found] ` <m38vkfoiut.fsf@fleche.redhat.com>
0 siblings, 1 reply; 128+ messages in thread
From: oza Pawandeep @ 2012-02-02 6:29 UTC (permalink / raw)
To: Tom Tromey
Cc: Yao Qi, Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
The paperwork is over, and Donlad from FSF has confirmed the same.
I have done basic testing of this final patch and everything looks ok.
The patch is ready to go in, please let me know if I have to attach
any paperwork to the mail.
please let me know, how to proceed further.
Regards,
Oza.
On Mon, Jan 9, 2012 at 9:54 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
>
> oza> Yes, I have paperwork with FSF; as last change was considerably big enough.
> oza> Now I am in a process of getting disclaimer from my new firm;
> oza> Will post the things along with necessary paperwork.
>
> Ok. In this case I think we can't put it in until your status is
> cleared up. Please let us know when this happens.
>
> Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 8:20 ` oza Pawandeep
2011-12-03 14:18 ` oza Pawandeep
@ 2011-12-03 15:06 ` oza Pawandeep
2011-12-20 19:05 ` Tom Tromey
2 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-12-03 15:06 UTC (permalink / raw)
To: Tom Tromey; +Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
Hi Tom,
please ignore the previous mail
(forgot add new line in Change log which I is corrected in this mail)
note: the patch is derived from current snapshot gdb-7.3.50.20111203
and Change log as well.
please find the patch below.
diff -urN arm_orig/ChangeLog arm_new/ChangeLog
--- arm_orig/ChangeLog 2011-12-03 18:05:04.000000000 +0530
+++ arm_new/ChangeLog 2011-12-03 19:48:56.000000000 +0530
@@ -1,3 +1,9 @@
+2011-12-03 Oza Pawandeep <oza.pawandeep@gmail.com>
+
+ * arm-linux-tdep.c: Added arm-reversible and process record
+ * arm-tdep.c: arm-reversible-debugging implementation
+ * arm-tdep.h: arm-reversible data structures
+
2011-11-09 Roland McGrath <mcgrathr@google.com>
* configure.ac: Add tool checks for READELF and READELF_FOR_TARGET.
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-12-03 19:28:27.000000000 +0530
@@ -1148,8 +1148,14 @@
simple_displaced_step_free_closure);
set_gdbarch_displaced_step_location (gdbarch, displaced_step_at_entry_point);
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ /* Syscall record. */
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-12-03 20:05:03.000000000 +0530
+++ arm_new/arm-tdep.c 2011-12-03 20:27:30.000000000 +0530
@@ -55,6 +55,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
#include "features/arm-with-iwmmxt.c"
#include "features/arm-with-vfpv2.c"
@@ -10175,3 +10177,2041 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct arm_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct arm_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define INSN_RECORDED(ARM_RECORD) \
+ (0 != ARM_RECORD->reg_rec_count || 0 != ARM_RECORD->mem_rec_count)
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* Record length. */
+ CORE_ADDR addr; /* Memory address. */
+};
+
+/* ARM instruction record contains opcode of current insn
+ and execution state (before entry to decode_insn()),
+ contains list of to-be-modified registers and
+ memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* Address of the insn being decoded. */
+ uint32_t arm_insn; /* Should accommodate thumb. */
+ uint32_t cond; /* Condition code. */
+ uint32_t opcode; /* Insn opcode. */
+ uint32_t decode; /* Insn decode bits. */
+ uint32_t mem_rec_count; /* No of mem records. */
+ uint32_t reg_rec_count; /* No of reg records. */
+ uint32_t *arm_regs; /* Registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* Memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* Checks ARM SBZ and SBO mandatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if (!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+typedef enum
+{
+ ARM_RECORD_STRH=1,
+ ARM_RECORD_STRD
+} arm_record_strx_t;
+
+typedef enum
+{
+ ARM_RECORD=1,
+ THUMB_RECORD,
+ THUMB2_RECORD
+} record_type_t;
+
+
+static int
+arm_record_strx (insn_decode_record *arm_insn_r, uint32_t *record_buf,
+ uint32_t *record_buf_mem, arm_record_strx_t str_type)
+{
+
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval[2]= {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+
+ if (14 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ {
+ /* 1) Handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1,
+ &u_regval[0]);
+ if (ARM_PC_REGNUM == reg_src1)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* Calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (12 == arm_insn_r->opcode || 8 == arm_insn_r->opcode)
+ {
+ /* 2) Store, register offset. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ }
+ else if (11 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 2 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ /* 3) Store, immediate pre-indexed. */
+ /* 5) Store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (15 == arm_insn_r->opcode || 6 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[0] - offset_8;
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (9 == arm_insn_r->opcode || 13 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ /* 4) Store, register pre-indexed. */
+ /* 6) Store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ if (13 == arm_insn_r->opcode || 4 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+ if (ARM_RECORD_STRH == str_type)
+ {
+ *(record_buf_mem) = 2;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if (ARM_RECORD_STRD == str_type)
+ {
+ *(record_buf_mem) = 4;
+ *(record_buf_mem + 1) = tgt_mem_addr;
+ *(record_buf_mem + 2) = 4;
+ *(record_buf_mem + 3) = tgt_mem_addr + 4;
+ arm_insn_r->mem_rec_count = 2;
+ }
+ /* Record Rn also as it changes. */
+ *(record_buf) = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ return 0;
+}
+
+/* Handling ARM extension space insns. */
+
+static int
+arm_record_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0; /* Return value: -1:record failure ; 0:success */
+ uint32_t opcode1 = 0, opcode2 = 0, insn_op1 = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+ uint32_t reg_src1 = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ ULONGEST u_regval = 0;
+
+ /* Handle unconditional insn extension space. */
+
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ if (arm_insn_r->cond)
+ {
+ /* PLD has no affect on architectural state, it just affects
+ the caches. */
+ if (5 == ((opcode1 & 0xE0) >> 5))
+ {
+ /* BLX(1) */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ /* STC2, LDC2, MCR2, MRC2, CDP2: <TBD>, co-processor insn. */
+ }
+
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if (3 == opcode1 && bit (arm_insn_r->arm_insn, 4))
+ {
+ ret = -1;
+ /* Undefined instruction on ARM V5; need to handle if later
+ versions define it. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 24, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+ insn_op1 = bits (arm_insn_r->arm_insn, 20, 23);
+
+ /* Handle arithmetic insn extension space. */
+ if (!opcode1 && 9 == opcode2 && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* Handle MLA(S) and MUL(S). */
+ if (0 <= insn_op1 && 3 >= insn_op1)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= insn_op1 && 15 >= insn_op1)
+ {
+ /* Handle SMLAL(S), SMULL(S), UMLAL(S), UMULL(S). */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 21, 22);
+
+ /* Handle control insn extension space. */
+
+ if (!opcode1 && 2 == opcode2 && !bit (arm_insn_r->arm_insn, 20)
+ && 1 != arm_insn_r->cond && !INSN_RECORDED(arm_insn_r))
+ {
+ if (!bit (arm_insn_r->arm_insn,25))
+ {
+ if (!bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if ((0 == insn_op1) || (2 == insn_op1))
+ {
+ /* MRS. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ else if (1 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ if (1 == insn_op1)
+ {
+ /* BX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else if (3 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BLX. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (5 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* QADD, QSUB, QDADD, QDSUB */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (7 == bits (arm_insn_r->arm_insn, 4, 7))
+ {
+ /* BKPT. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ || 10 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 12 == bits (arm_insn_r->arm_insn, 4, 7)
+ || 14 == bits (arm_insn_r->arm_insn, 4, 7)
+ )
+ {
+ if (0 == insn_op1 || 1 == insn_op1)
+ {
+ /* SMLA<x><y>, SMLAW<y>, SMULW<y>. */
+ /* We dont do optimization for SMULW<y> where we
+ need only Rd. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (2 == insn_op1)
+ {
+ /* SMLAL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1)
+ {
+ /* SMUL<x><y>. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ else
+ {
+ /* MSR : immediate form. */
+ if (1 == insn_op1)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == insn_op1)
+ {
+ /* 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;
+ }
+ }
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 20, 24);
+ insn_op1 = bits (arm_insn_r->arm_insn, 5, 6);
+
+ /* Handle load/store insn extension space. */
+
+ if (!opcode1 && bit (arm_insn_r->arm_insn, 7)
+ && bit (arm_insn_r->arm_insn, 4) && 1 != arm_insn_r->cond
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ /* SWP/SWPB. */
+ if (0 == insn_op1)
+ {
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* Get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRH. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (2 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* LDRD. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = record_buf[0] + 1;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (3 == insn_op1 && !bit (arm_insn_r->arm_insn, 20))
+ {
+ /* STRD. */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRD);
+ }
+ else if (bit (arm_insn_r->arm_insn, 20) && insn_op1 <= 3)
+ {
+ /* LDRH, LDRSB, LDRSH. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if (24 == opcode1 && bit (arm_insn_r->arm_insn, 21)
+ && !INSN_RECORDED(arm_insn_r))
+ {
+ ret = -1;
+ /* Handle coprocessor insn extension space. */
+ }
+
+ /* 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));
+
+
+ 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);
+
+ return ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+arm_record_data_proc_misc_ld_str (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+ ULONGEST u_regval[2] = {0};
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* Data processing insn /multiply insn. */
+ if (9 == arm_insn_r->decode
+ && ((4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)))
+ {
+ /* Handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if (0 == arm_insn_r->opcode || 1 == arm_insn_r->opcode)
+ {
+ /* Handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if (4 <= arm_insn_r->opcode && 7 >= arm_insn_r->opcode)
+ {
+ /* Handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (11 == arm_insn_r->decode || 13 == arm_insn_r->decode))
+ {
+ /* Handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precceded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place; as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21))
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if (9 == arm_insn_r->decode
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handling SWP, SWPB. */
+ /* These insn, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_regval[0];
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (3 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (7 == arm_insn_r->decode && 0x12 == opcode1)
+ {
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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
+ && !bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* Handle enhanced store insns and DSP insns (e.g. LDRD). */
+
+ /* Handle str(x) insn */
+ arm_record_strx(arm_insn_r, &record_buf[0], &record_buf_mem[0],
+ ARM_RECORD_STRH);
+ }
+ else if (1 == arm_insn_r->decode && 0x12 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* Handle BX, branch and link/exchange. */
+ /* Branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == arm_insn_r->decode && 0x16 == opcode1
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* Count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)
+ && (8 == arm_insn_r->opcode || 10 == arm_insn_r->opcode)
+ && sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)
+ && sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0)
+ )
+ {
+ /* Handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+arm_record_data_proc_imm (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode)
+ && 2 == bits (arm_insn_r->arm_insn, 20, 21)
+ && sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1)
+ )
+ {
+ /* Handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* Normal data processing insns. */
+ /* Out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ return -1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+arm_record_ld_st_imm_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ ULONGEST u_regval = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (ARM_PC_REGNUM != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 4:
+ case 0:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* We are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 011 insns. */
+
+static int
+arm_record_ld_st_reg_offset (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ LONGEST s_word;
+ ULONGEST u_regval[2];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* Handle enhanced store insns and LDRD DSP insn,
+ order begins according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* Store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1
+ , &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2
+ , &u_regval[1]);
+ if (15 == reg_src2)
+ {
+ /* If R15 was used as Rn, hence current PC+8. */
+ /* Pre-indexed mode doesnt reach here ; illegal insn. */
+ u_regval[0] = u_regval[0] + 8;
+ }
+ /* Calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[0] + u_regval[1];
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - u_regval[0];
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* Store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* Get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* Get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* Get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_signed (reg_cache, reg_src1, &s_word);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* Offset_12 used as shift. */
+ switch (offset_12)
+ {
+ case 0:
+ /* Offset_12 used as index. */
+ offset_12 = u_regval[0] << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_regval[0] >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_regval[0], 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* This is arithmetic shift. */
+ offset_12 = s_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM,
+ &u_regval[1]);
+ /* Get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_regval[1], 29)) << 31) \
+ | (u_regval[0]) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_regval[0] >> shift_imm) \
+ | (u_regval[0] <<
+ (sizeof(uint32_t) - shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ /* bit U set. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_regval[1] + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_regval[1] - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ /* STR. */
+ case 8:
+ case 12:
+ /* STR. */
+ case 9:
+ case 13:
+ /* STRT. */
+ case 1:
+ case 5:
+ /* STR. */
+ case 0:
+ case 4:
+ record_buf_mem[0] = 4;
+ break;
+
+ /* STRB. */
+ case 10:
+ case 14:
+ /* STRB. */
+ case 11:
+ case 15:
+ /* STRBT. */
+ case 3:
+ case 7:
+ /* STRB. */
+ case 2:
+ case 6:
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if (9 == arm_insn_r->opcode || 11 == arm_insn_r->opcode
+ || 13 == arm_insn_r->opcode || 15 == arm_insn_r->opcode
+ || 0 == arm_insn_r->opcode || 2 == arm_insn_r->opcode
+ || 4 == arm_insn_r->opcode || 6 == arm_insn_r->opcode
+ || 1 == arm_insn_r->opcode || 3 == arm_insn_r->opcode
+ || 5 == arm_insn_r->opcode || 7 == arm_insn_r->opcode
+ )
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode,and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+arm_record_ld_st_multiple (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16] = {0}, register_count = 0, register_bits = 0;
+ uint32_t reg_src1 = 0, addr_mode = 0, no_of_regs = 0;
+ uint32_t start_address = 0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval[2] = {0};
+
+ /* This mode is exclusively for load and store multiple. */
+ /* Handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
+ without optimization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDM (1,2,3) where LDM (3) changes CPSR too. */
+
+ if (bit (arm_insn_r->arm_insn, 20) && !bit (arm_insn_r->arm_insn, 22))
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ no_of_regs = 15;
+ }
+ else
+ {
+ register_bits = bits (arm_insn_r->arm_insn, 0, 14);
+ no_of_regs = 14;
+ }
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* Extra space for Base Register and CPSR; wihtout optimization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = register_count + 2;
+
+ for (register_count = 0; register_count < no_of_regs; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* Register_count gives total no of registers
+ and dually working as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+
+ }
+ else
+ {
+ /* It handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* Get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch (addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_regval[0]) - (register_count * 4) + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_regval[0];
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_regval[0]) - (register_count * 4);
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_regval[0] + 4;
+ arm_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("no decoding pattern found");
+ break;
+ }
+
+ /* Base register also changes; based on condition and W bit. */
+ /* We save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+arm_record_b_bl (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8];
+
+ /* Handle B, BL, BLX(1) insns. */
+ /* B simply branches so we do nothing here. */
+ /* Note: BLX(1) doesnt fall here but instead it falls into
+ extension space. */
+ if (bit (arm_insn_r->arm_insn, 24))
+ {
+ record_buf[0] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+arm_record_coproc (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+arm_record_coproc_data_proc (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+
+ /* Handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ ret = -1;
+ }
+ }
+
+ 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 ret;
+}
+
+/* Handling opcode 000 insns. */
+
+static int
+thumb_record_shift_add_sub (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_add_sub_cmp_mov (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* Handling opcode 010 insns. */
+
+static int
+thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+ ULONGEST u_regval[2] = {0};
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* Handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if (opcode2 >= 12 && opcode2 <= 15)
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode2 >= 8 && opcode2 <= 10)
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval[0]);
+ regcache_raw_read_unsigned (reg_cache, reg_src2, &u_regval[1]);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] = u_regval[0] + u_regval[1];
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* Handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* Branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* Format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 001 insns. */
+
+static int
+thumb_record_ld_st_imm_offset (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 100 insns. */
+
+static int
+thumb_record_ld_st_stack (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_SP_REGNUM, &u_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 101 insns. */
+
+static int
+thumb_record_misc (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+ uint32_t reg_src1;
+
+ ULONGEST u_regval = 0;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ regcache_raw_read_unsigned (reg_cache, ARM_PC_REGNUM, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count));
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* Handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* According to high vector configuration PC is set. */
+ /* User hits breakpoint and type reverse, in that case, we need
to go back with
+ previous CPSR and Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* We need to save SPSR value, which is not yet done. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
+ thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return 0;
+}
+
+/* Handling opcode 110 insns. */
+
+static int
+thumb_record_ldm_stm_swi (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ ULONGEST u_regval = 0;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* It handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* Get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ regcache_raw_read_unsigned (reg_cache, reg_src1, &u_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_regval;
+ thumb_insn_r->mem_rec_count = register_count;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* Handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ ret = tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B (1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
+ record_buf_mem);
+
+ return ret;
+}
+
+/* Handling opcode 111 insns. */
+
+static int
+thumb_record_branch (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t bits_h = 0;
+
+ bits_h = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (2 == bits_h || 3 == bits_h)
+ {
+ /* BL */
+ record_buf[0] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == bits_h)
+ {
+ /* BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ /* B(2) is automatically taken care in process_record, as PC is
+ saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+
+typedef int (*sti_arm_hdl_fp_t) (insn_decode_record*);
+
+/* Decode arm/thumb insn depending on condition cods and opcodes; and
+ dispatch it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, record_type_t record_type,
+ uint32_t insn_size)
+{
+
+ /* (Starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static const sti_arm_hdl_fp_t const arm_handle_insn[8] =
+ {
+ arm_record_data_proc_misc_ld_str, /* 000. */
+ arm_record_data_proc_imm, /* 001. */
+ arm_record_ld_st_imm_offset, /* 010. */
+ arm_record_ld_st_reg_offset, /* 011. */
+ arm_record_ld_st_multiple, /* 100. */
+ arm_record_b_bl, /* 101. */
+ arm_record_coproc, /* 110. */
+ arm_record_coproc_data_proc /* 111. */
+ };
+
+ /* (Starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static const sti_arm_hdl_fp_t const thumb_handle_insn[8] =
+ { \
+ thumb_record_shift_add_sub, /* 000. */
+ thumb_record_add_sub_cmp_mov, /* 001. */
+ thumb_record_ld_st_reg_offset, /* 010. */
+ thumb_record_ld_st_imm_offset, /* 011. */
+ thumb_record_ld_st_stack, /* 100. */
+ thumb_record_misc, /* 101. */
+ thumb_record_ldm_stm_swi, /* 110. */
+ thumb_record_branch /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_RECORD == record_type)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ ARM_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ 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))
+ {
+ ret = arm_handle_insn[insn_id] (arm_record);
+ }
+ }
+ else if (THUMB_RECORD == record_type)
+ {
+ /* As thumb does not have condition codes, we set negative. */
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer
(&u_buf.buf[0],
+ THUMB_INSN_SIZE_BYTES ,
+ gdbarch_byte_order (arm_record->gdbarch));
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_RECORD == record_type)
+ {
+ printf_unfiltered (_("Process record doesnt support thumb32 instruction "
+ "0x%0x at address %s.\n"),arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
+ arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* Throw assertion. */
+ gdb_assert (0);
+ }
+
+ return ret;
+}
+
+
+/* Cleans up local record registers and memory allocations. */
+
+void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->arm_regs);
+ xfree (record->arm_mems);
+}
+
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list".
+ Return -1 if something is wrong. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0; /* function return value: -1:record failure ;
0:success */
+ ULONGEST t_bit = 0, insn_id = 0;
+
+ ULONGEST u_regval = 0;
+
+ insn_decode_record arm_record;
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* Check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ regcache_raw_read_unsigned (arm_record.regcache, ARM_PS_REGNUM, &u_regval);
+
+ if (!(u_regval & t_bit))
+ {
+ /* We are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_RECORD, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ insn_id = bits (arm_record.arm_insn, 11, 15);
+ /* is it thumb2 insn? */
+ if ((0x1D == insn_id) || (0x1E == insn_id) || (0x1F == insn_id))
+ {
+ ret = decode_insn (&arm_record, THUMB2_RECORD,
THUMB_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* We are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_RECORD,
THUMB2_INSN_SIZE_BYTES);
+ }
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache ,
+ arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* Record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+
+ deallocate_reg_mem (&arm_record);
+
+ return ret;
+}
+
+
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-12-03 18:06:39.000000000 +0530
+++ arm_new/arm-tdep.h 2011-12-03 17:52:28.000000000 +0530
@@ -201,6 +201,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -330,6 +333,8 @@
instruction? */
extern int arm_pc_is_thumb (struct gdbarch *, CORE_ADDR);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-12-03 8:20 ` oza Pawandeep
2011-12-03 14:18 ` oza Pawandeep
2011-12-03 15:06 ` oza Pawandeep
@ 2011-12-20 19:05 ` Tom Tromey
2 siblings, 0 replies; 128+ messages in thread
From: Tom Tromey @ 2011-12-20 19:05 UTC (permalink / raw)
To: oza Pawandeep
Cc: Petr Hluzín, paawan oza, gdb-patches, chandra krishnappa
>>>>> "Oza" == oza Pawandeep <oza.pawandeep@gmail.com> writes:
Oza> 2) I could not write changelog entry because I have been getting
Oza> commments, and moreover I was not sure whether I should get changelog
Oza> entry from latest gdb 7.3 or latest current working version of gdb ? I
Oza> think later is true in my understanding.
Oza> I will include changelog this time; sorry for having you point it out
Oza> in all reviews.
Yeah, ChangeLogs are a bit of a pain. There are various ways to deal
with them, e.g., keeping them in a separate file until checkin time.
I use different techniques depending on the context. Anyway, I'm sorry
about it, but for the time being it is just a cost of working on GDB.
Tom
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-08-10 17:09 chandra krishnappa
2011-08-11 1:34 ` Yao Qi
0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-08-10 17:09 UTC (permalink / raw)
To: gdb-patches, Yao Qi
[-- Attachment #1: Type: text/plain, Size: 2450 bytes --]
Kindly suggest some steps or operations which confirms the basic host and target communication is working fine..
I am stuck up with connection itself....
1. Copied "gdbserver" ( ARM compiled ) on to target board.
./gdbserver 192.168.1.2:9876 ../from_host/test_arm
2. start gdb from host system
personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()
(gdb) continue
Continuing.
Cannot access memory at address 0x0
[Inferior 1 (Remote target) exited normally]
On the remote target the complete program is just executing and showing the results...
Not able to debug the program step by step not even any break..
Am searching for some step by step host : target gdb setup through cris-cross cables...
I dont have serial port on my laptop, generally there are more articles on serial connections... seems that used by most ..
Parallel I am looking at running dejagnu testsuite for x86 locally.. thinking of extend the x86 execution method of connection of host and target for ARM Board..
http://ftp.gnu.org/old-gnu/Manuals/gdb-5.1.1/html_node/gdb_130.html
the things in the above link, I have followed... later stuffs are not clear to me.. Logs attached for the reference...
Thanks & Regards,
-Chandra K
--- On Thu, 7/14/11, Yao Qi <yao@codesourcery.com> wrote:
> From: Yao Qi <yao@codesourcery.com>
> Subject: Re: [PATCH] arm reversible : <phase_2_complete>
> To: gdb-patches@sourceware.org
> Date: Thursday, July 14, 2011, 11:57 AM
> On 07/14/2011 09:39 AM, chandra
> krishnappa wrote:
> > 2. gdb test development active members, with whom I
> may seek help??
>
> You may have a look at this page about writing test cases
> for gdb
> http://sourceware.org/gdb/wiki/GDBTestcaseCookbook
>
> --
> Yao (齐尧)
>
[-- Attachment #2: Debugging_Process --]
[-- Type: application/octet-stream, Size: 302 bytes --]
test.c
compile c program and copy on to target board.
( linux$ arm-none-linux-gnueabi-gcc-4.5.1 -g test.c -o test_arm )
--------
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int i=0;
int j;
for (j=0;j<=10;j++) {
i=(int)random();
printf("i=%d when j=%d\n",i,j);
}
return 0;
}
[-- Attachment #3: Host_messages --]
[-- Type: application/octet-stream, Size: 3319 bytes --]
Host PC ( 192.168.1.2 )
personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()
(gdb) break main
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) bt
#0 0x400007b0 in ?? ()
Cannot access memory at address 0x0
#1 0x00000000 in ?? ()
(gdb) target record
(gdb) break main
No symbol table is loaded. Use the "file" command.
Make breakpoint pending on future shared library load? (y or [n]) n
(gdb) continue
Continuing.
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) y
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
GNU gdb (GDB) 7.3
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
warning: Can not parse XML target description; XML support was disabled at compile time
0x400007b0 in ?? ()
(gdb) continue
Continuing.
Cannot access memory at address 0x0
[Inferior 1 (Remote target) exited normally]
(gdb) target remote 192.168.1.6:9876
Remote debugging using 192.168.1.6:9876
0x400007b0 in ?? ()
(gdb) target record
(gdb) continue
Continuing.
Cannot access memory at address 0x0
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Quit this debugging session? (y or n) n
regcache.c:178: internal-error: register_size: Assertion `regnum >= 0 && regnum < (gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch))' failed.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
Create a core file of GDB? (y or n) n
0x400007b0 in ?? ()
[-- Attachment #4: Target_messages --]
[-- Type: application/octet-stream, Size: 2084 bytes --]
Target Board ( ARM ) 192.168.1.6
-----
[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
Process ../from_host/test_arm created; pid = 644
Listening on port 9876
Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10
Child exited with status 0
GDBserver exiting
[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
Process ../from_host/test_arm created; pid = 648
Listening on port 9876
Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10
Child exited with status 0
GDBserver exiting
[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
Process ../from_host/test_arm created; pid = 652
Listening on port 9876
Remote debugging from host 192.168.1.2
Killing all inferiors
[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
Process ../from_host/test_arm created; pid = 656
Listening on port 9876
Remote debugging from host 192.168.1.2
readchar: Got EOF
Remote side has terminated connection. GDBserver will reopen the connection.
Listening on port 9876
Remote debugging from host 192.168.1.2
i=1804289383 when j=0
i=846930886 when j=1
i=1681692777 when j=2
i=1714636915 when j=3
i=1957747793 when j=4
i=424238335 when j=5
i=719885386 when j=6
i=1649760492 when j=7
i=596516649 when j=8
i=1189641421 when j=9
i=1025202362 when j=10
Child exited with status 0
GDBserver exiting
[root@EmbedSky gdbserver]# ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
Process ../from_host/test_arm created; pid = 660
Listening on port 9876
Remote debugging from host 192.168.1.2
Killing all inferiors
[root@EmbedSky gdbserver]#
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-08-10 17:09 chandra krishnappa
@ 2011-08-11 1:34 ` Yao Qi
0 siblings, 0 replies; 128+ messages in thread
From: Yao Qi @ 2011-08-11 1:34 UTC (permalink / raw)
To: chandra krishnappa; +Cc: gdb-patches
On 08/11/2011 01:08 AM, chandra krishnappa wrote:
> Kindly suggest some steps or operations which confirms the basic host and target communication is working fine..
>
> I am stuck up with connection itself....
>
> 1. Copied "gdbserver" ( ARM compiled ) on to target board.
> ./gdbserver 192.168.1.2:9876 ../from_host/test_arm
>
> 2. start gdb from host system
> personal@computer:~/Desktop/gdb-7.3/gdb-7.3$ ./gdb/gdb
> GNU gdb (GDB) 7.3
> Copyright (C) 2011 Free Software Foundation, Inc.
> License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
> This is free software: you are free to change and redistribute it.
> There is NO WARRANTY, to the extent permitted by law. Type "show copying"
> and "show warranty" for details.
> This GDB was configured as "--host=i686-pc-linux-gnu --target=arm-linux".
> For bug reporting instructions, please see:
> <http://www.gnu.org/software/gdb/bugs/>.
> (gdb) target remote 192.168.1.6:9876
> Remote debugging using 192.168.1.6:9876
> warning: Can not parse XML target description; XML support was disabled at compile time
> 0x400007b0 in ?? ()
> (gdb) continue
> Continuing.
> Cannot access memory at address 0x0
> [Inferior 1 (Remote target) exited normally]
>
>
Your step 2 looks incorrect to me. You should fire gdb with debuggee
program, like ./gdb test_arm.
>
> On the remote target the complete program is just executing and showing the results...
>
> Not able to debug the program step by step not even any break..
>
> Am searching for some step by step host : target gdb setup through cris-cross cables...
>
> I dont have serial port on my laptop, generally there are more articles on serial connections... seems that used by most ..
>
Your connection between host gdb and gdbserver works. serial port is
usually used to connect with bare mental board which doesn't have
network connection. You don't need to have a serial port in this case.
>
> Parallel I am looking at running dejagnu testsuite for x86 locally.. thinking of extend the x86 execution method of connection of host and target for ARM Board..
>
dejagnu naturally supports remote testing, so you don't have to invent
the wheel again. What you need here is a board file. Here is an example,
# gdbserver running over ssh.
load_generic_config "gdbserver"
process_multilib_options ""
# The default compiler for this target on host machine.
set_board_info compiler
"/home/yao/toolchain/fsf-gcc-trunk/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-gcc"
set_board_info rsh_prog /usr/bin/ssh
set_board_info rcp_prog /usr/bin/scp
set_board_info protocol standard
set_board_info hostname your.target.host.name or ip address
set_board_info username yao
# gdbserver's location on your target board.
set_board_info gdb_server_prog /home/yao/gdbserver
# We will be using the standard GDB remote protocol
set_board_info gdb_protocol "remote"
# Use techniques appropriate to a stub
set_board_info use_gdb_stub 1
# This gdbserver can only run a process once per session.
set_board_info gdb,do_reload_on_run 1
# There's no support for argument-passing (yet).
set_board_info noargs 1
# Can't do input (or output) in the current gdbserver.
set_board_info gdb,noinferiorio 1
# Can't do hardware watchpoints, in general
set_board_info gdb,no_hardware_watchpoints 1
If your board has ssh, you can use this board file with minor changes
(such as location of gdbserver and gcc). If your board doesn't have
ssh, IIRC, dejagnu also support telnet and rsh to access remote boards.
You can find more from google.
You can save the board file as arm.exp, or whatever you prefer, and set
dejagnu a little bit so that this board file can be used when you run
`make check'. Please reference this wiki page on how to use a new board
file in gdb tests.
Testing gdbserver in a native configuration
http://sourceware.org/gdb/wiki/TestingGDB#Testing_gdbserver_in_a_native_configuration
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 128+ messages in thread
[parent not found: <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>]
* Re: [PATCH] arm reversible : <phase_2_complete>
[not found] <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>
@ 2011-06-06 17:42 ` chandra krishnappa
2011-07-05 8:47 ` oza Pawandeep
0 siblings, 1 reply; 128+ messages in thread
From: chandra krishnappa @ 2011-06-06 17:42 UTC (permalink / raw)
To: paawan oza, gdb-patches
Hi,
I will be working for testing the patch of ARM reversible debugging feature. Will be sending the test code for review once I develop the same.
This is to inform that I will be working on this task, and anybody has any pointers or comments to provide, its welcome.
I will pick up the patch from here from the mailing list or will work with Paawan Oza to get the latest build of arm reversible.
Thanks & Regards,
-Chandra K
--- On Fri, 3/6/11, "paawan oza" <paawan1982@yahoo.com> wrote:
> From: paawan oza <paawan1982@yahoo.com>
> Date: Fri, Jun 3, 2011 at 1:21 PM
> Subject: Re: [PATCH] arm reversible :
> <phase_2_complete>
> To: Tom Tromey <tromey@redhat.com>
> Cc: gdb-patches@sourceware.org,
> Petr Hluzín <petr.hluzin@gmail.com>
>
>
> Hi Tom,
>
> Fixed almost all comments.
> any more comments are welcome make this patch ok, if ARM
> person can have a look
> at it it would be great.
>
> PATCH STARTS
> ------------------------------------diff -urN
> arm_orig/arm-linux-tdep.c
> arm_new/arm-linux-tdep.c
> --- arm_orig/arm-linux-tdep.c 2011-03-03
> 09:21:13.000000000 +0530
> +++ arm_new/arm-linux-tdep.c 2011-05-07
> 14:20:31.000000000 +0530
> @@ -998,6 +998,9 @@
> set_gdbarch_fetch_tls_load_module_address (gdbarch,
>
> svr4_fetch_objfile_link_map);
>
> + /* Enable process record. */
> + set_gdbarch_process_record (gdbarch,
> arm_process_record);
> +
> tramp_frame_prepend_unwinder (gdbarch,
>
> &arm_linux_sigreturn_tramp_frame);
> tramp_frame_prepend_unwinder (gdbarch,
> @@ -1025,6 +1028,8 @@
>
>
> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
> +
> + tdep->arm_swi_record = NULL;
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes.
> */
> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
> --- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000
> +0530
> +++ arm_new/arm-tdep.c 2011-06-03 13:16:35.000000000
> +0530
> @@ -54,6 +54,8 @@
> #include "gdb_assert.h"
> #include "vec.h"
>
> +#include "record.h"
> +
> #include "features/arm-with-m.c"
>
> static int arm_debug;
> @@ -7929,3 +7931,1763 @@
> NULL, /* FIXME: i18n: "ARM debugging
> is %s. */
> &setdebuglist,
> &showdebuglist);
> }
> +
> +
> +
> +/* ARM-reversible process record data structures. */
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define THUMB2_INSN_SIZE_BYTES 4
> +
> +#define INSN_S_L_BIT_NUM 20
> +
> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int reg_len = 0; reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) *
> (reg_len)); \
> + while (reg_len) \
> + { \
> + REGS[reg_len - 1] = RECORD_BUF[reg_len -
> 1]; \
> + reg_len--; \
> + } \
> + } \
> + } \
> +while (0)
> +
> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
> +do \
> + { \
> + unsigned int mem_len = 0; mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = (struct arm_mem_r *)xmalloc \
> + (sizeof(struct arm_mem_r) *
> (mem_len)); \
> + while (mem_len) \
> + { \
> + MEMS[mem_len - 1].addr =
> RECORD_BUF[(mem_len * 2) - 1]; \
> + MEMS[mem_len - 1].len =
> RECORD_BUF[(mem_len * 2) - 2]; \
> + mem_len--; \
> + } \
> + } \
> + } \
> +while (0)
> +
> +
> +/* ARM memory record structure. */
> +struct arm_mem_r
> +{
> + uint32_t len; /* Record length. */
> + CORE_ADDR addr; /* Memory address. */
> +};
> +
> +/* ARM instruction record contains opcode of current insn
> and execution state
> (before entry to
>
> +decode_insn() ), contains list of to-be-modified registers
> and memory blocks
> (on return from
>
> +decode_insn() ). */
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr; /* Address of the
> insn being decoded. */
> + uint32_t arm_insn; /* Should
> accommodate thumb. */
> + uint32_t cond; /* Condition
> code. */
> + uint32_t opcode; /* Insn opcode.
> */
> + uint32_t decode; /* Insn decode
> bits. */
> + uint32_t mem_rec_count; /* No of mem recors
> */
> + uint32_t reg_rec_count; /* No of reg records
> */
> + uint32_t *arm_regs; /* Registers to be
> saved for this record. */
> + struct arm_mem_r *arm_mems; /* Memory to be saved
> for this record. */
> +} insn_decode_record;
> +
> +
> +/* Checks ARM SBZ and SBO mendatory fields. */
> +
> +static int
> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len,
> uint32_t sbo)
> +{
> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) +
> (len - 1));
> +
> + if (!len)
> + return 1;
> +
> + if(!sbo)
> + ones = ~ones;
> +
> + while (ones)
> + {
> + if (!(ones & sbo))
> + {
> + return 0;
> + }
> + ones = ones >> 1;
> + }
> + return 1;
> +}
> +
> +/* Handling ARM extension space insns. */
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_insn_r)
> +{
> + uint32_t ret = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if ((3 == opcode1) && (bit
> (arm_insn_r->arm_insn, 4)))
> + {
> + ret = -1;
> + /* Undefined instruction on ARM V5; need to
> handle if later versions
> + define it. */
> + }
> +
> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
> +
> + if ((!opcode1) && (9 == opcode2))
> + {
> + ret = -1;
> + /* Handle arithmetic insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + if ((!opcode1) && (2 == opcode2) &&
> (!bit (arm_insn_r->arm_insn, 20)))
> + {
> + ret = -1;
> + /* Handle control insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
> + if ((!opcode1) && (bit
> (arm_insn_r->arm_insn, 7)) \
> + &&
> (bit(arm_insn_r->arm_insn, 4)))
> + {
> + ret = -1;
> + /* Handle load/store insn extension space. */
> + }
> +
> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
> + if ((24 == opcode1) && (bit
> (arm_insn_r->arm_insn, 21)))
> + {
> + ret = -1;
> + /* Handle coprocessor insn extension space. */
> + }
> +
> + /* To be done for ARMv5 and later; as of now we return
> -1. */
> + if (-1 == ret)
> + 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 ret;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0,
> tgt_mem_addr = 0;
> + uint32_t opcode1 = 0;
> +
> + memset(&u_buf, 0, sizeof (u_buf));
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
> +
> + /* Data processing insn /multiply insn. */
> + if ((9 == arm_insn_r->decode)
> + && (((4 <= arm_insn_r->opcode)
> && (7 >= arm_insn_r->opcode))
> + || ((0 == arm_insn_r->opcode) || (1 ==
> arm_insn_r->opcode))))
> + {
> + /* Handle multiply instructions. */
> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
> + if ((0 == arm_insn_r->opcode) || (1 ==
> arm_insn_r->opcode))
> + {
> + /* Handle MLA and MUL. */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else if ((4 <= arm_insn_r->opcode)
> && (7 >= arm_insn_r->opcode))
> + {
> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 16, 19);
> + record_buf[1] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + record_buf[2] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 3;
> + }
> + }
> + else if ((bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM))
> + && ((11 == arm_insn_r->decode) ||
> (13 == arm_insn_r->decode)))
> + {
> + /* Handle misc load insns, as 20th bit (L =
> 1). */
> + /* LDR insn has a capability to do branching,
> if
> + MOV LR, PC is preccedded by LDR
> insn having Rn as R15
> + in that case, it emulates
> branch and link insn, and hence we
> + need to save CSPR and PC as
> well. I am not sure this is right
>
> + place as opcode = 010 LDR insn
> make this happen, if R15 was
> + used. */
> + reg_dest = bits (arm_insn_r->arm_insn, 12,
> 15);
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode))
> + && (sbo_sbz (arm_insn_r->arm_insn, 5,
> 12, 0))
> + && (sbo_sbz (arm_insn_r->arm_insn, 13,
> 4, 1))
> + && (2 == bits (arm_insn_r->arm_insn,
> 20, 21)))
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* 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;
> + }
> + }
> + else if ((9 == arm_insn_r->decode)
> + && ((8 == arm_insn_r->opcode)
> || (10 == arm_insn_r->opcode))
> + && (!bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM)))
> + {
> + /* Handling SWP, SWPB. */
> + /* These insns, changes register and memory as
> well. */
> + /* SWP or SWPB insn. */
> + /* Get memory address given by Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + /* SWP insn ?, swaps word. */
> + if (8 == arm_insn_r->opcode)
> + {
> + record_buf_mem[0] = 4;
> + }
> + else
> + {
> + /* SWPB insn, swaps only byte. */
> + record_buf_mem[0] = 1;
> + }
> + record_buf_mem[1] = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count = 1;
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((3 == arm_insn_r->decode) && (0x12
> == opcode1)
> + && (sbo_sbz
> (arm_insn_r->arm_insn, 9, 12, 1)))
> + {
> + /* Handle BLX, branch and link/exchange. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /* Branch is chosen by setting T bit of CSPR,
> bitp[0] of Rm,
> + and R14 stores the return
> address. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if ((7 == arm_insn_r->decode) && (0x12
> == opcode1))
> + {
> + /* Handle enhanced software breakpoint insn, BKPT
> */
> + /* CPSR is changed to be executed in ARM state,
> disabling normal
> + interrupts, entering abort mode.
> */
> + /* Accorindly to high vector configuration PC is
> set accordingly */
> + /* What if user hit breakpoint and type reverse,
> in
> + that case, we need to go back with
> previous CPSR and
> + Program Counter. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + 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)
> + && (!bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM)))
> + {
> + /* Handle enhanced store insns and DSP insns (e.g.
> LDRD)
> + let us begin according to addressing modes
> for store insns
> + STRH insn, addresing modes are taken
> following. */
> + if ((14 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode))
> + {
> + /* 1) Handle misc store, immediate offset.
> */
> + immed_low = bits (arm_insn_r->arm_insn, 0,
> 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8,
> 11);
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + if (15 == reg_src1)
> + {
> + /* If R15 was used as Rn, hence current
> PC+8. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + offset_8 = (immed_high << 4) |
> immed_low;
> + /* Calculate target store address. */
> + if (14 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((12 == arm_insn_r->opcode) || (8 ==
> arm_insn_r->opcode))
> + {
> + /* 2) Store, register offset. */
> + /* Get Rm. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0,
> 3);
> + /* Get Rn. */
> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> + ,
> &u_buf[1].unsigned_regval);
>
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence current
> PC+8. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn +/- Rm,
> register offset. */
> + if (12 == arm_insn_r->opcode)
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval
> - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + }
> + else if ((11 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (2 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> + {
> + /* 3) Store, immediate pre-indexed. */
> + /* 5) Store, immediate post-indexed. */
> + immed_low = bits (arm_insn_r->arm_insn, 0,
> 3);
> + immed_high = bits (arm_insn_r->arm_insn, 8,
> 11);
> + offset_8 = (immed_high << 4) |
> immed_low;
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned(reg_cache,
> reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm,
> register offset. */
> + if ((15 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> + offset_8;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> - offset_8;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((9 == arm_insn_r->opcode) || (13 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> + {
> + /* 4) Store, register pre-indexed. */
> + /* 6) Store, register post -indexed. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 0,
> 3);
> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> + ,
> &u_buf[1].unsigned_regval);
> + /* Calculate target store address, Rn +/- Rm,
> register offset. */
> + if ((13 == arm_insn_r->opcode) || (4 ==
> arm_insn_r->opcode))
> + {
> + tgt_mem_addr = u_buf[0].unsigned_regval
> + u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf[1].unsigned_regval
> - u_buf[0].unsigned_regval;
> + }
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> + /* Record Rn also as it changes. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 16, 19);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + /* DSP insns (e.g. LDRD) TBD. */
> + }
> + else if ((1 == arm_insn_r->decode) && (0x12
> == opcode1)
> + && sbo_sbz
> (arm_insn_r->arm_insn, 9, 12, 1))
> + {
> + /* Handle BX, branch and link/exchange. */
> + /* Branch is chosen by setting T bit of CSPR,
> bitp[0] of Rm. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((1 == arm_insn_r->decode) && (0x16
> == opcode1)
> + && (sbo_sbz
> (arm_insn_r->arm_insn, 9, 4, 1))
> + && (sbo_sbz
> (arm_insn_r->arm_insn, 17, 4, 1)))
> + {
> + /* Count leading zeros: CLZ. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if ((!bit (arm_insn_r->arm_insn,
> INSN_S_L_BIT_NUM))
> + && ((8 == arm_insn_r->opcode) ||
> (10 == arm_insn_r->opcode))
> + && (sbo_sbz
> (arm_insn_r->arm_insn, 17, 4, 1))
> + && (sbo_sbz
> (arm_insn_r->arm_insn, 1, 12, 0))
> + )
> + {
> + /* Handle MRS insn. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn
> modifies destination
> + register, which is specified by
> 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + gdb_assert_not_reached ("no decoding pattern
> found");
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +arm_handle_data_proc_imm_insn (insn_decode_record
> *arm_insn_r)
> +{
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + if (((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode))
> + && (2 == bits (arm_insn_r->arm_insn,
> 20, 21))
> + && (sbo_sbz (arm_insn_r->arm_insn,
> 13, 4, 1))
> + )
> + {
> + /* Handle MSR insn. */
> + if (9 == arm_insn_r->opcode)
> + {
> + /*CSPR is going to be changed. */
> + record_buf[0] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* SPSR is going to be changed. */
> + }
> + }
> + else if (arm_insn_r->opcode <= 15)
> + {
> + /* Normal data processing insns. */
> + /* Out of 11 shifter operands mode, all the insn
> modifies destination
> + register, which is specified by
> 13-16 decode. */
> + record_buf[0] = bits (arm_insn_r->arm_insn,
> 12, 15);
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + gdb_assert_not_reached ("no decoding pattern
> found");
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +arm_handle_ld_st_imm_offset_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0 , reg_dest = 0;
> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + memset(&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12,
> 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn
> having Rn as R15
> + in that case, it emulates branch and
> link insn, and hence we
> + need to save CSPR and PC as well.
> */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if ((8 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> + || (12 == arm_insn_r->opcode) || (14 ==
> arm_insn_r->opcode)
> + || (9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* Store, immediate offset, immediate
> pre-indexed,
> + immediate post-indexed.
> */
> + reg_src1 = bits (arm_insn_r->arm_insn,
> 16, 19);
> + offset_12 = bits (arm_insn_r->arm_insn,
> 0, 11);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + ,
> &u_buf.unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr = u_buf.unsigned_regval
> + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr = u_buf.unsigned_regval -
> offset_12;
> + }
> +
> + switch(arm_insn_r->opcode)
> + {
> + case 8:
> + case 12:
> + case 9:
> + case 13:
> + case 1:
> + case 5:
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + case 10:
> + case 14:
> + case 11:
> + case 15:
> + case 3:
> + case 7:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached ("Invalid
> addressing mode for insn");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* We are handling pre-indexed mode;
> post-indexed mode;
> + where Rn is
> going to be changed. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 011 insns. */
> +
> +static int
> +arm_handle_ld_st_reg_offset_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0,
> tgt_mem_addr = 0;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + struct
> + {
> + LONGEST signed_word;
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset(&u_buf, 0, sizeof (u_buf));
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 21, 24);
> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
> 4, 7);
> +
> + /* Handle enhanced store insns and LDRD DSP insn,
> + let us begin according to addressing modes for
> store insns
> + STRH insn. */
> +
> + /* LDR or STR? */
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + reg_dest = bits (arm_insn_r->arm_insn, 12,
> 15);
> + /* LDR insn has a capability to do branching, if
> + MOV LR, PC is precedded by LDR insn
> having Rn as R15
> + in that case, it emulates branch and
> link insn, and hence we
> + need to save CSPR and PC as well.
> */
> + if (15 != reg_dest)
> + {
> + record_buf[0] = bits
> (arm_insn_r->arm_insn, 12, 15);
> + arm_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + record_buf[0] = reg_dest;
> + record_buf[1] = ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if ((8 == arm_insn_r->opcode) || (10 ==
> arm_insn_r->opcode)
> + || (12 == arm_insn_r->opcode) || (14 ==
> arm_insn_r->opcode)
> + || (9 == arm_insn_r->opcode) || (11 ==
> arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15 ==
> arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + if (! bits (arm_insn_r->arm_insn, 4, 11))
> + {
> + /* Store insn, register offset and
> register pre-indexed,
> + register
> post-indexed. */
> + /* Get Rm. */
> + reg_src1 = bits
> (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits
> (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> ,
> &u_buf[1].unsigned_regval);
>
> + if (15 == reg_src2)
> + {
> + /* If R15 was used as Rn, hence
> current PC+8. */
> + /* Pre-indexed mode doesnt reach
> here ; illegal insn. */
> + u_buf[0].unsigned_regval =
> u_buf[0].unsigned_regval + 8;
> + }
> + /* Calculate target store address, Rn
> +/- Rm, register offset. */
> + /* U == 1. */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr =
> u_buf[0].unsigned_regval +
> u_buf[1].unsigned_regval;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval -
> u_buf[0].unsigned_regval;
> + }
> +
> + switch(arm_insn_r->opcode)
> + {
> + case 8:
> + case 12:
> + case 9:
> + case 13:
> + case 1:
> + case 5:
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + case 10:
> + case 14:
> + case 11:
> + case 15:
> + case 3:
> + case 7:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11
> == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15
> == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in
> pre-indexed mode and
> +
> post-indexed mode as well. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + else
> + {
> + /* Store insn, scaled register offset;
> scaled pre-indexed. */
> + offset_12 = bits
> (arm_insn_r->arm_insn, 5, 6);
> + /* Get Rm. */
> + reg_src1 = bits
> (arm_insn_r->arm_insn, 0, 3);
> + /* Get Rn. */
> + reg_src2 = bits
> (arm_insn_r->arm_insn, 16, 19);
> + /* Get shift_imm. */
> + shift_imm = bits
> (arm_insn_r->arm_insn, 7, 11);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> +
> , &u_buf[0].unsigned_regval);
> + regcache_raw_read_signed (reg_cache,
> reg_src1
> +
> , &u_buf[0].signed_word);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + /* Offset_12 used as shift. */
> + switch(offset_12)
> + {
> + case 0:
> + /* Offset_12 used as index.
> */
> + offset_12 =
> u_buf[0].unsigned_regval << shift_imm;
> + break;
> +
> + case 1:
> + offset_12 =
> (!shift_imm)?0:u_buf[0].unsigned_regval >>
> shift_imm;
>
> + break;
> +
> + case 2:
> + if (!shift_imm)
> + {
> + if (bit
> (u_buf[0].unsigned_regval, 31))
> + {
> + offset_12 =
> 0xFFFFFFFF;
> + }
> + else
> + {
> + offset_12 = 0;
> + }
> + }
> + else
> + {
> + /* This is arithmetic
> shift. */
> + offset_12 =
> u_buf[0].signed_word >> shift_imm;
> + }
> + break;
> +
> + case 3:
> + if (!shift_imm)
> + {
> +
> regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
> +
> , &u_buf[1].unsigned_regval);
> + /* Get C flag value and
> shift it by 31. */
> + offset_12 = (((bit
> (u_buf[1].unsigned_regval, 29)) << 31)
> \
> + |
> (u_buf[0].unsigned_regval) >> 1);
> + }
> + else
> + {
> + offset_12 =
> (u_buf[0].unsigned_regval >> shift_imm) \
> + |
> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
> shift_imm));
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> + break;
> + }
> +
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> +
> , &u_buf[1].unsigned_regval);
> + /* U == 1 */
> + if (bit (arm_insn_r->arm_insn, 23))
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval + offset_12;
> + }
> + else
> + {
> + tgt_mem_addr =
> u_buf[1].unsigned_regval - offset_12;
> + }
> +
> + switch (arm_insn_r->opcode)
> + {
> + case 8:
> + case 12:
> + case 9:
> + case 13:
> + case 1:
> + case 5:
> + /* STR insn, STRT insn. */
> + record_buf_mem[0] = 4;
> + break;
> +
> + case 10:
> + case 14:
> + case 11:
> + case 15:
> + case 3:
> + case 7:
> + /* STRB insn, STRBT insn. */
> + record_buf_mem[0] = 1;
> + break;
> +
> + default:
> + gdb_assert_not_reached
> ("Invalid addressing mode for insn");
> + break;
> + }
> + record_buf_mem[1] = tgt_mem_addr;
> + arm_insn_r->mem_rec_count = 1;
> +
> + if ((9 == arm_insn_r->opcode) || (11
> == arm_insn_r->opcode)
> + || (13 == arm_insn_r->opcode) || (15
> == arm_insn_r->opcode)
> + || (0 == arm_insn_r->opcode) || (2 ==
> arm_insn_r->opcode)
> + || (4 == arm_insn_r->opcode) || (6 ==
> arm_insn_r->opcode)
> + || (1 == arm_insn_r->opcode) || (3 ==
> arm_insn_r->opcode)
> + || (5 == arm_insn_r->opcode) || (7 ==
> arm_insn_r->opcode))
> + {
> + /* Rn is going to be changed in
> register scaled pre-indexed
> + mode, and
> scaled post indexed mode. */
> + record_buf[0] = reg_src2;
> + arm_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +arm_handle_ld_st_multiple_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t register_list[16] = {0}, register_count = 0,
> register_bits = 0;
>
>
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
> no_of_regs = 0;
> + uint32_t start_address = 0, index = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf[2];
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + /* This mode is exclusively for load and store
> multiple. */
> + /* Handle incremenrt after/before and decrment
> after.before mode;
> + Rn is changing depending on W bit, but as of
> now we store Rn too
> without optmization. */
> +
> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
> + {
> + /* LDM (1,2,3) where LDM (3) changes CPSR too.
> */
> +
> + if ((bit (arm_insn_r->arm_insn,20)) &&
> !(bit (arm_insn_r->arm_insn,22)))
> + {
> + register_bits = bits
> (arm_insn_r->arm_insn, 0, 15);
> + no_of_regs = 15;
> + }
> + else
> + {
> + register_bits = bits
> (arm_insn_r->arm_insn, 0, 14);
> + no_of_regs = 14;
> + }
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
> 19);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> +
> + /* Extra space for Base Register and CPSR;
> wihtout optmization. */
> + record_buf[register_count] = reg_src1;
> + record_buf[register_count + 1] =
> ARM_PS_REGNUM;
> + arm_insn_r->reg_rec_count = register_count
> + 2;
> +
> + for (register_count = 0; register_count <
> no_of_regs; register_count++)
> + {
> + if (register_list[register_count])
> + {
> + /* Register_count gives total no of
> registers and dually working
> + as reg number.
> */
> + record_buf[index] =
> register_count;
> + index++;
> + }
> + }
> +
> + }
> + else
> + {
> + /* It handles both STM(1) and STM(2). */
> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
> +
> + register_bits = bits (arm_insn_r->arm_insn, 0,
> 15);
> + /* Get Rn. */
> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> +
> + switch(addr_mode)
> + {
> + /* Decrement after. */
> + case 0:
> + start_address = (u_buf[0].unsigned_regval)
> - (register_count * 4) +
> 4;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment after. */
> + case 1:
> + start_address = u_buf[0].unsigned_regval;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Decrement before. */
> + case 2:
> +
> + start_address = (u_buf[0].unsigned_regval)
> - (register_count * 4);
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + /* Increment before. */
> + case 3:
> + start_address = u_buf[0].unsigned_regval +
> 4;
> + arm_insn_r->mem_rec_count =
> register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) -
> 1] = start_address;
> + record_buf_mem[(register_count * 2) -
> 2] = 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + break;
> +
> + default:
> + gdb_assert_not_reached ("Invalid addressing
> mode for insn");
> + break;
> + }
> +
> + /* Base register also changes; based on condition
> and W bit. */
> + /* We save it anyway without optimization. */
> + record_buf[0] = reg_src1;
> + arm_insn_r->reg_rec_count = 1;
> + }
> +
> + 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);
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
> +{
> +
> + uint32_t record_buf[8];
> +
> + /* Handle B, BL, BLX(1) insns. */
> + /* Wihtout optmization we save link register,
> + CSPR for the insn which changes T bit. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + arm_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (arm_insn_r->arm_regs,
> arm_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
> +{
> + 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;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +arm_handle_coproc_data_proc_insn (insn_decode_record
> *arm_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep
> (arm_insn_r->gdbarch);
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t shift_imm = 0;
> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
> + uint32_t start_address = 0;
> +
> + /* Handle SWI insn; system call would be handled over
> here. */
> +
> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
> 24, 27);
> + if (15 == arm_insn_r->opcode)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record
> support\n"));
> + return -1;
> + }
> + }
> +
> + 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;
> +}
> +
> +/* Handling opcode 000 insns. */
> +
> +static int
> +thumb_handle_shift_add_sub_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_src1 = 0;
> +
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
> +
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 010 insns. */
> +
> +static int
> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
> +
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + gdb_byte buf[4];
> + } u_buf[2];
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
> +
> + if (bit (thumb_insn_r->arm_insn, 12))
> + {
> + /* Handle load/store register offset. */
> + opcode2 = bits (thumb_insn_r->arm_insn, 9,
> 10);
> + if ((opcode2 >= 12) && (opcode2 <=
> 15))
> + {
> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.
> */
> + reg_src1 = bits
> (thumb_insn_r->arm_insn,0, 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if ((opcode2 >= 8) && (opcode2
> <= 10))
> + {
> + /* STR(2), STRB(2), STRH(2) . */
> + reg_src1 = bits (thumb_insn_r->arm_insn,
> 3, 5);
> + reg_src2 = bits (thumb_insn_r->arm_insn,
> 6, 8);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src1
> + ,
> &u_buf[0].unsigned_regval);
> + regcache_raw_read_unsigned (reg_cache,
> reg_src2
> + ,
> &u_buf[1].unsigned_regval);
> + if (8 == opcode2)
> + record_buf_mem[0] = 4; /* STR (2).
> */
> + else if (10 == opcode2)
> + record_buf_mem[0] = 1; /* STRB
> (2). */
> + else if (9 == opcode2)
> + record_buf_mem[0] = 2; /* STRH (2).
> */
> + record_buf_mem[1] =
> u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + }
> + else if (bit (thumb_insn_r->arm_insn, 11))
> + {
> + /* Handle load from literal pool. */
> + /* LDR(3). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
>
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (opcode1)
> + {
> + opcode2 = bits (thumb_insn_r->arm_insn, 8,
> 9);
> + opcode3 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + if ((3 == opcode2) && (!opcode3))
> + {
> + /* Branch with exchange. */
> + record_buf[0] = ARM_PS_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + 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;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + /* Format 5; data processing insns. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + if (bit (thumb_insn_r->arm_insn, 7))
> + {
> + reg_src1 = reg_src1 + 8;
> + }
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = reg_src1;
> + thumb_insn_r->reg_rec_count = 2;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count,
> record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 001 insns. */
> +
> +static int
> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (opcode)
> + {
> + /* LDR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else
> + {
> + /* STR(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
> 5);
> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
> 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_5 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count,
> record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 100 insns. */
> +
> +static int
> +thumb_handle_ld_st_stack_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> + uint32_t record_buf[8], record_buf_mem[8];
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (3 == opcode)
> + {
> + /* LDR(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (1 == opcode)
> + {
> + /* LDRH(1). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
> 2);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* STR(3). */
> + immed_8 = bits (thumb_insn_r->arm_insn, 0,
> 7);
> + regcache_raw_read_unsigned (reg_cache,
> ARM_SP_REGNUM
> + ,
> &u_buf.unsigned_regval);
> + record_buf_mem[0] = 4;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_8 * 4);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> + else if (0 == opcode)
> + {
> + /* STRH(1). */
> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
> 10);
> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
> 5);
> + regcache_raw_read_unsigned (reg_cache, reg_src1
> + ,
> &u_buf.unsigned_regval);
> + record_buf_mem[0] = 2;
> + record_buf_mem[1] = u_buf.unsigned_regval +
> (immed_5 * 2);
> + thumb_insn_r->mem_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count,
> record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 101 insns. */
> +
> +static int
> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
> = 0, immed_5 = 0;
> + uint32_t register_bits = 0, register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0,
> start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
> +
> + if (14 == opcode2)
> + {
> + /* POP. */
> + register_bits = bits (thumb_insn_r->arm_insn,
> 0, 7);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = ARM_PS_REGNUM;
> + record_buf[register_count + 1] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = register_count +
> 2;
> + for (register_count = 0; register_count < 8;
> register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (10 == opcode2)
> + {
> + /* PUSH. */
> + register_bits = bits (thumb_insn_r->arm_insn,
> 0, 7);
> + regcache_raw_read_unsigned (reg_cache,
> ARM_PC_REGNUM
> + ,
> &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval - \
> + (4 * (bit
> (thumb_insn_r->arm_insn, 8) + register_count)) ;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] =
> start_address;
> + record_buf_mem[(register_count * 2) - 2] =
> 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (0x1E == opcode1)
> + {
> + /* BKPT insn. */
> + /* Handle enhanced software breakpoint insn,
> BKPT. */
> + /* CPSR is changed to be executed in ARM state,
> disabling normal
> + interrupts, entering abort mode.
> */
> + /* Accorindly to high vector configuration PC is
> set accordingly. */
> + /* FIX ME ? what if user hit breakpoint and
> type reverse, in
> + that case, we need to go back with
> previous CPSR and
> + Program Counter.. */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> + /* Save SPSR also; how?. */
> + printf_unfiltered (_("Process record does not
> support instruction "
> + "0x%0x at address
> %s.\n"),
> +
> thumb_insn_r->arm_insn,
> + paddress
> (thumb_insn_r->gdbarch,
> thumb_insn_r->this_addr));
> + return -1;
> + }
> + else if ((0 == opcode) || (1 == opcode))
> + {
> + /* ADD(5), ADD(6). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = reg_src1;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> + else if (2 == opcode)
> + {
> + /* ADD(7), SUB(4). */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + record_buf[0] = ARM_SP_REGNUM;
> + thumb_insn_r->reg_rec_count = 1;
> + }
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count,
> record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 110 insns. */
> +
> +static int
> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep
> (thumb_insn_r->gdbarch);
> + struct regcache *reg_cache =
> thumb_insn_r->regcache;
> +
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0,
> register_count = 0;
> + uint32_t register_list[8] = {0}, index = 0,
> start_address = 0;
> + uint32_t record_buf[24], record_buf_mem[48];
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
> +
> + if (1 == opcode2)
> + {
> +
> + /* LDMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn,
> 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_list[register_count++] = 1;
> + register_bits = register_bits >> 1;
> + }
> + record_buf[register_count] = reg_src1;
> + thumb_insn_r->reg_rec_count = register_count +
> 1;
> + for (register_count = 0; register_count < 8;
> register_count++)
> + {
> + if (register_list[register_count])
> + {
> + record_buf[index] = register_count;
> + index++;
> + }
> + }
> + }
> + else if (0 == opcode2)
> + {
> + /* It handles both STMIA. */
> + register_bits = bits (thumb_insn_r->arm_insn,
> 0, 7);
> + /* Get Rn. */
> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
> 10);
> + regcache_raw_read_unsigned (reg_cache, reg_src1,
> &u_buf.unsigned_regval);
> + while (register_bits)
> + {
> + if (register_bits & 0x00000001)
> + register_count++;
> + register_bits = register_bits >> 1;
> + }
> + start_address = u_buf.unsigned_regval;
> + thumb_insn_r->mem_rec_count = register_count;
> + while (register_count)
> + {
> + record_buf_mem[(register_count * 2) - 1] =
> start_address;
> + record_buf_mem[(register_count * 2) - 2] =
> 4;
> + start_address = start_address + 4;
> + register_count--;
> + }
> + }
> + else if (0x1F == opcode1)
> + {
> + /* Handle arm syscall insn. */
> + if (tdep->arm_swi_record != NULL)
> + {
> + tdep->arm_swi_record(reg_cache);
> + }
> + else
> + {
> + printf_unfiltered (_("no syscall record
> support\n"));
> + return -1;
> + }
> + }
> +
> + /* B(1), conditional branch is automatically taken care
> in process_record,
> + as PC is saved there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> + MEM_ALLOC (thumb_insn_r->arm_mems,
> thumb_insn_r->mem_rec_count,
> record_buf_mem);
> +
> + return 0;
> +}
> +
> +/* Handling opcode 111 insns. */
> +
> +static int
> +thumb_handle_branch_insn (insn_decode_record
> *thumb_insn_r)
> +{
> + uint32_t record_buf[8];
> + uint32_t reg_val1 = 0;
> + uint32_t reg_src1 = 0;
> + uint32_t opcode = 0, immed_5 = 0;
> +
> +
> + /* BL , BLX(1). */
> + record_buf[0] = ARM_PS_REGNUM;
> + record_buf[1] = ARM_LR_REGNUM;
> + thumb_insn_r->reg_rec_count = 2;
> +
> + /* B(2) is automatically taken care in process_record,
> as PC is saved
> + there. */
> +
> + REG_ALLOC (thumb_insn_r->arm_regs,
> thumb_insn_r->reg_rec_count, record_buf);
> +
> + return 0;
> +}
> +
> +
> +/* Decode arm/thumb insn depending on condition cods and
> opcodes; and dispatch
> it. */
> +
> +static int
> +decode_insn (insn_decode_record *arm_record, uint32_t
> insn_size)
> +{
> +
> + /* (Starting from numerical 0); bits 25, 26, 27 decodes
> type of arm
> instruction. */
> + static int (*const arm_handle_insn[8])
> +
> (insn_decode_record*) =
> + {
> + arm_handle_data_proc_misc_ld_str_insn, /*
> 000. */
> + arm_handle_data_proc_imm_insn,
> /* 001. */
> + arm_handle_ld_st_imm_offset_insn, /*
> 010. */
> + arm_handle_ld_st_reg_offset_insn, /*
> 011. */
> + arm_handle_ld_st_multiple_insn, /*
> 100. */
> + arm_handle_brn_insn,
> /* 101. */
> + arm_handle_coproc_insn,
> /* 110. */
> + arm_handle_coproc_data_proc_insn /*
> 111. */
> + };
> +
> + /* (Starting from numerical 0); bits 13,14,15 decodes
> type of thumb
> instruction. */
> + static int (*const thumb_handle_insn[8])
> +
> (insn_decode_record*) =
> + { \
> + thumb_handle_shift_add_sub_insn, /*
> 000. */
> + thumb_handle_add_sub_cmp_mov_insn, /*
> 001. */
> + thumb_handle_ld_st_reg_offset_insn, /*
> 010. */
> + thumb_handle_ld_st_imm_offset_insn, /*
> 011. */
> + thumb_handle_ld_st_stack_insn, /*
> 100. */
> + thumb_handle_misc_insn,
> /* 101. */
> + thumb_handle_swi_insn,
> /* 110. */
> + thumb_handle_branch_insn
> /* 111. */
> + };
> +
> + struct
> + {
> + gdb_byte buf[insn_size];
> + } u_buf;
> +
> + uint32_t ret=0, insn_id = 0;
> +
> + memset (&u_buf, 0, sizeof(u_buf));
> + if (target_read_memory (arm_record->this_addr,
> &u_buf.buf[0], insn_size))
> + {
> + if (record_debug)
> + {
> + printf_unfiltered (_("Process record: error
> reading memory at "
> + "addr %s len
> = %d.\n"),
> + paddress (arm_record->gdbarch,
> arm_record->this_addr), insn_size);
> + return -1;
> + }
> + }
> + else if (ARM_INSN_SIZE_BYTES == insn_size)
> + {
> + arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> + , ARM_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
>
> + arm_record->cond = bits
> (arm_record->arm_insn, 28, 31);
> + insn_id = bits (arm_record->arm_insn, 25,
> 27);
> + ret = (0x0F != arm_record->cond)
> + ? arm_handle_insn[insn_id] (arm_record)
> + : handle_extension_space (arm_record);
> + }
> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
> + {
> + /* As thumb does not have condition codes,
> following field is useless.
> */
> + arm_record->cond = -1;
> + arm_record->arm_insn = (uint32_t)
> extract_unsigned_integer (&u_buf.buf[0]
> + , THUMB_INSN_SIZE_BYTES ,
> gdbarch_byte_order (arm_record->gdbarch));
> +
> + insn_id = bits (arm_record->arm_insn, 13,
> 15);
> + ret = thumb_handle_insn[insn_id] (arm_record);
> + }
> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
> + {
> + /* Yet to be implemented; handle thumb2 part
> here. */
> + printf_unfiltered (_("Process record does not
> support instruction 0x%0x "
> + "at address %s.\n"),
> +
> arm_record->arm_insn,
> + paddress
> (arm_record->gdbarch,
> arm_record->this_addr));
> + ret = -1;
> + }
> + else
> + {
> + /* Throw assertion. */
> + gdb_assert(0);
> + }
> +
> + return ret;
> +}
> +
> +/* Parse the current instruction and record the values of
> the registers and
> + memory that will be changed in current instruction to
> "record_arch_list".
> + Return -1 if something is wrong.. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct
> regcache *regcache,
> + CORE_ADDR
> insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order
> (gdbarch);
> + uint32_t no_of_rec = 0;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0;
> +
> + struct
> + {
> + ULONGEST unsigned_regval;
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof
> (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record:
> arm_process_record "
> +
> "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* Check the insn, whether it is thumb or arm one.
> */
> +
> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
> + regcache_raw_read_unsigned (arm_record.regcache,
> ARM_PS_REGNUM
> + ,
> &u_buf.unsigned_regval);
> +
> + if (!(u_buf.unsigned_regval & t_bit))
> + {
> + /* We are decoding arm insn. */
> + ret = decode_insn (&arm_record,
> ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* We are decoding thumb insn. */
> + ret = decode_insn (&arm_record,
> THUMB_INSN_SIZE_BYTES);
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_arch_list_add_reg (arm_record.regcache,
> ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec = 0; no_of_rec <
> arm_record.reg_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_reg
> (arm_record.regcache \
> +
> , (arm_record.arm_regs[no_of_rec])))
> + ret = -1;
> + }
> + }
> + /* Record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec = 0; no_of_rec <
> arm_record.mem_rec_count;
> no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> +
> ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> +
> arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
> --- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000
> +0530
> +++ arm_new/arm-tdep.h 2011-05-07 14:20:31.000000000
> +0530
> @@ -200,6 +200,9 @@
> /* Return the expected next PC if FRAME is stopped at a
> syscall
> instruction. */
> CORE_ADDR (*syscall_next_pc) (struct frame_info
> *frame);
> +
> + /* Parse swi insn args, sycall record. */
> + int (*arm_swi_record) (struct regcache *regcache);
> };
>
> /* Structures used for displaced stepping. */
> @@ -310,6 +313,10 @@
> struct
> displaced_step_closure *,
> CORE_ADDR, CORE_ADDR,
> struct regcache *);
>
> +extern int arm_process_record (struct gdbarch *gdbarch,
> + struct
> regcache *regcache, CORE_ADDR addr);
> +
> +
> /* Functions exported from armbsd-tdep.h. */
>
> /* Return the appropriate register set for the core
> section identified
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
2011-06-06 17:42 ` chandra krishnappa
@ 2011-07-05 8:47 ` oza Pawandeep
0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-07-05 8:47 UTC (permalink / raw)
To: gdb-patches; +Cc: paawan oza, chandra krishnappa
Hi all,
can anybody from ARM background review the code with functional perspective ?
Chandra K, is assisting for gdb automated testsuite for arm
reversible, but review is equally important specially if ARM folk
could have a look at the patch at functional perspective.
Thanks & Regards,
Oza.
>
> --- On Fri, 3/6/11, "paawan oza" <paawan1982@yahoo.com> wrote:
>> From: paawan oza <paawan1982@yahoo.com>
>> Date: Fri, Jun 3, 2011 at 1:21 PM
>> Subject: Re: [PATCH] arm reversible :
>> <phase_2_complete>
>> To: Tom Tromey <tromey@redhat.com>
>> Cc: gdb-patches@sourceware.org,
>> Petr Hluzín <petr.hluzin@gmail.com>
>>
>>
>> Hi Tom,
>>
>> Fixed almost all comments.
>> any more comments are welcome make this patch ok, if ARM
>> person can have a look
>> at it it would be great.
>>
>> PATCH STARTS
>> ------------------------------------diff -urN
>> arm_orig/arm-linux-tdep.c
>> arm_new/arm-linux-tdep.c
>> --- arm_orig/arm-linux-tdep.c 2011-03-03
>> 09:21:13.000000000 +0530
>> +++ arm_new/arm-linux-tdep.c 2011-05-07
>> 14:20:31.000000000 +0530
>> @@ -998,6 +998,9 @@
>> set_gdbarch_fetch_tls_load_module_address (gdbarch,
>>
>> svr4_fetch_objfile_link_map);
>>
>> + /* Enable process record. */
>> + set_gdbarch_process_record (gdbarch,
>> arm_process_record);
>> +
>> tramp_frame_prepend_unwinder (gdbarch,
>>
>> &arm_linux_sigreturn_tramp_frame);
>> tramp_frame_prepend_unwinder (gdbarch,
>> @@ -1025,6 +1028,8 @@
>>
>>
>> tdep->syscall_next_pc = arm_linux_syscall_next_pc;
>> +
>> + tdep->arm_swi_record = NULL;
>> }
>>
>> /* Provide a prototype to silence -Wmissing-prototypes.
>> */
>> diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
>> --- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.c 2011-06-03 13:16:35.000000000
>> +0530
>> @@ -54,6 +54,8 @@
>> #include "gdb_assert.h"
>> #include "vec.h"
>>
>> +#include "record.h"
>> +
>> #include "features/arm-with-m.c"
>>
>> static int arm_debug;
>> @@ -7929,3 +7931,1763 @@
>> NULL, /* FIXME: i18n: "ARM debugging
>> is %s. */
>> &setdebuglist,
>> &showdebuglist);
>> }
>> +
>> +
>> +
>> +/* ARM-reversible process record data structures. */
>> +
>> +#define ARM_INSN_SIZE_BYTES 4
>> +#define THUMB_INSN_SIZE_BYTES 2
>> +#define THUMB2_INSN_SIZE_BYTES 4
>> +
>> +#define INSN_S_L_BIT_NUM 20
>> +
>> +#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
>> +do \
>> + { \
>> + unsigned int reg_len = 0; reg_len = LENGTH; \
>> + if (reg_len) \
>> + { \
>> + REGS = (uint32_t*) xmalloc (sizeof(uint32_t) *
>> (reg_len)); \
>> + while (reg_len) \
>> + { \
>> + REGS[reg_len - 1] = RECORD_BUF[reg_len -
>> 1]; \
>> + reg_len--; \
>> + } \
>> + } \
>> + } \
>> +while (0)
>> +
>> +#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
>> +do \
>> + { \
>> + unsigned int mem_len = 0; mem_len = LENGTH; \
>> + if (mem_len) \
>> + { \
>> + MEMS = (struct arm_mem_r *)xmalloc \
>> + (sizeof(struct arm_mem_r) *
>> (mem_len)); \
>> + while (mem_len) \
>> + { \
>> + MEMS[mem_len - 1].addr =
>> RECORD_BUF[(mem_len * 2) - 1]; \
>> + MEMS[mem_len - 1].len =
>> RECORD_BUF[(mem_len * 2) - 2]; \
>> + mem_len--; \
>> + } \
>> + } \
>> + } \
>> +while (0)
>> +
>> +
>> +/* ARM memory record structure. */
>> +struct arm_mem_r
>> +{
>> + uint32_t len; /* Record length. */
>> + CORE_ADDR addr; /* Memory address. */
>> +};
>> +
>> +/* ARM instruction record contains opcode of current insn
>> and execution state
>> (before entry to
>>
>> +decode_insn() ), contains list of to-be-modified registers
>> and memory blocks
>> (on return from
>>
>> +decode_insn() ). */
>> +typedef struct insn_decode_record_t
>> +{
>> + struct gdbarch *gdbarch;
>> + struct regcache *regcache;
>> + CORE_ADDR this_addr; /* Address of the
>> insn being decoded. */
>> + uint32_t arm_insn; /* Should
>> accommodate thumb. */
>> + uint32_t cond; /* Condition
>> code. */
>> + uint32_t opcode; /* Insn opcode.
>> */
>> + uint32_t decode; /* Insn decode
>> bits. */
>> + uint32_t mem_rec_count; /* No of mem recors
>> */
>> + uint32_t reg_rec_count; /* No of reg records
>> */
>> + uint32_t *arm_regs; /* Registers to be
>> saved for this record. */
>> + struct arm_mem_r *arm_mems; /* Memory to be saved
>> for this record. */
>> +} insn_decode_record;
>> +
>> +
>> +/* Checks ARM SBZ and SBO mendatory fields. */
>> +
>> +static int
>> +sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len,
>> uint32_t sbo)
>> +{
>> + uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) +
>> (len - 1));
>> +
>> + if (!len)
>> + return 1;
>> +
>> + if(!sbo)
>> + ones = ~ones;
>> +
>> + while (ones)
>> + {
>> + if (!(ones & sbo))
>> + {
>> + return 0;
>> + }
>> + ones = ones >> 1;
>> + }
>> + return 1;
>> +}
>> +
>> +/* Handling ARM extension space insns. */
>> +
>> +static int
>> +handle_extension_space (insn_decode_record *arm_insn_r)
>> +{
>> + uint32_t ret = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0;
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> + if ((3 == opcode1) && (bit
>> (arm_insn_r->arm_insn, 4)))
>> + {
>> + ret = -1;
>> + /* Undefined instruction on ARM V5; need to
>> handle if later versions
>> + define it. */
>> + }
>> +
>> + opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
>> +
>> + if ((!opcode1) && (9 == opcode2))
>> + {
>> + ret = -1;
>> + /* Handle arithmetic insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
>> + opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> + if ((!opcode1) && (2 == opcode2) &&
>> (!bit (arm_insn_r->arm_insn, 20)))
>> + {
>> + ret = -1;
>> + /* Handle control insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
>> + if ((!opcode1) && (bit
>> (arm_insn_r->arm_insn, 7)) \
>> + &&
>> (bit(arm_insn_r->arm_insn, 4)))
>> + {
>> + ret = -1;
>> + /* Handle load/store insn extension space. */
>> + }
>> +
>> + opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
>> + if ((24 == opcode1) && (bit
>> (arm_insn_r->arm_insn, 21)))
>> + {
>> + ret = -1;
>> + /* Handle coprocessor insn extension space. */
>> + }
>> +
>> + /* To be done for ARMv5 and later; as of now we return
>> -1. */
>> + if (-1 == ret)
>> + 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 ret;
>> +}
>> +
>> +/* Handling opcode 000 insns. */
>> +
>> +static int
>> +arm_handle_data_proc_misc_ld_str_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> +
>> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> + uint32_t immed_high = 0, immed_low = 0,offset_8 = 0,
>> tgt_mem_addr = 0;
>> + uint32_t opcode1 = 0;
>> +
>> + memset(&u_buf, 0, sizeof (u_buf));
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> + opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
>> +
>> + /* Data processing insn /multiply insn. */
>> + if ((9 == arm_insn_r->decode)
>> + && (((4 <= arm_insn_r->opcode)
>> && (7 >= arm_insn_r->opcode))
>> + || ((0 == arm_insn_r->opcode) || (1 ==
>> arm_insn_r->opcode))))
>> + {
>> + /* Handle multiply instructions. */
>> + /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
>> + if ((0 == arm_insn_r->opcode) || (1 ==
>> arm_insn_r->opcode))
>> + {
>> + /* Handle MLA and MUL. */
>> + record_buf[0] = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + else if ((4 <= arm_insn_r->opcode)
>> && (7 >= arm_insn_r->opcode))
>> + {
>> + /* Handle SMLAL, SMULL, UMLAL, UMULL. */
>> + record_buf[0] = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> + record_buf[1] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> + record_buf[2] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 3;
>> + }
>> + }
>> + else if ((bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM))
>> + && ((11 == arm_insn_r->decode) ||
>> (13 == arm_insn_r->decode)))
>> + {
>> + /* Handle misc load insns, as 20th bit (L =
>> 1). */
>> + /* LDR insn has a capability to do branching,
>> if
>> + MOV LR, PC is preccedded by LDR
>> insn having Rn as R15
>> + in that case, it emulates
>> branch and link insn, and hence we
>> + need to save CSPR and PC as
>> well. I am not sure this is right
>>
>> + place as opcode = 010 LDR insn
>> make this happen, if R15 was
>> + used. */
>> + reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + record_buf[0] = reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else if (((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode))
>> + && (sbo_sbz (arm_insn_r->arm_insn, 5,
>> 12, 0))
>> + && (sbo_sbz (arm_insn_r->arm_insn, 13,
>> 4, 1))
>> + && (2 == bits (arm_insn_r->arm_insn,
>> 20, 21)))
>> + {
>> + /* Handle MSR insn. */
>> + if (9 == arm_insn_r->opcode)
>> + {
>> + /* CSPR is going to be changed. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* 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;
>> + }
>> + }
>> + else if ((9 == arm_insn_r->decode)
>> + && ((8 == arm_insn_r->opcode)
>> || (10 == arm_insn_r->opcode))
>> + && (!bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM)))
>> + {
>> + /* Handling SWP, SWPB. */
>> + /* These insns, changes register and memory as
>> well. */
>> + /* SWP or SWPB insn. */
>> + /* Get memory address given by Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + /* SWP insn ?, swaps word. */
>> + if (8 == arm_insn_r->opcode)
>> + {
>> + record_buf_mem[0] = 4;
>> + }
>> + else
>> + {
>> + /* SWPB insn, swaps only byte. */
>> + record_buf_mem[0] = 1;
>> + }
>> + record_buf_mem[1] = u_buf[0].unsigned_regval;
>> + arm_insn_r->mem_rec_count = 1;
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((3 == arm_insn_r->decode) && (0x12
>> == opcode1)
>> + && (sbo_sbz
>> (arm_insn_r->arm_insn, 9, 12, 1)))
>> + {
>> + /* Handle BLX, branch and link/exchange. */
>> + if (9 == arm_insn_r->opcode)
>> + {
>> + /* Branch is chosen by setting T bit of CSPR,
>> bitp[0] of Rm,
>> + and R14 stores the return
>> address. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else if ((7 == arm_insn_r->decode) && (0x12
>> == opcode1))
>> + {
>> + /* Handle enhanced software breakpoint insn, BKPT
>> */
>> + /* CPSR is changed to be executed in ARM state,
>> disabling normal
>> + interrupts, entering abort mode.
>> */
>> + /* Accorindly to high vector configuration PC is
>> set accordingly */
>> + /* What if user hit breakpoint and type reverse,
>> in
>> + that case, we need to go back with
>> previous CPSR and
>> + Program Counter. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + 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)
>> + && (!bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM)))
>> + {
>> + /* Handle enhanced store insns and DSP insns (e.g.
>> LDRD)
>> + let us begin according to addressing modes
>> for store insns
>> + STRH insn, addresing modes are taken
>> following. */
>> + if ((14 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode))
>> + {
>> + /* 1) Handle misc store, immediate offset.
>> */
>> + immed_low = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> + immed_high = bits (arm_insn_r->arm_insn, 8,
>> 11);
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + if (15 == reg_src1)
>> + {
>> + /* If R15 was used as Rn, hence current
>> PC+8. */
>> + u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> + }
>> + offset_8 = (immed_high << 4) |
>> immed_low;
>> + /* Calculate target store address. */
>> + if (14 == arm_insn_r->opcode)
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + }
>> + else if ((12 == arm_insn_r->opcode) || (8 ==
>> arm_insn_r->opcode))
>> + {
>> + /* 2) Store, register offset. */
>> + /* Get Rm. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> + /* Get Rn. */
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> + ,
>> &u_buf[1].unsigned_regval);
>>
>> + if (15 == reg_src2)
>> + {
>> + /* If R15 was used as Rn, hence current
>> PC+8. */
>> + u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> + }
>> + /* Calculate target store address, Rn +/- Rm,
>> register offset. */
>> + if (12 == arm_insn_r->opcode)
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + }
>> + else if ((11 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> + || (2 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode))
>> + {
>> + /* 3) Store, immediate pre-indexed. */
>> + /* 5) Store, immediate post-indexed. */
>> + immed_low = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> + immed_high = bits (arm_insn_r->arm_insn, 8,
>> 11);
>> + offset_8 = (immed_high << 4) |
>> immed_low;
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + regcache_raw_read_unsigned(reg_cache,
>> reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + /* Calculate target store address, Rn +/- Rm,
>> register offset. */
>> + if ((15 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode))
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> + offset_8;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> - offset_8;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + /* Record Rn also as it changes. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((9 == arm_insn_r->opcode) || (13 ==
>> arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (4 ==
>> arm_insn_r->opcode))
>> + {
>> + /* 4) Store, register pre-indexed. */
>> + /* 6) Store, register post -indexed. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 0,
>> 3);
>> + reg_src2 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> + ,
>> &u_buf[1].unsigned_regval);
>> + /* Calculate target store address, Rn +/- Rm,
>> register offset. */
>> + if ((13 == arm_insn_r->opcode) || (4 ==
>> arm_insn_r->opcode))
>> + {
>> + tgt_mem_addr = u_buf[0].unsigned_regval
>> + u_buf[1].unsigned_regval;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf[1].unsigned_regval
>> - u_buf[0].unsigned_regval;
>> + }
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> + /* Record Rn also as it changes. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + /* DSP insns (e.g. LDRD) TBD. */
>> + }
>> + else if ((1 == arm_insn_r->decode) && (0x12
>> == opcode1)
>> + && sbo_sbz
>> (arm_insn_r->arm_insn, 9, 12, 1))
>> + {
>> + /* Handle BX, branch and link/exchange. */
>> + /* Branch is chosen by setting T bit of CSPR,
>> bitp[0] of Rm. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((1 == arm_insn_r->decode) && (0x16
>> == opcode1)
>> + && (sbo_sbz
>> (arm_insn_r->arm_insn, 9, 4, 1))
>> + && (sbo_sbz
>> (arm_insn_r->arm_insn, 17, 4, 1)))
>> + {
>> + /* Count leading zeros: CLZ. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((!bit (arm_insn_r->arm_insn,
>> INSN_S_L_BIT_NUM))
>> + && ((8 == arm_insn_r->opcode) ||
>> (10 == arm_insn_r->opcode))
>> + && (sbo_sbz
>> (arm_insn_r->arm_insn, 17, 4, 1))
>> + && (sbo_sbz
>> (arm_insn_r->arm_insn, 1, 12, 0))
>> + )
>> + {
>> + /* Handle MRS insn. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else if (arm_insn_r->opcode <= 15)
>> + {
>> + /* Normal data processing insns. */
>> + /* Out of 11 shifter operands mode, all the insn
>> modifies destination
>> + register, which is specified by
>> 13-16 decode. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + else
>> + {
>> + gdb_assert_not_reached ("no decoding pattern
>> found");
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +arm_handle_data_proc_imm_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> + if (((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode))
>> + && (2 == bits (arm_insn_r->arm_insn,
>> 20, 21))
>> + && (sbo_sbz (arm_insn_r->arm_insn,
>> 13, 4, 1))
>> + )
>> + {
>> + /* Handle MSR insn. */
>> + if (9 == arm_insn_r->opcode)
>> + {
>> + /*CSPR is going to be changed. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* SPSR is going to be changed. */
>> + }
>> + }
>> + else if (arm_insn_r->opcode <= 15)
>> + {
>> + /* Normal data processing insns. */
>> + /* Out of 11 shifter operands mode, all the insn
>> modifies destination
>> + register, which is specified by
>> 13-16 decode. */
>> + record_buf[0] = bits (arm_insn_r->arm_insn,
>> 12, 15);
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + else
>> + {
>> + gdb_assert_not_reached ("no decoding pattern
>> found");
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns. */
>> +
>> +static int
>> +arm_handle_ld_st_imm_offset_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t reg_src1 = 0 , reg_dest = 0;
>> + uint32_t offset_12 = 0, tgt_mem_addr = 0;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + memset(&u_buf, 0, sizeof (u_buf));
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> + /* LDR insn has a capability to do branching, if
>> + MOV LR, PC is precedded by LDR insn
>> having Rn as R15
>> + in that case, it emulates branch and
>> link insn, and hence we
>> + need to save CSPR and PC as well.
>> */
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + record_buf[0] = reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + if ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> + || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> + || (9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + /* Store, immediate offset, immediate
>> pre-indexed,
>> + immediate post-indexed.
>> */
>> + reg_src1 = bits (arm_insn_r->arm_insn,
>> 16, 19);
>> + offset_12 = bits (arm_insn_r->arm_insn,
>> 0, 11);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + ,
>> &u_buf.unsigned_regval);
>> + /* U == 1 */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr = u_buf.unsigned_regval
>> + offset_12;
>> + }
>> + else
>> + {
>> + tgt_mem_addr = u_buf.unsigned_regval -
>> offset_12;
>> + }
>> +
>> + switch(arm_insn_r->opcode)
>> + {
>> + case 8:
>> + case 12:
>> + case 9:
>> + case 13:
>> + case 1:
>> + case 5:
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + case 10:
>> + case 14:
>> + case 11:
>> + case 15:
>> + case 3:
>> + case 7:
>> + /* STRB insn, STRBT insn. */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> + default:
>> + gdb_assert_not_reached ("Invalid
>> addressing mode for insn");
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + /* We are handling pre-indexed mode;
>> post-indexed mode;
>> + where Rn is
>> going to be changed. */
>> + record_buf[0] = reg_src1;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 011 insns. */
>> +
>> +static int
>> +arm_handle_ld_st_reg_offset_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t shift_imm = 0;
>> + uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
>> + uint32_t immed_high = 0, immed_low = 0, offset_12 = 0,
>> tgt_mem_addr = 0;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + struct
>> + {
>> + LONGEST signed_word;
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> + memset(&u_buf, 0, sizeof (u_buf));
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 21, 24);
>> + arm_insn_r->decode = bits (arm_insn_r->arm_insn,
>> 4, 7);
>> +
>> + /* Handle enhanced store insns and LDRD DSP insn,
>> + let us begin according to addressing modes for
>> store insns
>> + STRH insn. */
>> +
>> + /* LDR or STR? */
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + reg_dest = bits (arm_insn_r->arm_insn, 12,
>> 15);
>> + /* LDR insn has a capability to do branching, if
>> + MOV LR, PC is precedded by LDR insn
>> having Rn as R15
>> + in that case, it emulates branch and
>> link insn, and hence we
>> + need to save CSPR and PC as well.
>> */
>> + if (15 != reg_dest)
>> + {
>> + record_buf[0] = bits
>> (arm_insn_r->arm_insn, 12, 15);
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + record_buf[0] = reg_dest;
>> + record_buf[1] = ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + if ((8 == arm_insn_r->opcode) || (10 ==
>> arm_insn_r->opcode)
>> + || (12 == arm_insn_r->opcode) || (14 ==
>> arm_insn_r->opcode)
>> + || (9 == arm_insn_r->opcode) || (11 ==
>> arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15 ==
>> arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + if (! bits (arm_insn_r->arm_insn, 4, 11))
>> + {
>> + /* Store insn, register offset and
>> register pre-indexed,
>> + register
>> post-indexed. */
>> + /* Get Rm. */
>> + reg_src1 = bits
>> (arm_insn_r->arm_insn, 0, 3);
>> + /* Get Rn. */
>> + reg_src2 = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +
>> , &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>> ,
>> &u_buf[1].unsigned_regval);
>>
>> + if (15 == reg_src2)
>> + {
>> + /* If R15 was used as Rn, hence
>> current PC+8. */
>> + /* Pre-indexed mode doesnt reach
>> here ; illegal insn. */
>> + u_buf[0].unsigned_regval =
>> u_buf[0].unsigned_regval + 8;
>> + }
>> + /* Calculate target store address, Rn
>> +/- Rm, register offset. */
>> + /* U == 1. */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr =
>> u_buf[0].unsigned_regval +
>> u_buf[1].unsigned_regval;
>> + }
>> + else
>> + {
>> + tgt_mem_addr =
>> u_buf[1].unsigned_regval -
>> u_buf[0].unsigned_regval;
>> + }
>> +
>> + switch(arm_insn_r->opcode)
>> + {
>> + case 8:
>> + case 12:
>> + case 9:
>> + case 13:
>> + case 1:
>> + case 5:
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + case 10:
>> + case 14:
>> + case 11:
>> + case 15:
>> + case 3:
>> + case 7:
>> + /* STRB insn, STRBT insn. */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> + default:
>> + gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11
>> == arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15
>> == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + /* Rn is going to be changed in
>> pre-indexed mode and
>> +
>> post-indexed mode as well. */
>> + record_buf[0] = reg_src2;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + else
>> + {
>> + /* Store insn, scaled register offset;
>> scaled pre-indexed. */
>> + offset_12 = bits
>> (arm_insn_r->arm_insn, 5, 6);
>> + /* Get Rm. */
>> + reg_src1 = bits
>> (arm_insn_r->arm_insn, 0, 3);
>> + /* Get Rn. */
>> + reg_src2 = bits
>> (arm_insn_r->arm_insn, 16, 19);
>> + /* Get shift_imm. */
>> + shift_imm = bits
>> (arm_insn_r->arm_insn, 7, 11);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> +
>> , &u_buf[0].unsigned_regval);
>> + regcache_raw_read_signed (reg_cache,
>> reg_src1
>> +
>> , &u_buf[0].signed_word);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>> , &u_buf[1].unsigned_regval);
>> + /* Offset_12 used as shift. */
>> + switch(offset_12)
>> + {
>> + case 0:
>> + /* Offset_12 used as index.
>> */
>> + offset_12 =
>> u_buf[0].unsigned_regval << shift_imm;
>> + break;
>> +
>> + case 1:
>> + offset_12 =
>> (!shift_imm)?0:u_buf[0].unsigned_regval >>
>> shift_imm;
>>
>> + break;
>> +
>> + case 2:
>> + if (!shift_imm)
>> + {
>> + if (bit
>> (u_buf[0].unsigned_regval, 31))
>> + {
>> + offset_12 =
>> 0xFFFFFFFF;
>> + }
>> + else
>> + {
>> + offset_12 = 0;
>> + }
>> + }
>> + else
>> + {
>> + /* This is arithmetic
>> shift. */
>> + offset_12 =
>> u_buf[0].signed_word >> shift_imm;
>> + }
>> + break;
>> +
>> + case 3:
>> + if (!shift_imm)
>> + {
>> +
>> regcache_raw_read_unsigned (reg_cache, ARM_PS_REGNUM
>> +
>> , &u_buf[1].unsigned_regval);
>> + /* Get C flag value and
>> shift it by 31. */
>> + offset_12 = (((bit
>> (u_buf[1].unsigned_regval, 29)) << 31)
>> \
>> + |
>> (u_buf[0].unsigned_regval) >> 1);
>> + }
>> + else
>> + {
>> + offset_12 =
>> (u_buf[0].unsigned_regval >> shift_imm) \
>> + |
>> (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
>> shift_imm));
>> + }
>> + break;
>> +
>> + default:
>> + gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> + break;
>> + }
>> +
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> +
>> , &u_buf[1].unsigned_regval);
>> + /* U == 1 */
>> + if (bit (arm_insn_r->arm_insn, 23))
>> + {
>> + tgt_mem_addr =
>> u_buf[1].unsigned_regval + offset_12;
>> + }
>> + else
>> + {
>> + tgt_mem_addr =
>> u_buf[1].unsigned_regval - offset_12;
>> + }
>> +
>> + switch (arm_insn_r->opcode)
>> + {
>> + case 8:
>> + case 12:
>> + case 9:
>> + case 13:
>> + case 1:
>> + case 5:
>> + /* STR insn, STRT insn. */
>> + record_buf_mem[0] = 4;
>> + break;
>> +
>> + case 10:
>> + case 14:
>> + case 11:
>> + case 15:
>> + case 3:
>> + case 7:
>> + /* STRB insn, STRBT insn. */
>> + record_buf_mem[0] = 1;
>> + break;
>> +
>> + default:
>> + gdb_assert_not_reached
>> ("Invalid addressing mode for insn");
>> + break;
>> + }
>> + record_buf_mem[1] = tgt_mem_addr;
>> + arm_insn_r->mem_rec_count = 1;
>> +
>> + if ((9 == arm_insn_r->opcode) || (11
>> == arm_insn_r->opcode)
>> + || (13 == arm_insn_r->opcode) || (15
>> == arm_insn_r->opcode)
>> + || (0 == arm_insn_r->opcode) || (2 ==
>> arm_insn_r->opcode)
>> + || (4 == arm_insn_r->opcode) || (6 ==
>> arm_insn_r->opcode)
>> + || (1 == arm_insn_r->opcode) || (3 ==
>> arm_insn_r->opcode)
>> + || (5 == arm_insn_r->opcode) || (7 ==
>> arm_insn_r->opcode))
>> + {
>> + /* Rn is going to be changed in
>> register scaled pre-indexed
>> + mode, and
>> scaled post indexed mode. */
>> + record_buf[0] = reg_src2;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + }
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns. */
>> +
>> +static int
>> +arm_handle_ld_st_multiple_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t register_list[16] = {0}, register_count = 0,
>> register_bits = 0;
>>
>>
>> + uint32_t shift_imm = 0;
>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0,
>> no_of_regs = 0;
>> + uint32_t start_address = 0, index = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf[2];
>> +
>> + memset (&u_buf, 0, sizeof(u_buf));
>> +
>> + /* This mode is exclusively for load and store
>> multiple. */
>> + /* Handle incremenrt after/before and decrment
>> after.before mode;
>> + Rn is changing depending on W bit, but as of
>> now we store Rn too
>> without optmization. */
>> +
>> + if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
>> + {
>> + /* LDM (1,2,3) where LDM (3) changes CPSR too.
>> */
>> +
>> + if ((bit (arm_insn_r->arm_insn,20)) &&
>> !(bit (arm_insn_r->arm_insn,22)))
>> + {
>> + register_bits = bits
>> (arm_insn_r->arm_insn, 0, 15);
>> + no_of_regs = 15;
>> + }
>> + else
>> + {
>> + register_bits = bits
>> (arm_insn_r->arm_insn, 0, 14);
>> + no_of_regs = 14;
>> + }
>> + /* Get Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16,
>> 19);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> +
>> + /* Extra space for Base Register and CPSR;
>> wihtout optmization. */
>> + record_buf[register_count] = reg_src1;
>> + record_buf[register_count + 1] =
>> ARM_PS_REGNUM;
>> + arm_insn_r->reg_rec_count = register_count
>> + 2;
>> +
>> + for (register_count = 0; register_count <
>> no_of_regs; register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + /* Register_count gives total no of
>> registers and dually working
>> + as reg number.
>> */
>> + record_buf[index] =
>> register_count;
>> + index++;
>> + }
>> + }
>> +
>> + }
>> + else
>> + {
>> + /* It handles both STM(1) and STM(2). */
>> + addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
>> +
>> + register_bits = bits (arm_insn_r->arm_insn, 0,
>> 15);
>> + /* Get Rn. */
>> + reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> +
>> + switch(addr_mode)
>> + {
>> + /* Decrement after. */
>> + case 0:
>> + start_address = (u_buf[0].unsigned_regval)
>> - (register_count * 4) +
>> 4;
>> + arm_insn_r->mem_rec_count =
>> register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> + record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Increment after. */
>> + case 1:
>> + start_address = u_buf[0].unsigned_regval;
>> + arm_insn_r->mem_rec_count =
>> register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> + record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Decrement before. */
>> + case 2:
>> +
>> + start_address = (u_buf[0].unsigned_regval)
>> - (register_count * 4);
>> + arm_insn_r->mem_rec_count =
>> register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> + record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + /* Increment before. */
>> + case 3:
>> + start_address = u_buf[0].unsigned_regval +
>> 4;
>> + arm_insn_r->mem_rec_count =
>> register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) -
>> 1] = start_address;
>> + record_buf_mem[(register_count * 2) -
>> 2] = 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + break;
>> +
>> + default:
>> + gdb_assert_not_reached ("Invalid addressing
>> mode for insn");
>> + break;
>> + }
>> +
>> + /* Base register also changes; based on condition
>> and W bit. */
>> + /* We save it anyway without optimization. */
>> + record_buf[0] = reg_src1;
>> + arm_insn_r->reg_rec_count = 1;
>> + }
>> +
>> + 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);
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 101 insns. */
>> +
>> +static int
>> +arm_handle_brn_insn (insn_decode_record *arm_insn_r)
>> +{
>> +
>> + uint32_t record_buf[8];
>> +
>> + /* Handle B, BL, BLX(1) insns. */
>> + /* Wihtout optmization we save link register,
>> + CSPR for the insn which changes T bit. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + arm_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (arm_insn_r->arm_regs,
>> arm_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns. */
>> +
>> +static int
>> +arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
>> +{
>> + 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;
>> +}
>> +
>> +/* Handling opcode 111 insns. */
>> +
>> +static int
>> +arm_handle_coproc_data_proc_insn (insn_decode_record
>> *arm_insn_r)
>> +{
>> + struct gdbarch_tdep *tdep = gdbarch_tdep
>> (arm_insn_r->gdbarch);
>> + struct regcache *reg_cache = arm_insn_r->regcache;
>> +
>> + uint32_t shift_imm = 0;
>> + uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
>> + uint32_t start_address = 0;
>> +
>> + /* Handle SWI insn; system call would be handled over
>> here. */
>> +
>> + arm_insn_r->opcode = bits (arm_insn_r->arm_insn,
>> 24, 27);
>> + if (15 == arm_insn_r->opcode)
>> + {
>> + /* Handle arm syscall insn. */
>> + if (tdep->arm_swi_record != NULL)
>> + {
>> + tdep->arm_swi_record(reg_cache);
>> + }
>> + else
>> + {
>> + printf_unfiltered (_("no syscall record
>> support\n"));
>> + return -1;
>> + }
>> + }
>> +
>> + 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;
>> +}
>> +
>> +/* Handling opcode 000 insns. */
>> +
>> +static int
>> +thumb_handle_shift_add_sub_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_src1 = 0;
>> +
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
>> +
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +thumb_handle_add_sub_cmp_mov_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_src1 = 0;
>> +
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
>> +
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 010 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_reg_offset_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_src1 = 0, reg_src2 = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
>> +
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + gdb_byte buf[4];
>> + } u_buf[2];
>> +
>> + opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
>> +
>> + if (bit (thumb_insn_r->arm_insn, 12))
>> + {
>> + /* Handle load/store register offset. */
>> + opcode2 = bits (thumb_insn_r->arm_insn, 9,
>> 10);
>> + if ((opcode2 >= 12) && (opcode2 <=
>> 15))
>> + {
>> + /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH.
>> */
>> + reg_src1 = bits
>> (thumb_insn_r->arm_insn,0, 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if ((opcode2 >= 8) && (opcode2
>> <= 10))
>> + {
>> + /* STR(2), STRB(2), STRH(2) . */
>> + reg_src1 = bits (thumb_insn_r->arm_insn,
>> 3, 5);
>> + reg_src2 = bits (thumb_insn_r->arm_insn,
>> 6, 8);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src1
>> + ,
>> &u_buf[0].unsigned_regval);
>> + regcache_raw_read_unsigned (reg_cache,
>> reg_src2
>> + ,
>> &u_buf[1].unsigned_regval);
>> + if (8 == opcode2)
>> + record_buf_mem[0] = 4; /* STR (2).
>> */
>> + else if (10 == opcode2)
>> + record_buf_mem[0] = 1; /* STRB
>> (2). */
>> + else if (9 == opcode2)
>> + record_buf_mem[0] = 2; /* STRH (2).
>> */
>> + record_buf_mem[1] =
>> u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
>>
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> + }
>> + else if (bit (thumb_insn_r->arm_insn, 11))
>> + {
>> + /* Handle load from literal pool. */
>> + /* LDR(3). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>>
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (opcode1)
>> + {
>> + opcode2 = bits (thumb_insn_r->arm_insn, 8,
>> 9);
>> + opcode3 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> + if ((3 == opcode2) && (!opcode3))
>> + {
>> + /* Branch with exchange. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + 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;
>> + thumb_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + /* Format 5; data processing insns. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> + if (bit (thumb_insn_r->arm_insn, 7))
>> + {
>> + reg_src1 = reg_src1 + 8;
>> + }
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 2;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 001 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_imm_offset_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, immed_5 = 0;
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (opcode)
>> + {
>> + /* LDR(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + {
>> + /* STR(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
>> 5);
>> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
>> 10);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 4;
>> + record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_5 * 4);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 100 insns. */
>> +
>> +static int
>> +thumb_handle_ld_st_stack_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> + uint32_t record_buf[8], record_buf_mem[8];
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (3 == opcode)
>> + {
>> + /* LDR(4). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (1 == opcode)
>> + {
>> + /* LDRH(1). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 0,
>> 2);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (2 == opcode)
>> + {
>> + /* STR(3). */
>> + immed_8 = bits (thumb_insn_r->arm_insn, 0,
>> 7);
>> + regcache_raw_read_unsigned (reg_cache,
>> ARM_SP_REGNUM
>> + ,
>> &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 4;
>> + record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_8 * 4);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> + else if (0 == opcode)
>> + {
>> + /* STRH(1). */
>> + immed_5 = bits (thumb_insn_r->arm_insn, 6,
>> 10);
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 3,
>> 5);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1
>> + ,
>> &u_buf.unsigned_regval);
>> + record_buf_mem[0] = 2;
>> + record_buf_mem[1] = u_buf.unsigned_regval +
>> (immed_5 * 2);
>> + thumb_insn_r->mem_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 101 insns. */
>> +
>> +static int
>> +thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8
>> = 0, immed_5 = 0;
>> + uint32_t register_bits = 0, register_count = 0;
>> + uint32_t register_list[8] = {0}, index = 0,
>> start_address = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode = bits (thumb_insn_r->arm_insn, 11, 12);
>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> + opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
>> +
>> + if (14 == opcode2)
>> + {
>> + /* POP. */
>> + register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> + record_buf[register_count] = ARM_PS_REGNUM;
>> + record_buf[register_count + 1] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = register_count +
>> 2;
>> + for (register_count = 0; register_count < 8;
>> register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + record_buf[index] = register_count;
>> + index++;
>> + }
>> + }
>> + }
>> + else if (10 == opcode2)
>> + {
>> + /* PUSH. */
>> + register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> + regcache_raw_read_unsigned (reg_cache,
>> ARM_PC_REGNUM
>> + ,
>> &u_buf.unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> + start_address = u_buf.unsigned_regval - \
>> + (4 * (bit
>> (thumb_insn_r->arm_insn, 8) + register_count)) ;
>> + thumb_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> + record_buf_mem[(register_count * 2) - 2] =
>> 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + record_buf[0] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (0x1E == opcode1)
>> + {
>> + /* BKPT insn. */
>> + /* Handle enhanced software breakpoint insn,
>> BKPT. */
>> + /* CPSR is changed to be executed in ARM state,
>> disabling normal
>> + interrupts, entering abort mode.
>> */
>> + /* Accorindly to high vector configuration PC is
>> set accordingly. */
>> + /* FIX ME ? what if user hit breakpoint and
>> type reverse, in
>> + that case, we need to go back with
>> previous CPSR and
>> + Program Counter.. */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + thumb_insn_r->reg_rec_count = 2;
>> + /* Save SPSR also; how?. */
>> + printf_unfiltered (_("Process record does not
>> support instruction "
>> + "0x%0x at address
>> %s.\n"),
>> +
>> thumb_insn_r->arm_insn,
>> + paddress
>> (thumb_insn_r->gdbarch,
>> thumb_insn_r->this_addr));
>> + return -1;
>> + }
>> + else if ((0 == opcode) || (1 == opcode))
>> + {
>> + /* ADD(5), ADD(6). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> + record_buf[0] = reg_src1;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> + else if (2 == opcode)
>> + {
>> + /* ADD(7), SUB(4). */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> + record_buf[0] = ARM_SP_REGNUM;
>> + thumb_insn_r->reg_rec_count = 1;
>> + }
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 110 insns. */
>> +
>> +static int
>> +thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
>> +{
>> + struct gdbarch_tdep *tdep = gdbarch_tdep
>> (thumb_insn_r->gdbarch);
>> + struct regcache *reg_cache =
>> thumb_insn_r->regcache;
>> +
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0,
>> register_count = 0;
>> + uint32_t register_list[8] = {0}, index = 0,
>> start_address = 0;
>> + uint32_t record_buf[24], record_buf_mem[48];
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
>> + opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
>> +
>> + if (1 == opcode2)
>> + {
>> +
>> + /* LDMIA. */
>> + register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> + /* Get Rn. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_list[register_count++] = 1;
>> + register_bits = register_bits >> 1;
>> + }
>> + record_buf[register_count] = reg_src1;
>> + thumb_insn_r->reg_rec_count = register_count +
>> 1;
>> + for (register_count = 0; register_count < 8;
>> register_count++)
>> + {
>> + if (register_list[register_count])
>> + {
>> + record_buf[index] = register_count;
>> + index++;
>> + }
>> + }
>> + }
>> + else if (0 == opcode2)
>> + {
>> + /* It handles both STMIA. */
>> + register_bits = bits (thumb_insn_r->arm_insn,
>> 0, 7);
>> + /* Get Rn. */
>> + reg_src1 = bits (thumb_insn_r->arm_insn, 8,
>> 10);
>> + regcache_raw_read_unsigned (reg_cache, reg_src1,
>> &u_buf.unsigned_regval);
>> + while (register_bits)
>> + {
>> + if (register_bits & 0x00000001)
>> + register_count++;
>> + register_bits = register_bits >> 1;
>> + }
>> + start_address = u_buf.unsigned_regval;
>> + thumb_insn_r->mem_rec_count = register_count;
>> + while (register_count)
>> + {
>> + record_buf_mem[(register_count * 2) - 1] =
>> start_address;
>> + record_buf_mem[(register_count * 2) - 2] =
>> 4;
>> + start_address = start_address + 4;
>> + register_count--;
>> + }
>> + }
>> + else if (0x1F == opcode1)
>> + {
>> + /* Handle arm syscall insn. */
>> + if (tdep->arm_swi_record != NULL)
>> + {
>> + tdep->arm_swi_record(reg_cache);
>> + }
>> + else
>> + {
>> + printf_unfiltered (_("no syscall record
>> support\n"));
>> + return -1;
>> + }
>> + }
>> +
>> + /* B(1), conditional branch is automatically taken care
>> in process_record,
>> + as PC is saved there. */
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> + MEM_ALLOC (thumb_insn_r->arm_mems,
>> thumb_insn_r->mem_rec_count,
>> record_buf_mem);
>> +
>> + return 0;
>> +}
>> +
>> +/* Handling opcode 111 insns. */
>> +
>> +static int
>> +thumb_handle_branch_insn (insn_decode_record
>> *thumb_insn_r)
>> +{
>> + uint32_t record_buf[8];
>> + uint32_t reg_val1 = 0;
>> + uint32_t reg_src1 = 0;
>> + uint32_t opcode = 0, immed_5 = 0;
>> +
>> +
>> + /* BL , BLX(1). */
>> + record_buf[0] = ARM_PS_REGNUM;
>> + record_buf[1] = ARM_LR_REGNUM;
>> + thumb_insn_r->reg_rec_count = 2;
>> +
>> + /* B(2) is automatically taken care in process_record,
>> as PC is saved
>> + there. */
>> +
>> + REG_ALLOC (thumb_insn_r->arm_regs,
>> thumb_insn_r->reg_rec_count, record_buf);
>> +
>> + return 0;
>> +}
>> +
>> +
>> +/* Decode arm/thumb insn depending on condition cods and
>> opcodes; and dispatch
>> it. */
>> +
>> +static int
>> +decode_insn (insn_decode_record *arm_record, uint32_t
>> insn_size)
>> +{
>> +
>> + /* (Starting from numerical 0); bits 25, 26, 27 decodes
>> type of arm
>> instruction. */
>> + static int (*const arm_handle_insn[8])
>> +
>> (insn_decode_record*) =
>> + {
>> + arm_handle_data_proc_misc_ld_str_insn, /*
>> 000. */
>> + arm_handle_data_proc_imm_insn,
>> /* 001. */
>> + arm_handle_ld_st_imm_offset_insn, /*
>> 010. */
>> + arm_handle_ld_st_reg_offset_insn, /*
>> 011. */
>> + arm_handle_ld_st_multiple_insn, /*
>> 100. */
>> + arm_handle_brn_insn,
>> /* 101. */
>> + arm_handle_coproc_insn,
>> /* 110. */
>> + arm_handle_coproc_data_proc_insn /*
>> 111. */
>> + };
>> +
>> + /* (Starting from numerical 0); bits 13,14,15 decodes
>> type of thumb
>> instruction. */
>> + static int (*const thumb_handle_insn[8])
>> +
>> (insn_decode_record*) =
>> + { \
>> + thumb_handle_shift_add_sub_insn, /*
>> 000. */
>> + thumb_handle_add_sub_cmp_mov_insn, /*
>> 001. */
>> + thumb_handle_ld_st_reg_offset_insn, /*
>> 010. */
>> + thumb_handle_ld_st_imm_offset_insn, /*
>> 011. */
>> + thumb_handle_ld_st_stack_insn, /*
>> 100. */
>> + thumb_handle_misc_insn,
>> /* 101. */
>> + thumb_handle_swi_insn,
>> /* 110. */
>> + thumb_handle_branch_insn
>> /* 111. */
>> + };
>> +
>> + struct
>> + {
>> + gdb_byte buf[insn_size];
>> + } u_buf;
>> +
>> + uint32_t ret=0, insn_id = 0;
>> +
>> + memset (&u_buf, 0, sizeof(u_buf));
>> + if (target_read_memory (arm_record->this_addr,
>> &u_buf.buf[0], insn_size))
>> + {
>> + if (record_debug)
>> + {
>> + printf_unfiltered (_("Process record: error
>> reading memory at "
>> + "addr %s len
>> = %d.\n"),
>> + paddress (arm_record->gdbarch,
>> arm_record->this_addr), insn_size);
>> + return -1;
>> + }
>> + }
>> + else if (ARM_INSN_SIZE_BYTES == insn_size)
>> + {
>> + arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> + , ARM_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>>
>> + arm_record->cond = bits
>> (arm_record->arm_insn, 28, 31);
>> + insn_id = bits (arm_record->arm_insn, 25,
>> 27);
>> + ret = (0x0F != arm_record->cond)
>> + ? arm_handle_insn[insn_id] (arm_record)
>> + : handle_extension_space (arm_record);
>> + }
>> + else if (THUMB_INSN_SIZE_BYTES == insn_size)
>> + {
>> + /* As thumb does not have condition codes,
>> following field is useless.
>> */
>> + arm_record->cond = -1;
>> + arm_record->arm_insn = (uint32_t)
>> extract_unsigned_integer (&u_buf.buf[0]
>> + , THUMB_INSN_SIZE_BYTES ,
>> gdbarch_byte_order (arm_record->gdbarch));
>> +
>> + insn_id = bits (arm_record->arm_insn, 13,
>> 15);
>> + ret = thumb_handle_insn[insn_id] (arm_record);
>> + }
>> + else if (THUMB2_INSN_SIZE_BYTES == insn_size)
>> + {
>> + /* Yet to be implemented; handle thumb2 part
>> here. */
>> + printf_unfiltered (_("Process record does not
>> support instruction 0x%0x "
>> + "at address %s.\n"),
>> +
>> arm_record->arm_insn,
>> + paddress
>> (arm_record->gdbarch,
>> arm_record->this_addr));
>> + ret = -1;
>> + }
>> + else
>> + {
>> + /* Throw assertion. */
>> + gdb_assert(0);
>> + }
>> +
>> + return ret;
>> +}
>> +
>> +/* Parse the current instruction and record the values of
>> the registers and
>> + memory that will be changed in current instruction to
>> "record_arch_list".
>> + Return -1 if something is wrong.. */
>> +
>> +int
>> +arm_process_record (struct gdbarch *gdbarch, struct
>> regcache *regcache,
>> + CORE_ADDR
>> insn_addr)
>> +{
>> +
>> + enum bfd_endian byte_order = gdbarch_byte_order
>> (gdbarch);
>> + uint32_t no_of_rec = 0;
>> + uint32_t ret = 0;
>> + ULONGEST t_bit = 0;
>> +
>> + struct
>> + {
>> + ULONGEST unsigned_regval;
>> + } u_buf;
>> +
>> + insn_decode_record arm_record;
>> + memset (&u_buf, 0, sizeof(u_buf));
>> +
>> + memset (&arm_record, 0, sizeof
>> (insn_decode_record));
>> + arm_record.regcache = regcache;
>> + arm_record.this_addr = insn_addr;
>> + arm_record.gdbarch = gdbarch;
>> +
>> +
>> + if (record_debug > 1)
>> + {
>> + fprintf_unfiltered (gdb_stdlog, "Process record:
>> arm_process_record "
>> +
>> "addr = %s\n",
>> + paddress (gdbarch, arm_record.this_addr));
>> + }
>> +
>> + /* Check the insn, whether it is thumb or arm one.
>> */
>> +
>> + t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
>> + regcache_raw_read_unsigned (arm_record.regcache,
>> ARM_PS_REGNUM
>> + ,
>> &u_buf.unsigned_regval);
>> +
>> + if (!(u_buf.unsigned_regval & t_bit))
>> + {
>> + /* We are decoding arm insn. */
>> + ret = decode_insn (&arm_record,
>> ARM_INSN_SIZE_BYTES);
>> + }
>> + else
>> + {
>> + /* We are decoding thumb insn. */
>> + ret = decode_insn (&arm_record,
>> THUMB_INSN_SIZE_BYTES);
>> + }
>> +
>> + if (0 == ret)
>> + {
>> + /* Record registers. */
>> + record_arch_list_add_reg (arm_record.regcache,
>> ARM_PC_REGNUM);
>> + if (arm_record.arm_regs)
>> + {
>> + for (no_of_rec = 0; no_of_rec <
>> arm_record.reg_rec_count;
>> no_of_rec++)
>> + {
>> + if (record_arch_list_add_reg
>> (arm_record.regcache \
>> +
>> , (arm_record.arm_regs[no_of_rec])))
>> + ret = -1;
>> + }
>> + }
>> + /* Record memories. */
>> + if (arm_record.arm_mems)
>> + {
>> + for (no_of_rec = 0; no_of_rec <
>> arm_record.mem_rec_count;
>> no_of_rec++)
>> + {
>> + if (record_arch_list_add_mem \
>> +
>> ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
>> +
>> arm_record.arm_mems[no_of_rec].len))
>> + ret = -1;
>> + }
>> + }
>> +
>> + if (record_arch_list_add_end ())
>> + ret = -1;
>> + }
>> +
>> + if (arm_record.arm_regs)
>> + xfree (arm_record.arm_regs);
>> + if (arm_record.arm_mems)
>> + xfree (arm_record.arm_mems);
>> +
>> + return ret;
>> +}
>> diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
>> --- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000
>> +0530
>> +++ arm_new/arm-tdep.h 2011-05-07 14:20:31.000000000
>> +0530
>> @@ -200,6 +200,9 @@
>> /* Return the expected next PC if FRAME is stopped at a
>> syscall
>> instruction. */
>> CORE_ADDR (*syscall_next_pc) (struct frame_info
>> *frame);
>> +
>> + /* Parse swi insn args, sycall record. */
>> + int (*arm_swi_record) (struct regcache *regcache);
>> };
>>
>> /* Structures used for displaced stepping. */
>> @@ -310,6 +313,10 @@
>> struct
>> displaced_step_closure *,
>> CORE_ADDR, CORE_ADDR,
>> struct regcache *);
>>
>> +extern int arm_process_record (struct gdbarch *gdbarch,
>> + struct
>> regcache *regcache, CORE_ADDR addr);
>> +
>> +
>> /* Functions exported from armbsd-tdep.h. */
>>
>> /* Return the appropriate register set for the core
>> section identified
>>
>
^ permalink raw reply [flat|nested] 128+ messages in thread
* Re: [PATCH] arm reversible : <phase_2_complete>
@ 2011-05-24 7:19 paawan oza
0 siblings, 0 replies; 128+ messages in thread
From: paawan oza @ 2011-05-24 7:19 UTC (permalink / raw)
To: Petr Hluzín; +Cc: gdb-patches
Hi,
please find the updated patch below. except one, all from Petr are implemented
in this.
execuse me for typo if any,do not hesitate to point it out.
PATCH STARTS
---------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-05-07 14:20:31.000000000 +0530
@@ -998,6 +998,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record. */
+ set_gdbarch_process_record (gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c 2011-05-24 12:43:20.000000000 +0530
@@ -54,6 +54,8 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
static int arm_debug;
@@ -7929,3 +7931,1736 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* ARM-reversible process record data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+
+#define GET_REG_VAL(REGCACHE,NO,VAL) \
+ regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define GET_REG_VAL_SIGNED(REGCACHE,NO,VAL) \
+ regcache_raw_read_unsigned (REGCACHE, NO, VAL);
+
+#define INSN_S_L_BIT_NUM 20
+
+#define REG_ALLOC(REGS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ if (LENGTH) \
+ { \
+ REGS = (uint32_t*) xmalloc (sizeof(uint32_t) * (LENGTH)); \
+ while(LENGTH) \
+ { \
+ REGS[LENGTH - 1] = RECORD_BUF[LENGTH - 1]; \
+ LENGTH--; \
+ } \
+ } \
+ } \
+while (0)
+
+#define MEM_ALLOC(MEMS,LENGTH,RECORD_BUF) \
+do \
+ { \
+ if (LENGTH) \
+ { \
+ MEMS = (struct arm_mem_r *)xmalloc \
+ (sizeof(struct arm_mem_r) * (LENGTH)); \
+ while(LENGTH) \
+ { \
+ MEMS[LENGTH - 1].addr = RECORD_BUF[(LENGTH * 2) - 1]; \
+ MEMS[LENGTH - 1].len = RECORD_BUF[(LENGTH * 2) - 2]; \
+ LENGTH--; \
+ } \
+ } \
+ } \
+while (0)
+
+
+/* ARM memory record structure. */
+struct arm_mem_r
+{
+ uint32_t len; /* record length. */
+ CORE_ADDR addr; /* memory address. */
+};
+
+/* ARM instruction record.
+contains opcode of current insn and execution state (before entry to
+decode_insn() ),
+contains list of to-be-modified registers and memory blocks (on return from
+decode_insn() ). */
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* address of the insn being decoded. */
+ uint32_t arm_insn; /* should accommodate thumb. */
+ uint32_t cond; /* condition code. */
+ uint32_t opcode; /* insn opcode. */
+ uint32_t decode; /* insn decode bits. */
+ uint32_t mem_rec_count; /* no of mem recors */
+ uint32_t reg_rec_count; /* no of reg records */
+ uint32_t *arm_regs; /* registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* memory to be saved for this record. */
+} insn_decode_record;
+
+
+/* checks ARM SBZ and SBO mendatory fields. */
+
+static int
+sbo_sbz (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ones = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if(!sbo)
+ ones = ~ones;
+
+ while (ones)
+ {
+ if (!(ones & sbo))
+ {
+ return 0;
+ }
+ ones = ones >> 1;
+ }
+ return 1;
+}
+
+/* handling ARM extension space insns. */
+
+static int
+handle_extension_space (insn_decode_record *arm_insn_r)
+{
+ uint32_t ret = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((!opcode1) && (9 == opcode2))
+ {
+ ret = -1;
+ /* handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+ {
+ ret = -1;
+ /* handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+ && (bit(arm_insn_r->arm_insn, 4)))
+ {
+ ret = -1;
+ /* handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+ {
+ ret = -1;
+ /* handle coprocessor insn extension space. */
+ }
+
+ /* to be done for ARMv5 and later; as of now we return -1. */
+ if (-1 == ret)
+ 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 ret;
+}
+
+/* handling opcode 000 insns. */
+
+static int
+arm_handle_data_proc_misc_ld_str_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* handle MLA and MUL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* handle SMLAL, SMULL, UMLAL, UMULL. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ record_buf[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[2] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 3;
+ }
+ }
+ else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is preccedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 5, 12, 0))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+ {
+ /* handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* 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;
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* Handling SWP, SWPB. */
+ /* these insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ /* get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ record_buf_mem[0] = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ record_buf_mem[0] = 1;
+ }
+ record_buf_mem[1] = u_buf[0].unsigned_regval;
+ arm_insn_r->mem_rec_count = 1;
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1)))
+ {
+ /* handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly */
+ /* what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ 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)
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) handle misc store, immediate offset. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1,
&u_buf[0].unsigned_regval);
+ if (15 == reg_src1)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) store, register offset. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) store, immediate pre-indexed. */
+ /* 5) store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval - offset_8;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) store, register pre-indexed. */
+ /* 6) store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval + u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - u_buf[0].unsigned_regval;
+ }
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+ /* record Rn also as it changes. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && sbo_sbz (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* handle BX, branch and link/exchange. */
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && (sbo_sbz (arm_insn_r->arm_insn, 9, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1)))
+ {
+ /* count leading zeros: CLZ. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (sbo_sbz (arm_insn_r->arm_insn, 17, 4, 1))
+ && (sbo_sbz (arm_insn_r->arm_insn, 1, 12, 0))
+ )
+ {
+ /* handle MRS insn. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 001 insns. */
+
+static int
+arm_handle_data_proc_imm_insn (insn_decode_record *arm_insn_r)
+{
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && (sbo_sbz (arm_insn_r->arm_insn, 13, 4, 1))
+ )
+ {
+ /* handle MSR insn. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ record_buf[0] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ /* Oza: FIX ME ? how to read SPSR value? */
+ }
+ }
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ gdb_assert_not_reached ("no decoding pattern found");
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 010 insns. */
+
+static int
+arm_handle_ld_st_imm_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_dest = 0;
+ uint32_t offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.unsigned_regval - offset_12;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* we are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 011 insns. */
+
+static int
+arm_handle_ld_st_reg_offset_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ struct
+ {
+ ULONGEST signed_word;
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ record_buf[0] = reg_dest;
+ record_buf[1] = ARM_PS_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].unsigned_regval);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ /* pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].unsigned_regval = u_buf[0].unsigned_regval + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].unsigned_regval +
u_buf[1].unsigned_regval;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval -
u_buf[0].unsigned_regval;
+ }
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ else
+ {
+ /* store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL_SIGNED (reg_cache, reg_src1, &u_buf[0].signed_word);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* offset_12 used as shift. */
+ switch(offset_12)
+ {
+ case 0:
+ /* offset_12 used as index. */
+ offset_12 = u_buf[0].unsigned_regval << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].unsigned_regval >>
shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].unsigned_regval, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* this is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ GET_REG_VAL (reg_cache, ARM_PS_REGNUM,
&u_buf[1].unsigned_regval);
+ /* get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].unsigned_regval, 29)) << 31)
\
+ | (u_buf[0].unsigned_regval) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].unsigned_regval >> shift_imm) \
+ | (u_buf[0].unsigned_regval << (sizeof(uint32_t) -
shift_imm));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].unsigned_regval - offset_12;
+ }
+
+ switch (arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ record_buf_mem[0] = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ record_buf_mem[0] = 1;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+ record_buf_mem[1] = tgt_mem_addr;
+ arm_insn_r->mem_rec_count = 1;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ record_buf[0] = reg_src2;
+ arm_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 100 insns. */
+
+static int
+arm_handle_ld_st_multiple_insn (insn_decode_record *arm_insn_r)
+{
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16]={0}, register_count=0, register_bits=0;
+ uint32_t shift_imm=0;
+ uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+ uint32_t start_address=0, index = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* this mode is exclusively for load and store multiple. */
+ /* handle incremenrt after/before and decrment after.before mode;
+ Rn is changing depending on W bit, but as of now we store Rn too
without optmization. */
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDR (1,2,3) where LDR (3) changes CPSR too. */
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* extra space for Base Register and CPSR; wihtout optmization. */
+ record_buf[register_count] = reg_src1;
+ record_buf[register_count + 1] = ARM_PS_REGNUM;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ /* register_count gives total no of registers and dually working
+ as reg number. */
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ arm_insn_r->reg_rec_count = register_count + 2;
+ }
+ else
+ {
+ /* it handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch(addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4) +
4;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ arm_insn_r->mem_rec_count = register_count;
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].unsigned_regval;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ arm_insn_r->mem_rec_count = register_count;
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].unsigned_regval) - (register_count * 4);
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ arm_insn_r->mem_rec_count = register_count;
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].unsigned_regval + 4;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ arm_insn_r->mem_rec_count = register_count;
+ break;
+
+ default:
+ gdb_assert_not_reached ("Invalid addressing mode for insn");
+ break;
+ }
+
+ /* base register also changes; based on condition and W bit. */
+ /* we save it anyway without optimization. */
+ record_buf[0] = reg_src1;
+ arm_insn_r->reg_rec_count = 1;
+ }
+
+ 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);
+ return 0;
+}
+
+/* handling opcode 101 insns. */
+
+static int
+arm_handle_brn_insn (insn_decode_record *arm_insn_r)
+{
+
+ uint32_t record_buf[8];
+
+ /* handle B, BL, BLX(1) insns. */
+ /* wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ arm_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (arm_insn_r->arm_regs, arm_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* handling opcode 110 insns. */
+
+static int
+arm_handle_coproc_insn (insn_decode_record *arm_insn_r)
+{
+ 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;
+}
+
+/* handling opcode 111 insns. */
+
+static int
+arm_handle_coproc_data_proc_insn (insn_decode_record *arm_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ 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;
+}
+
+/* handling opcode 000 insns. */
+
+static int
+thumb_handle_shift_add_sub_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* handling opcode 001 insns. */
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_src1 = 0;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+/* handling opcode 010 insns. */
+
+static int
+thumb_handle_ld_st_reg_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* handle load/store register offset. */
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].unsigned_regval);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].unsigned_regval);
+ if (8 == opcode2)
+ record_buf_mem[0] = 4; /* STR (2). */
+ else if (10 == opcode2)
+ record_buf_mem[0] = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ record_buf_mem[0] = 2; /* STRH (2). */
+ record_buf_mem[1] =
u_buf[0].unsigned_regval+u_buf[1].unsigned_regval;
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* branch with exchange. */
+ record_buf[0] = ARM_PS_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ 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;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ /* format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = reg_src1;
+ thumb_insn_r->reg_rec_count = 2;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 001 insns. */
+
+static int
+thumb_handle_ld_st_imm_offset_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 100 insns. */
+
+static int
+thumb_handle_ld_st_stack_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+ uint32_t record_buf[8], record_buf_mem[8];
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 4;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_8 * 4);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ record_buf_mem[0] = 2;
+ record_buf_mem[1] = u_buf.unsigned_regval + (immed_5 * 2);
+ thumb_insn_r->mem_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 101 insns. */
+
+static int
+thumb_handle_misc_insn (insn_decode_record *thumb_insn_r)
+{
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = ARM_PS_REGNUM;
+ record_buf[register_count + 1] = ARM_SP_REGNUM;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ thumb_insn_r->reg_rec_count = register_count + 2;
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ thumb_insn_r->mem_rec_count = register_count;
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly. */
+ /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+ /* save SPSR also; how?. */
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),
+ thumb_insn_r->arm_insn,
+ paddress (thumb_insn_r->gdbarch,
thumb_insn_r->this_addr));
+ return -1;
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = reg_src1;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ record_buf[0] = ARM_SP_REGNUM;
+ thumb_insn_r->reg_rec_count = 1;
+ }
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 110 insns. */
+
+static int
+thumb_handle_swi_insn (insn_decode_record *thumb_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+ uint32_t record_buf[24], record_buf_mem[48];
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ record_buf[register_count] = reg_src1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ record_buf[index] = register_count;
+ index++;
+ }
+ }
+ thumb_insn_r->reg_rec_count = register_count + 1;
+ }
+ else if (0 == opcode2)
+ {
+ /* it handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.unsigned_regval);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.unsigned_regval;
+ while (register_count)
+ {
+ record_buf_mem[(register_count * 2) - 1] = start_address;
+ record_buf_mem[(register_count * 2) - 2] = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ thumb_insn_r->mem_rec_count = register_count;
+ }
+ else if (0x1F == opcode1)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ printf_unfiltered (_("no syscall record support\n"));
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+ MEM_ALLOC (thumb_insn_r->arm_mems, thumb_insn_r->mem_rec_count,
record_buf_mem);
+
+ return 0;
+}
+
+/* handling opcode 111 insns. */
+
+static int
+thumb_handle_branch_insn (insn_decode_record *thumb_insn_r)
+{
+ uint32_t record_buf[8];
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+
+ /* BL , BLX(1). */
+ record_buf[0] = ARM_PS_REGNUM;
+ record_buf[1] = ARM_LR_REGNUM;
+ thumb_insn_r->reg_rec_count = 2;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+
+ REG_ALLOC (thumb_insn_r->arm_regs, thumb_insn_r->reg_rec_count, record_buf);
+
+ return 0;
+}
+
+
+/* decode arm/thumb insn depending on condition cods and opcodes; and dispatch
it. */
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ static int (*const arm_handle_insn[8])
+ (insn_decode_record*) =
+ {
+ arm_handle_data_proc_misc_ld_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_handle_ld_st_multiple_insn, /* 100. */
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ static int (*const thumb_handle_insn[8])
+ (insn_decode_record*) =
+ { \
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_handle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+ thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ struct
+ {
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0, insn_id = 0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , ARM_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ insn_id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)
+ ? arm_handle_insn[insn_id] (arm_record)
+ : handle_extension_space (arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ /* As thumb does not have condition codes, following field is useless.
*/
+ arm_record->cond = -1;
+ arm_record->arm_insn = (uint32_t) extract_unsigned_integer (&u_buf.buf[0]
+ , THUMB_INSN_SIZE_BYTES , gdbarch_byte_order (arm_record->gdbarch));
+
+ insn_id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[insn_id] (arm_record);
+ }
+ else if (THUMB2_INSN_SIZE_BYTES == insn_size)
+ {
+ /* yet to be implemented; handle thumb2 part here. */
+ printf_unfiltered (_("Process record does not support instruction 0x%0x "
+ "at address %s.\n"),
+ arm_record->arm_insn,
+ paddress (arm_record->gdbarch,
arm_record->this_addr));
+ ret = -1;
+ }
+ else
+ {
+ /* throw assertion. */
+ gdb_assert(0);
+ }
+
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t no_of_rec = 0;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0;
+
+ struct
+ {
+ ULONGEST unsigned_regval;
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.unsigned_regval);
+
+ if (!(u_buf.unsigned_regval & t_bit))
+ {
+ /* we are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* we are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ if (0 == ret)
+ {
+ /* record registers. */
+ record_arch_list_add_reg (arm_record.regcache, ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.reg_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_reg (arm_record.regcache \
+ ,
(arm_record.arm_regs[no_of_rec])));
+ ret = -1;
+ }
+ }
+ /* record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec = 0; no_of_rec < arm_record.mem_rec_count;
no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+ }
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h 2011-05-07 14:20:31.000000000 +0530
@@ -200,6 +200,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi insn args, sycall record. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -310,6 +313,10 @@
struct displaced_step_closure *,
CORE_ADDR, CORE_ADDR, struct regcache *);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
+
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
^ permalink raw reply [flat|nested] 128+ messages in thread
[parent not found: <341905.10459.qm@web112513.mail.gq1.yahoo.com>]
* [PATCH] arm reversible <phase_2_complete>
@ 2011-04-20 19:10 oza Pawandeep
0 siblings, 0 replies; 128+ messages in thread
From: oza Pawandeep @ 2011-04-20 19:10 UTC (permalink / raw)
To: gdb-patches, gdb
Hi,
I am working on phase-3 now.
if anybody could please start reviewing phase-2 patch (as this is
independent of phase-3 and could be checked in independently too)
I may start implementing review comments as and when I get.
In Parallel, test cases are also being worked upon.
following is the phase-2 patch.
PATCH STARTS.
------------------------------
diff -urN arm_orig/arm-linux-tdep.c arm_new/arm-linux-tdep.c
--- arm_orig/arm-linux-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-linux-tdep.c 2011-04-15 13:11:15.000000000 +0530
@@ -998,6 +998,9 @@
set_gdbarch_fetch_tls_load_module_address (gdbarch,
svr4_fetch_objfile_link_map);
+ /* Enable process record */
+ set_gdbarch_process_record(gdbarch, arm_process_record);
+
tramp_frame_prepend_unwinder (gdbarch,
&arm_linux_sigreturn_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch,
@@ -1025,6 +1028,8 @@
tdep->syscall_next_pc = arm_linux_syscall_next_pc;
+
+ tdep->arm_swi_record = NULL;
}
/* Provide a prototype to silence -Wmissing-prototypes. */
diff -urN arm_orig/arm-tdep.c arm_new/arm-tdep.c
--- arm_orig/arm-tdep.c 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.c 2011-04-15 13:11:15.000000000 +0530
@@ -54,8 +54,11 @@
#include "gdb_assert.h"
#include "vec.h"
+#include "record.h"
+
#include "features/arm-with-m.c"
+
static int arm_debug;
/* Macros for setting and testing a bit in a minimal symbol that marks
@@ -7929,3 +7932,1692 @@
NULL, /* FIXME: i18n: "ARM debugging is %s. */
&setdebuglist, &showdebuglist);
}
+
+
+
+/* arm-reversible process reacord data structures. */
+
+#define ARM_INSN_SIZE_BYTES 4
+#define THUMB_INSN_SIZE_BYTES 2
+#define THUMB2_INSN_SIZE_BYTES 4
+#define NO_OF_TYPE_OF_ARM_INSNS 8
+#define NO_OF_TYPE_OF_THUMB_INSNS 8
+#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
+ record_arch_list_add_reg (arm_record.regcache, regnum)
+#define GET_REG_VAL(REGCACHE,NO,BUF) regcache_raw_read (REGCACHE, NO, BUF);
+#define INSN_S_L_BIT_NUM 20
+
+struct arm_mem_r
+{
+ uint32_t len;
+ CORE_ADDR addr;
+};
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr; /* address of the insn being decoded. */
+ uint32_t arm_insn; /* should accomodate thumb. */
+ uint32_t cond; /* condition code. */
+ uint32_t id; /* type of insn. */
+ uint32_t opcode; /* insn opcode. */
+ uint32_t decode; /* insn decode bits. */
+ uint32_t *arm_regs; /* registers to be saved for this record. */
+ struct arm_mem_r *arm_mems; /* memory to be saved for this record. */
+} insn_decode_record;
+
+
+static int
+SBO_SBZ (uint32_t insn, uint32_t bit_num, uint32_t len, uint32_t sbo)
+{
+ uint32_t ONES = bits (insn, bit_num - 1, (bit_num -1) + (len - 1));
+
+ if (!len)
+ return 1;
+
+ if(!sbo)
+ ONES = ~ONES;
+
+ while (ONES)
+ {
+ if (!(ONES & sbo))
+ {
+ return 0;
+ }
+ ONES = ONES >> 1;
+ }
+ return 1;
+}
+
+static int
+handle_extension_space (insn_decode_record *arm_record)
+{
+ insn_decode_record *arm_insn_r = arm_record;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0;
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((3 == opcode1) && (bit (arm_insn_r->arm_insn, 4)))
+ {
+ /* undefined instruction on ARM V5; need to handle if later versions
+ define it. */
+ }
+
+ opcode2 = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if ((!opcode1) && (9 == opcode2))
+ {
+ /* handle arithmetic insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 26, 27);
+ opcode2 = bits (arm_insn_r->arm_insn, 23, 24);
+
+ if ((!opcode1) && (2 == opcode2) && (!bit (arm_insn_r->arm_insn, 20)))
+ {
+ /* handle control insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 25, 27);
+ if ((!opcode1) && (bit (arm_insn_r->arm_insn, 7)) \
+ && (bit(arm_insn_r->arm_insn, 4)))
+ {
+ /* handle load/store insn extension space. */
+ }
+
+ opcode1 = bits (arm_insn_r->arm_insn, 23, 27);
+ if ((24 == opcode1) && (bit (arm_insn_r->arm_insn, 21)))
+ {
+ /* handle coprocessor insn extension space. */
+ }
+
+ /* to be done for ARMv5 and later; as of now we return -1. */
+ return -1;
+}
+
+static int
+arm_handle_data_proc_misc_load_str_insn (void *data)
+{
+
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0,offset_8 = 0, tgt_mem_addr = 0;
+ uint32_t opcode1 = 0;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+ opcode1 = bits (arm_insn_r->arm_insn, 20, 24);
+
+ /* data processing insn /multiply insn. */
+ if ((9 == arm_insn_r->decode)
+ && (((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ || ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))))
+ {
+ /* handle multiply instructions. */
+ /* MLA, MUL, SMLAL, SMULL, UMLAL, UMULL. */
+ if ((0 == arm_insn_r->opcode) || (1 == arm_insn_r->opcode))
+ {
+ /* handle MLA and MUL. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ else if ((4 <= arm_insn_r->opcode) && (7 >= arm_insn_r->opcode))
+ {
+ /* handle SMLAL, SMULL, UMLAL, UMULL. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*4);
+ arm_insn_r->arm_regs[0] = 3;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ arm_insn_r->arm_regs[2] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->arm_regs[3] = ARM_PS_REGNUM;
+ }
+ }
+ else if ((bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((11 == arm_insn_r->decode) || (13 == arm_insn_r->decode)))
+ {
+ /* handle misc load insns, as 20th bit (L = 1). */
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. I am not sure this is right
+ place as opcode = 010 LDR insn make this happen, if R15 was
+ used. */
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ if (15 != reg_dest)
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ else
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = reg_dest;
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ }
+ else if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (SBO_SBZ (arm_insn_r->arm_insn, 5, 12, 0))
+ && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21)))
+ {
+ /* handle MSR insn. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ if (9 == arm_insn_r->opcode)
+ {
+ /* CSPR is going to be changed. */
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ /* Oza: FIX ME ? how to read SPSR value ? */
+ }
+ }
+ else if ((9 == arm_insn_r->decode)
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* Handling SWP, SWPB. */
+ /* these insns, changes register and memory as well. */
+ /* SWP or SWPB insn. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ /* get memory address given by Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ arm_insn_r->arm_mems[0].len = 1;
+ /* SWP insn ?, swaps word. */
+ if (8 == arm_insn_r->opcode)
+ {
+ arm_insn_r->arm_mems[1].len = 4;
+ }
+ else
+ {
+ /* SWPB insn, swaps only byte. */
+ arm_insn_r->arm_mems[1].len = 1;
+ }
+ arm_insn_r->arm_mems[1].addr = u_buf[0].s_word;
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ else if ((3 == arm_insn_r->decode) && (0x12 == opcode1)
+ && (SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1)))
+ {
+ /* handle BLX, branch and link/exchange. */
+ if (9 == arm_insn_r->opcode)
+ {
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm,
+ and R14 stores the return address. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+ }
+ }
+ else if ((7 == arm_insn_r->decode) && (0x12 == opcode1))
+ {
+ /* handle enhanced software breakpoint insn, BKPT */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly */
+ /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+ /* save SPSR also; how? */
+ }
+ else if ((11 == arm_insn_r->decode)
+ && (!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM)))
+ {
+ /* handle enhanced store insns and DSP insns (e.g. LDRD)
+ let us begin according to addressing modes for store insns
+ STRH insn, addresing modes are taken following. */
+ if ((14 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ {
+ /* 1) handle misc store, immediate offset. */
+ printf("handling store insn, immed offfset insn\n");
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ if (15 == reg_src1)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].s_word = u_buf[0].s_word + 8;
+ }
+ offset_8 = (immed_high << 4) | immed_low;
+ /* calculate target store address. */
+ if (14 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].s_word + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].s_word - offset_8;
+ }
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ arm_insn_r->arm_mems[1].len = 2;
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ }
+ else if ((12 == arm_insn_r->opcode) || (8 == arm_insn_r->opcode))
+ {
+ /* 2) store, register offset. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].buf[0]);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ u_buf[0].s_word = u_buf[0].s_word + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if (12 == arm_insn_r->opcode)
+ {
+ tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+ }
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ arm_insn_r->arm_mems[1].len = 2;
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ }
+ else if ((11 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (2 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ /* 3) store, immediate pre-indexed. */
+ /* 5) store, immediate post-indexed. */
+ immed_low = bits (arm_insn_r->arm_insn, 0, 3);
+ immed_high = bits (arm_insn_r->arm_insn, 8, 11);
+ offset_8 = (immed_high << 4) | immed_low;
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL(reg_cache, reg_src1, &u_buf[0].buf[0]);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((15 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].s_word + offset_8;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[0].s_word - offset_8;
+ }
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ arm_insn_r->arm_mems[1].len = 2;
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ /* record Rn also as it changes. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16, 19);
+ }
+ else if ((9 == arm_insn_r->opcode) || (13 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ /* 4) store, register pre-indexed. */
+ /* 6) store, register post -indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ if ((13 == arm_insn_r->opcode) || (4 == arm_insn_r->opcode))
+ {
+ tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+ }
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ arm_insn_r->arm_mems[1].len = 2;
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ /* record Rn also as it changes. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 16,
19);
+ }
+ /* DSP insns (e.g. LDRD) TBD. */
+ }
+ else if ((1 == arm_insn_r->decode) && (0x12 == opcode1)
+ && SBO_SBZ (arm_insn_r->arm_insn, 9, 12, 1))
+ {
+ /* handle BX, branch and link/exchange. */
+ /* branch is chosen by setting T bit of CSPR, bitp[0] of Rm. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ }
+ else if ((1 == arm_insn_r->decode) && (0x16 == opcode1)
+ && SBO_SBZ (arm_insn_r->arm_insn, 9, 4, 1)
+ && SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+ {
+ /* count leading zeros: CLZ. */
+ printf("handling CLZ - count leading zero insn\n");
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ else if ((!bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ && ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode))
+ && (SBO_SBZ (arm_insn_r->arm_insn, 17, 4, 1))
+ && (SBO_SBZ (arm_insn_r->arm_insn, 1, 12, 0))
+ )
+ {
+ /* handle MRS insn. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ /* following is always true, in case none of the above conditions meet, it
will fall here. */
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ return 0;
+}
+
+static int
+arm_handle_data_proc_imm_insn (void *data)
+{
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_8 = 0, tgt_mem_addr = 0;
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode))
+ && (2 == bits (arm_insn_r->arm_insn, 20, 21))
+ && (SBO_SBZ (arm_insn_r->arm_insn, 13, 4, 1))
+ )
+ {
+ /* handle MSR insn. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ if (9 == arm_insn_r->opcode)
+ {
+ /*CSPR is going to be changed. */
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ }
+ else
+ {
+ /* SPSR is going to be changed. */
+ /* Oza: FIX ME ? how to read SPSR value? */
+ }
+ }
+ /* following is always true, in case none of the above conditions meet, it
will fall
+ here. */
+ else if (arm_insn_r->opcode <= 15)
+ {
+ /* normal data processing insns. */
+ /* out of 11 shifter operands mode, all the insn modifies destination
+ register, which is specified by 13-16 decode. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ return 0;
+}
+
+static int
+arm_handle_ld_st_imm_offset_insn (void *data)
+{
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t reg_src1 = 0 , reg_src2= 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ else
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = reg_dest;
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* store, immediate offset, immediate pre-indexed,
+ immediate post-indexed. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ offset_12 = bits (arm_insn_r->arm_insn, 0, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf.s_word + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf.s_word - offset_12;
+ }
+
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ arm_insn_r->arm_mems[1].len = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ arm_insn_r->arm_mems[1].len = 1;
+ break;
+
+ default:
+ /* rest of the insns are unreachable for this addressing mode.
*/
+ break;
+ }
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ /* we are handling pre-indexed mode; post-indexed mode;
+ where Rn is going to be changed. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc
(sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = reg_src1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+arm_handle_ld_st_reg_offset_insn (void *data)
+{
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, reg_dest = 0;
+ uint32_t immed_high = 0, immed_low = 0, offset_12 = 0, tgt_mem_addr = 0;
+
+ union
+ {
+ int32_t signed_word;
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ memset(&u_buf, 0, sizeof(u_buf));
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 21, 24);
+ arm_insn_r->decode = bits (arm_insn_r->arm_insn, 4, 7);
+
+ /* handle enhanced store insns and LDRD DSP insn,
+ let us begin according to addressing modes for store insns
+ STRH insn. */
+
+ /* LDR or STR? */
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ reg_dest = bits (arm_insn_r->arm_insn, 12, 15);
+ /* LDR insn has a capability to do branching, if
+ MOV LR, PC is precedded by LDR insn having Rn as R15
+ in that case, it emulates branch and link insn, and hence we
+ need to save CSPR and PC as well. */
+ if (15 != reg_dest)
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = bits (arm_insn_r->arm_insn, 12, 15);
+ }
+ else
+ {
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = reg_dest;
+ arm_insn_r->arm_regs[2] = ARM_PS_REGNUM;
+ }
+ }
+ else
+ {
+ if ((8 == arm_insn_r->opcode) || (10 == arm_insn_r->opcode)
+ || (12 == arm_insn_r->opcode) || (14 == arm_insn_r->opcode)
+ || (9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ if (! bits (arm_insn_r->arm_insn, 4, 11))
+ {
+ /* store insn, register offset and register pre-indexed,
+ register post-indexed. */
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ GET_REG_VAL (reg_cache, reg_src2,
&u_buf[1].buf[0]);
+ if (15 == reg_src2)
+ {
+ /* if R15 was used as Rn, hence current PC+8. */
+ /* pre-indexed mode doesnt reach here ; illegal insn. */
+ u_buf[0].s_word = u_buf[0].s_word + 8;
+ }
+ /* calculate target store address, Rn +/- Rm, register offset. */
+ /* U == 1. */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[0].s_word + u_buf[1].s_word;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].s_word - u_buf[0].s_word;
+ }
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ switch(arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ arm_insn_r->arm_mems[1].len = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ arm_insn_r->arm_mems[1].len = 1;
+ break;
+
+ default:
+ /* rest of the insns are unreachable for this addr mode. */
+ break;
+ }
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ arm_insn_r->arm_regs = \
+ (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ /* Rn is going to be changed in pre-indexed mode and
+ post-indexed mode as well. */
+ arm_insn_r->arm_regs[1] = reg_src2;
+ }
+ }
+ else
+ {
+ /* store insn, scaled register offset; scaled pre-indexed. */
+ offset_12 = bits (arm_insn_r->arm_insn, 5, 6);
+ /* get Rm. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 0, 3);
+ /* get Rn. */
+ reg_src2 = bits (arm_insn_r->arm_insn, 16, 19);
+ /* get shift_imm. */
+ shift_imm = bits (arm_insn_r->arm_insn, 7, 11);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+ /* offset_12 used as shift. */
+ switch(offset_12)
+ {
+ case 0:
+ /* offset_12 used as index. */
+ offset_12 = u_buf[0].s_word << shift_imm;
+ break;
+
+ case 1:
+ offset_12 = (!shift_imm)?0:u_buf[0].s_word >> shift_imm;
+ break;
+
+ case 2:
+ if (!shift_imm)
+ {
+ if (bit (u_buf[0].s_word, 31))
+ {
+ offset_12 = 0xFFFFFFFF;
+ }
+ else
+ {
+ offset_12 = 0;
+ }
+ }
+ else
+ {
+ /* this is arithmetic shift. */
+ offset_12 = u_buf[0].signed_word >> shift_imm;
+ }
+ break;
+
+ case 3:
+ if (!shift_imm)
+ {
+ GET_REG_VAL (reg_cache, ARM_PS_REGNUM, &u_buf[1].buf[0]);
+ /* get C flag value and shift it by 31. */
+ offset_12 = (((bit (u_buf[1].s_word, 29)) << 31) \
+ | (u_buf[0].s_word) >> 1);
+ }
+ else
+ {
+ offset_12 = (u_buf[0].s_word >> shift_imm) \
+ | (u_buf[0].s_word <<
(sizeof(uint32_t)-shift_imm));
+ }
+ break;
+
+ default:
+ /* unreachable. */
+ break;
+ }
+
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+ /* U == 1 */
+ if (bit (arm_insn_r->arm_insn, 23))
+ {
+ tgt_mem_addr = u_buf[1].s_word + offset_12;
+ }
+ else
+ {
+ tgt_mem_addr = u_buf[1].s_word - offset_12;
+ }
+
+ arm_insn_r->arm_mems = (struct arm_mem_r *)
+ xmalloc (sizeof(struct arm_mem_r)*2);
+ arm_insn_r->arm_mems[0].len = 1;
+ arm_insn_r->arm_mems[1].addr = tgt_mem_addr;
+ switch (arm_insn_r->opcode)
+ {
+ case 8:
+ case 12:
+ case 9:
+ case 13:
+ case 1:
+ case 5:
+ /* STR insn, STRT insn. */
+ arm_insn_r->arm_mems[1].len = 4;
+ break;
+
+ case 10:
+ case 14:
+ case 11:
+ case 15:
+ case 3:
+ case 7:
+ /* STRB insn, STRBT insn. */
+ arm_insn_r->arm_mems[1].len = 1;
+ break;
+
+ default:
+ /* rest of the insns are unreachable for this addr mode. */
+ break;
+ }
+ if ((9 == arm_insn_r->opcode) || (11 == arm_insn_r->opcode)
+ || (13 == arm_insn_r->opcode) || (15 == arm_insn_r->opcode)
+ || (0 == arm_insn_r->opcode) || (2 == arm_insn_r->opcode)
+ || (4 == arm_insn_r->opcode) || (6 == arm_insn_r->opcode)
+ || (1 == arm_insn_r->opcode) || (3 == arm_insn_r->opcode)
+ || (5 == arm_insn_r->opcode) || (7 == arm_insn_r->opcode))
+ {
+ arm_insn_r->arm_regs = \
+ (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ /* Rn is going to be changed in register scaled pre-indexed
+ mode, and scaled post indexed mode. */
+ arm_insn_r->arm_regs[1] = reg_src2;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+arm_hamdle_ld_st_multiple_insn (void *data)
+{
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t register_list[16]={0}, register_count=0, register_bits=0;
+ uint32_t shift_imm=0;
+ uint32_t reg_src1=0, reg_src2=0, addr_mode=0;
+ uint32_t start_address=0, index = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ /* this mode is exclusively for load and store multiple. */
+ /* handle incremenrt after/before and decrment after.before mode;
+ Rn is chaging depending on W bit, but as of now we store Rn too wihtout
going for
+ optmization. */
+
+
+ if (bit (arm_insn_r->arm_insn, INSN_S_L_BIT_NUM))
+ {
+ /* LDR (1,2,3) where LDR (3) changes CPSR too. */
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+
+ /* extra space for Base Register and CPSR; wihtout optmization. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc \
+ (sizeof(uint32_t) * (register_count +
3));
+ arm_insn_r->arm_regs[0] = register_count + 2;
+ arm_insn_r->arm_regs[register_count+1] = reg_src1;
+ arm_insn_r->arm_regs[register_count+2] = ARM_PS_REGNUM;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ arm_insn_r->arm_regs[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else
+ {
+ /* it handles both STM(1) and STM(2). */
+ addr_mode = bits (arm_insn_r->arm_insn, 23, 24);
+
+ register_bits = bits (arm_insn_r->arm_insn, 0, 15);
+ /* get Rn. */
+ reg_src1 = bits (arm_insn_r->arm_insn, 16, 19);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+
+ switch(addr_mode)
+ {
+ /* Decrement after. */
+ case 0:
+ start_address = (u_buf[0].s_word) - (register_count * 4) + 4;
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count+1));
+ arm_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ arm_insn_r->arm_mems[register_count].addr = start_address;
+ arm_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment after. */
+ case 1:
+ start_address = u_buf[0].s_word;
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count+1));
+ arm_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ arm_insn_r->arm_mems[register_count].addr = start_address;
+ arm_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Decrement before. */
+ case 2:
+
+ start_address = (u_buf[0].s_word) - (register_count * 4);
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count+1));
+ arm_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ arm_insn_r->arm_mems[register_count].addr = start_address;
+ arm_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ /* Increment before. */
+ case 3:
+ start_address = u_buf[0].s_word + 4;
+ arm_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count+1));
+ arm_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ arm_insn_r->arm_mems[register_count].addr = start_address;
+ arm_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ break;
+
+ default:
+ /* unreachable. */
+ break;
+ }
+
+ /* base register also changes; based on condition and W bit. */
+ /* we save it anyway without optimization. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ arm_insn_r->arm_regs[0] = 1;
+ arm_insn_r->arm_regs[1] = reg_src1;
+ }
+ return 0;
+}
+
+static int
+arm_handle_brn_insn (void *data)
+{
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ /* handle B, BL, BLX(1) insns. */
+ /* wihtout optmization we save link register,
+ CSPR for the insn which changes T bit. */
+ arm_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ arm_insn_r->arm_regs[0] = 2;
+ arm_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ arm_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+ return 0;
+}
+
+static int
+arm_handle_coproc_insn (void *data)
+{
+ return -1;
+}
+
+static int
+arm_handle_coproc_data_proc_insn (void *data)
+{
+
+ insn_decode_record *arm_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
+ struct regcache *reg_cache = arm_insn_r->regcache;
+
+ uint32_t shift_imm = 0;
+ uint32_t reg_src1 = 0, reg_src2 = 0, addr_mode = 0;
+ uint32_t start_address = 0;
+
+ /* handle SWI insn; system call would be handled over here. */
+
+ arm_insn_r->opcode = bits (arm_insn_r->arm_insn, 24, 27);
+ if (15 == arm_insn_r->opcode)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ return -1;
+}
+
+
+static int
+thumb_handle_shift_add_sub_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep ( thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_src1 = 0;
+
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = reg_src1;
+
+ return 0;
+}
+
+static int
+thumb_handle_add_sub_cmp_mov_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_src1 = 0;
+
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = reg_src1;
+
+ return 0;
+}
+
+static int
+thumb_handle_ld_st_reg_offset_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = thumb_insn_r->regcache;
+
+ uint32_t reg_src1 = 0, reg_src2 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, opcode3 = 0;
+
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf[2];
+
+ if (bit (thumb_insn_r->arm_insn, 12))
+ {
+ /* handle load/store register offset. */
+ opcode1 = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 10);
+ if ((opcode2 >= 12) && (opcode2 <= 15))
+ {
+ /* LDR(2), LDRB(2) , LDRH(2), LDRSB, LDRSH. */
+ reg_src1 = bits (thumb_insn_r->arm_insn,0, 2);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ }
+ else if ((opcode2 >= 8) && (opcode2 <= 10))
+ {
+ /* STR(2), STRB(2), STRH(2) . */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ reg_src2 = bits (thumb_insn_r->arm_insn, 6, 8);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf[0].buf[0]);
+ GET_REG_VAL (reg_cache, reg_src2, &u_buf[1].buf[0]);
+ thumb_insn_r->arm_mems = (struct arm_mem_r *) \
+ xmalloc (sizeof(struct arm_mem_r) * 2);
+ thumb_insn_r->arm_mems[0].len = 1;
+ thumb_insn_r->arm_mems[0].addr = u_buf[0].s_word+u_buf[1].s_word;
+ if (8 == opcode2)
+ thumb_insn_r->arm_mems[0].len = 4; /* STR (2). */
+ else if (10 == opcode2)
+ thumb_insn_r->arm_mems[0].len = 1; /* STRB (2). */
+ else if (9 == opcode2)
+ thumb_insn_r->arm_mems[0].len = 2; /* STRH (2). */
+ }
+ goto end;
+ }
+ else if (bit (thumb_insn_r->arm_insn, 11))
+ {
+ /* handle load from literal pool. */
+ /* LDR(3). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ goto end;
+ }
+
+ thumb_insn_r->opcode = bits (thumb_insn_r->arm_insn, 13, 15);
+ opcode1 = bits (thumb_insn_r->arm_insn, 10, 12);
+ if (opcode1)
+ {
+ opcode2 = bits (thumb_insn_r->arm_insn, 8, 9);
+ opcode3 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if ((3 == opcode2) && (!opcode3))
+ {
+ /* branch with exchange. */
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ }
+ else
+ {
+ /* format 8; special data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = reg_src1;
+ }
+ }
+ else
+ {
+ /* format 5; data processing insns. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ if (bit (thumb_insn_r->arm_insn, 7))
+ {
+ reg_src1 = reg_src1 + 8;
+ }
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = reg_src1;
+ }
+
+ end:
+ return 0;
+}
+
+static int
+thumb_handle_ld_st_imm_offset_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (opcode)
+ {
+ /* LDR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ }
+ else
+ {
+ /* STR(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+ thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ thumb_insn_r->arm_mems[0].len = 1;
+ thumb_insn_r->arm_mems[1].len = 4;
+ thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 4);
+ }
+
+ return 0;
+}
+
+static int
+thumb_hamdle_ld_st_stack_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, immed_8 = 0, immed_5 = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (3 == opcode)
+ {
+ /* LDR(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ }
+ else if (1 == opcode)
+ {
+ /* LDRH(1). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ }
+ else if (2 == opcode)
+ {
+ /* STR(3). */
+ immed_8 = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_SP_REGNUM, &u_buf.buf[0]);
+ thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ thumb_insn_r->arm_mems[0].len = 1;
+ thumb_insn_r->arm_mems[1].len = 4;
+ thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_8 * 4);
+ }
+ else if (0 == opcode)
+ {
+ /* STRH(1). */
+ immed_5 = bits (thumb_insn_r->arm_insn, 6, 10);
+ reg_src1 = bits (thumb_insn_r->arm_insn, 3, 5);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+ thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*2);
+ thumb_insn_r->arm_mems[0].len = 1;
+ thumb_insn_r->arm_mems[1].len = 2;
+ thumb_insn_r->arm_mems[1].addr = u_buf.s_word + (immed_5 * 2);
+ }
+ return 0;
+}
+
+static int
+thumb_handle_misc_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode = 0, opcode1 = 0, opcode2 = 0, immed_8 = 0, immed_5 = 0;
+ uint32_t register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ opcode = bits (thumb_insn_r->arm_insn, 11, 12);
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 9, 12);
+
+ if (14 == opcode2)
+ {
+ /* POP. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+ (sizeof(uint32_t) * (register_count +
3));
+ thumb_insn_r->arm_regs[0] = register_count + 2;
+ thumb_insn_r->arm_regs[register_count + 1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[register_count + 2] = ARM_SP_REGNUM;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ thumb_insn_r->arm_regs[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (10 == opcode2)
+ {
+ /* PUSH. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ GET_REG_VAL (reg_cache, ARM_PC_REGNUM, &u_buf.buf[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.s_word - \
+ (4 * (bit (thumb_insn_r->arm_insn, 8) + register_count)) ;
+ thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count + 1));
+ thumb_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ thumb_insn_r->arm_mems[register_count].addr = start_address;
+ thumb_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t) * 2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+ }
+ else if (0x1E == opcode1)
+ {
+ /* BKPT insn. */
+ /* handle enhanced software breakpoint insn, BKPT. */
+ /* CPSR is changed to be executed in ARM state, disabling normal
+ interrupts, entering abort mode. */
+ /* accorindly to high vector configuration PC is set accordingly. */
+ /* Oza: FIX ME ? what if user hit breakpoint and type reverse, in
+ that case, we need to go back with previous CPSR and
+ Program Counter.. */
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+ /* save SPSR also; how?. */
+ }
+ else if ((0 == opcode) || (1 == opcode))
+ {
+ /* ADD(5), ADD(6). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = reg_src1;
+ }
+ else if (2 == opcode)
+ {
+ /* ADD(7), SUB(4). */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*2);
+ thumb_insn_r->arm_regs[0] = 1;
+ thumb_insn_r->arm_regs[1] = ARM_SP_REGNUM;
+ }
+
+
+ return 0;
+}
+
+static int
+thumb_handle_swi_insn (void *data)
+{
+
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+ uint32_t reg_val1 = 0;
+ uint32_t reg_src1 = 0;
+ uint32_t opcode1 = 0, opcode2 = 0, register_bits = 0, register_count = 0;
+ uint32_t register_list[8] = {0}, index = 0, start_address = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ opcode1 = bits (thumb_insn_r->arm_insn, 8, 12);
+ opcode2 = bits (thumb_insn_r->arm_insn, 11, 12);
+
+ if (1 == opcode2)
+ {
+
+ /* LDMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_list[register_count++] = 1;
+ register_bits = register_bits >> 1;
+ }
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc \
+ (sizeof(uint32_t) * (register_count +
2));
+ thumb_insn_r->arm_regs[0] = register_count + 1;
+ thumb_insn_r->arm_regs[register_count + 1] = reg_src1;
+ for (register_count = 0; register_count < 8; register_count++)
+ {
+ if (register_list[register_count])
+ {
+ thumb_insn_r->arm_regs[index] = register_count;
+ index++;
+ }
+ }
+ }
+ else if (0 == opcode2)
+ {
+ /* it handles both STMIA. */
+ register_bits = bits (thumb_insn_r->arm_insn, 0, 7);
+ /* get Rn. */
+ reg_src1 = bits (thumb_insn_r->arm_insn, 8, 10);
+ GET_REG_VAL (reg_cache, reg_src1, &u_buf.buf[0]);
+ while (register_bits)
+ {
+ if (register_bits & 0x00000001)
+ register_count++;
+ register_bits = register_bits >> 1;
+ }
+ start_address = u_buf.s_word;
+ thumb_insn_r->arm_mems = (struct arm_mem_r *)xmalloc (sizeof(struct
+ arm_mem_r)*(register_count+1));
+ thumb_insn_r->arm_mems[0].len = register_count;
+ while (register_count)
+ {
+ thumb_insn_r->arm_mems[register_count].addr = start_address;
+ thumb_insn_r->arm_mems[register_count].len = 4;
+ start_address = start_address + 4;
+ register_count--;
+ }
+ }
+ else if (0x1F == opcode1)
+ {
+ /* handle arm syscall insn. */
+ if (tdep->arm_swi_record != NULL)
+ {
+ printf("handling syscall swi insn\n");
+ tdep->arm_swi_record(reg_cache);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ /* B(1), conditional branch is automatically taken care in process_record,
+ as PC is saved there. */
+
+ return 0;
+}
+
+static int
+thumb_handle_branch_insn (void *data)
+{
+ insn_decode_record *thumb_insn_r = (insn_decode_record*) data;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (thumb_insn_r->gdbarch);
+ struct regcache *reg_cache = (struct regcache*) thumb_insn_r->regcache;
+
+ uint32_t reg_val1=0;
+ uint32_t reg_src1=0;
+ uint32_t opcode = 0, immed_5 = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+
+ /* BL , BLX(1). */
+ thumb_insn_r->arm_regs = (uint32_t*)xmalloc (sizeof(uint32_t)*3);
+ thumb_insn_r->arm_regs[0] = 2;
+ thumb_insn_r->arm_regs[1] = ARM_PS_REGNUM;
+ thumb_insn_r->arm_regs[2] = ARM_LR_REGNUM;
+
+ /* B(2) is automatically taken care in process_record, as PC is saved
+ there. */
+ return 0;
+}
+
+
+
+static int
+decode_insn (insn_decode_record *arm_record, uint32_t insn_size)
+{
+
+ /* (starting from numerical 0); bits 25, 26, 27 decodes type of arm
instruction. */
+ int (*const arm_handle_insn[NO_OF_TYPE_OF_ARM_INSNS]) (void*) =
+ {
+ arm_handle_data_proc_misc_load_str_insn, /* 000. */
+ arm_handle_data_proc_imm_insn, /* 001. */
+ arm_handle_ld_st_imm_offset_insn, /* 010. */
+ arm_handle_ld_st_reg_offset_insn, /* 011. */
+ arm_hamdle_ld_st_multiple_insn, /* 100. */
+ arm_handle_brn_insn, /* 101. */
+ arm_handle_coproc_insn, /* 110. */
+ arm_handle_coproc_data_proc_insn /* 111. */
+ };
+
+ /* (starting from numerical 0); bits 13,14,15 decodes type of thumb
instruction. */
+ int (*const thumb_handle_insn[NO_OF_TYPE_OF_THUMB_INSNS]) (void*) =
+ {
+ thumb_handle_shift_add_sub_insn, /* 000. */
+ thumb_handle_add_sub_cmp_mov_insn, /* 001. */
+ thumb_handle_ld_st_reg_offset_insn, /* 010. */
+ thumb_handle_ld_st_imm_offset_insn, /* 011. */
+ thumb_hamdle_ld_st_stack_insn, /* 100. */
+ thumb_handle_misc_insn, /* 101. */
+ thumb_handle_swi_insn, /* 110. */
+ thumb_handle_branch_insn /* 111. */
+ };
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[insn_size];
+ } u_buf;
+
+ uint32_t ret=0;
+
+ memset (&u_buf, 0, sizeof(u_buf));
+ if (target_read_memory (arm_record->this_addr, &u_buf.buf[0], insn_size))
+ {
+ if (record_debug)
+ {
+ printf_unfiltered (_("Process record: error reading memory at "
+ "addr %s len = %d.\n"),
+ paddress (arm_record->gdbarch, arm_record->this_addr), insn_size);
+ return -1;
+ }
+ }
+ else if (ARM_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = u_buf.s_word;
+ arm_record->cond = bits (arm_record->arm_insn, 28, 31);
+ arm_record->id = bits (arm_record->arm_insn, 25, 27);
+ ret = (0x0F != arm_record->cond)? \
+ arm_handle_insn[arm_record->id] ((void*)arm_record) : \
+ handle_extension_space(arm_record);
+ }
+ else if (THUMB_INSN_SIZE_BYTES == insn_size)
+ {
+ arm_record->arm_insn = u_buf.s_word;
+ arm_record->id = bits (arm_record->arm_insn, 13, 15);
+ ret = thumb_handle_insn[arm_record->id] ((void*)arm_record);
+ }
+ return ret;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something is wrong.. */
+
+int
+arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ uint32_t no_of_rec=0;
+ uint32_t ret=0;
+ ULONGEST t_bit = 0;
+
+ union
+ {
+ uint32_t s_word;
+ gdb_byte buf[4];
+ } u_buf;
+
+ insn_decode_record arm_record;
+ memset (&u_buf, 0, sizeof(u_buf));
+
+ memset (&arm_record, 0, sizeof (insn_decode_record));
+ arm_record.regcache = regcache;
+ arm_record.this_addr = insn_addr;
+ arm_record.gdbarch = gdbarch;
+
+
+ if (record_debug > 1)
+ {
+ fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
+ "addr = %s\n",
+ paddress (gdbarch, arm_record.this_addr));
+ }
+
+ /* check the insn, whether it is thumb or arm one. */
+
+ t_bit = arm_psr_thumb_bit (arm_record.gdbarch);
+ GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
+
+ if (!(u_buf.s_word & t_bit))
+ {
+ /* we are decoding arm insn. */
+ ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
+ }
+ else
+ {
+ /* we are decoding thumb insn. */
+ ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
+ }
+
+ /* record registers. */
+ ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
+ if (arm_record.arm_regs)
+ {
+ for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
+ {
+ if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
+ ret = -1;
+ }
+ }
+ /* record memories. */
+ if (arm_record.arm_mems)
+ {
+ for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
+ {
+ if (record_arch_list_add_mem \
+ ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
+ arm_record.arm_mems[no_of_rec].len))
+ ret = -1;
+ }
+ }
+
+ if (record_arch_list_add_end ())
+ ret = -1;
+
+ if (arm_record.arm_regs)
+ xfree (arm_record.arm_regs);
+ if (arm_record.arm_mems)
+ xfree (arm_record.arm_mems);
+
+ return ret;
+}
diff -urN arm_orig/arm-tdep.h arm_new/arm-tdep.h
--- arm_orig/arm-tdep.h 2011-03-03 09:21:13.000000000 +0530
+++ arm_new/arm-tdep.h 2011-04-15 13:11:15.000000000 +0530
@@ -200,6 +200,9 @@
/* Return the expected next PC if FRAME is stopped at a syscall
instruction. */
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
+
+ /* Parse swi args. */
+ int (*arm_swi_record) (struct regcache *regcache);
};
/* Structures used for displaced stepping. */
@@ -310,6 +313,10 @@
struct displaced_step_closure *,
CORE_ADDR, CORE_ADDR, struct regcache *);
+extern int arm_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
+
/* Functions exported from armbsd-tdep.h. */
/* Return the appropriate register set for the core section identified
----- Original Message ----
From: Yao Qi <yao@codesourcery.com>
To: gdb@sourceware.org
Sent: Mon, April 11, 2011 8:35:42 AM
Subject: Re: [PATCH] arm reversible : progress <phase_2_complete>
On 04/10/2011 05:41 PM, paawan oza wrote:
> Hi,
>
> phase2 (both arm and thumb insn implemenation is complete)
>
> Hi Tom:
> I have taken care of most of your comments: but could nit incorporate numercial
>
> to be replaced by some meaningful symbolic names.
> as I dont know what sort of symbolic names are approproate.
>
>
This one looks much better than previous ones. Thanks for working on
this. I am not the people to approve this patch. Some of my cents below.
> +
> +#define ARM_INSN_SIZE_BYTES 4
> +#define THUMB_INSN_SIZE_BYTES 2
> +#define NO_OF_TYPE_OF_ARM_INSNS 8
> +#define NO_OF_TYPE_OF_THUMB_INSNS 8
> +
> +#define ARM_RECORD_ARCH_LIST_ADD_REG(regnum) \
> + record_arch_list_add_reg (arm_record.regcache, regnum)
> +
> +#define GET_REG_VAL(REGCACHE,NO,BUF) regcache_raw_read (REGCACHE, NO, BUF);
> +
> +#define IS_IT_ARM_INSN(X) ((X & 0x00000020) >> 5)
> +#define ARM_PARSE_INSN(X,BIT_POS,NO_OF_BITS) \
> + ((X >> (BIT_POS-1)) & (0xFFFFFFFF >> ((sizeof(uint32_t)*8) -
\
> + NO_OF_BITS)))
There are some existing macros you can use for parsing instructions.
/* Support routines for instruction parsing. */
#define submask(x) ((1L << ((x) + 1)) - 1)
#define bit(obj,st) (((obj) >> (st)) & 1)
#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
#define sbits(obj,st,fn) \
((long) (bits(obj,st,fn) | ((long) bit(obj,fn) * ~ submask (fn - st))))
> +
> +#define INSN_S_L_BIT_NUM 21
> +#define ARM_BIT_SET(X, NUM) (((X >> (NUM-1)) & 0x00000001) == 1)
> +#define GET_BIT(X, NUM) (((X >> (NUM-1)) & 0x00000001))
> +
GET_BIT can be replaced by `bit' I posted above.
> +
> +static int
> +handle_extension_space (insn_decode_record *arm_record)
> +{
> + insn_decode_record *arm_insn_r = arm_record;
> + struct gdbarch_tdep *tdep = gdbarch_tdep (arm_insn_r->gdbarch);
> + struct regcache *reg_cache = arm_insn_r->regcache;
> +
> + uint32_t reg_src1 = 0, reg_src2 = 0;
> + uint32_t opcode1 = 0, opcode2 = 0;
> +
> + opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,26,3);
> + if ((3 == opcode1) && ARM_BIT_SET(arm_insn_r->arm_insn,5))
> + {
> + /* undefined instruction on ARM V5; need to handle if later versions
> + define it. */
> + }
> +
> + opcode2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,5,4);
> +
> + if ((!opcode1) && (9 == opcode2))
> + {
> + /* handle arithmetic insn extension space. */
> + }
> +
> + opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,27,2);
^ ^
You need an extra space after each comma.
> + opcode2 = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,2);
> +
> + if ((!opcode1) && (2 == opcode2) && !ARM_BIT_SET(arm_insn_r->arm_insn,21))
> + {
> + /* handle control insn extension space. */
> + }
> +
> + opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,26,3);
> + if ((!opcode1) && (ARM_BIT_SET(arm_insn_r->arm_insn,8)) \
> + && (ARM_BIT_SET(arm_insn_r->arm_insn,5)))
> + {
> + /* handle load/store insn extension space. */
> + }
> +
> + opcode1 = ARM_PARSE_INSN (arm_insn_r->arm_insn,24,5);
> + if ((24 == opcode1) && ARM_BIT_SET(arm_insn_r->arm_insn,22))
> + {
> + /* handle coprocessor insn extension space. */
> + }
> +
> + /* to be done for ARMv5 and later; as of now we return -1. */
> + return -1;
> +}
> +
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to "record_arch_list".
> + Return -1 if something is wrong.. */
> +
> +int
> +arm_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> +
> + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> + uint32_t no_of_rec=0;
> + uint32_t ret=0;
> +
> + union
> + {
> + uint32_t s_word;
> + gdb_byte buf[4];
> + } u_buf;
> +
> + insn_decode_record arm_record;
> + memset (&u_buf, 0, sizeof(u_buf));
> +
> + memset (&arm_record, 0, sizeof (insn_decode_record));
> + arm_record.regcache = regcache;
> + arm_record.this_addr = insn_addr;
> + arm_record.gdbarch = gdbarch;
> +
> +
> + if (record_debug > 1)
> + {
> + fprintf_unfiltered (gdb_stdlog, "Process record: arm_process_record "
> + "addr = %s\n",
> + paddress (gdbarch, arm_record.this_addr));
> + }
> +
> + /* check the insn, whether it is thumb or arm one. */
> + GET_REG_VAL (arm_record.regcache, ARM_PS_REGNUM, &u_buf.buf[0]);
> + arm_record.cond = ARM_PARSE_INSN (arm_record.arm_insn,29,4);
> +
> + if (!IS_IT_ARM_INSN (u_buf.s_word))
Please reference to `arm_frame_is_thumb' or `displaced_in_arm_mode' to
see how to check ARM mode or Thumb mode.
> + {
> + /* we are decoding arm insn. */
> + ret = decode_insn (&arm_record, ARM_INSN_SIZE_BYTES);
> + }
> + else
> + {
> + /* we are decoding thumb insn. */
> + ret = decode_insn (&arm_record, THUMB_INSN_SIZE_BYTES);
On some ARM arch, there are 32-bit Thumb instructions, called Thumb-2.
Do you plan to support Thumb-2 insn?
> + }
> +
> + /* record registers. */
> + ARM_RECORD_ARCH_LIST_ADD_REG(ARM_PC_REGNUM);
> + if (arm_record.arm_regs)
> + {
> + for (no_of_rec=1;no_of_rec<=arm_record.arm_regs[0];no_of_rec++)
> + {
> + if (ARM_RECORD_ARCH_LIST_ADD_REG (arm_record.arm_regs[no_of_rec]))
> + ret = -1;
> + }
> + }
> + /* record memories. */
> + if (arm_record.arm_mems)
> + {
> + for (no_of_rec=1;no_of_rec<=arm_record.arm_mems[0].len;no_of_rec++)
> + {
> + if (record_arch_list_add_mem \
> + ((CORE_ADDR)arm_record.arm_mems[no_of_rec].addr,
> + arm_record.arm_mems[no_of_rec].len))
> + ret = -1;
> + }
> + }
> +
> + if (record_arch_list_add_end ())
> + ret = -1;
> +
> + if (arm_record.arm_regs)
> + xfree (arm_record.arm_regs);
> + if (arm_record.arm_mems)
> + xfree (arm_record.arm_mems);
> +
> + return ret;
> +}
--
Yao (齐尧)
^ permalink raw reply [flat|nested] 128+ messages in thread
end of thread, other threads:[~2012-03-13 5:41 UTC | newest]
Thread overview: 128+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-05-29 15:38 [PATCH] arm reversible : <phase_2_complete> paawan oza
2011-05-31 18:05 ` Tom Tromey
2011-06-03 7:44 ` paawan oza
2011-06-03 7:51 ` paawan oza
2011-07-12 21:10 ` Tom Tromey
2011-07-13 3:17 ` chandra krishnappa
2011-07-13 5:36 ` paawan oza
2011-07-13 15:20 ` Tom Tromey
2011-07-14 4:49 ` chandra krishnappa
2011-07-14 15:01 ` Yao Qi
2011-07-13 6:57 ` paawan oza
[not found] ` <1316327455.23344.YahooMailNeo@web112509.mail.gq1.yahoo.com>
2011-09-19 7:37 ` paawan oza
2011-09-22 17:12 ` oza Pawandeep
2011-09-27 6:52 ` oza Pawandeep
2011-10-06 18:01 ` oza Pawandeep
[not found] ` <CAK1A=4xuUT++WRzdUnZc0KodYF0AiukUyJa7Pr=wzb4i-OQ5eQ@mail.gmail.com>
2011-10-08 2:50 ` Fwd: " paawan oza
2011-10-11 18:11 ` [PATCH] arm reversible : <phase_2_complete> how to go ahead ? paawan oza
2011-10-11 19:02 ` Tom Tromey
2011-10-14 20:13 ` [PATCH] arm reversible : <phase_2_complete> Tom Tromey
2011-10-15 3:46 ` paawan oza
2011-10-15 7:01 ` chandra krishnappa
2011-10-15 9:32 ` Yao Qi
2011-10-15 13:33 ` Yao Qi
2011-10-15 16:34 ` oza Pawandeep
2011-10-15 17:38 ` oza Pawandeep
2011-10-16 8:00 ` oza Pawandeep
2011-10-16 8:44 ` oza Pawandeep
2011-10-17 4:25 ` Yao Qi
2011-10-17 3:18 ` Yao Qi
2011-10-17 4:28 ` oza Pawandeep
2011-10-17 15:42 ` chandra krishnappa
2011-11-03 17:10 ` Tom Tromey
2011-11-04 16:27 ` Yao Qi
2011-10-16 23:32 ` Petr Hluzín
2011-10-22 15:42 ` oza Pawandeep
2011-10-23 10:17 ` oza Pawandeep
2011-10-24 7:43 ` Petr Hluzín
2011-10-25 7:20 ` Yao Qi
2011-11-03 17:41 ` Tom Tromey
2011-11-05 17:36 ` Petr Hluzín
2011-11-03 17:38 ` Tom Tromey
2011-11-05 17:35 ` Petr Hluzín
2011-11-07 15:39 ` Tom Tromey
2011-11-08 6:02 ` oza Pawandeep
2011-11-08 10:17 ` Yao Qi
2011-11-08 10:45 ` oza Pawandeep
2011-11-09 5:28 ` oza Pawandeep
2011-11-09 6:08 ` oza Pawandeep
2011-11-17 9:24 ` oza Pawandeep
2011-11-17 9:52 ` Yao Qi
2011-11-17 20:40 ` Tom Tromey
2011-11-18 3:18 ` oza Pawandeep
2011-11-18 17:22 ` Tom Tromey
2011-11-19 9:43 ` oza Pawandeep
2011-11-19 11:39 ` oza Pawandeep
2011-12-02 18:36 ` Tom Tromey
2011-12-03 8:20 ` oza Pawandeep
2011-12-03 14:18 ` oza Pawandeep
2011-12-03 16:32 ` Petr Hluzín
2011-12-03 18:46 ` oza Pawandeep
2011-12-03 19:02 ` oza Pawandeep
2011-12-03 20:30 ` Petr Hluzín
[not found] ` <1322975560.12415.YahooMailNeo@web112518.mail.gq1.yahoo.com>
2011-12-04 7:09 ` paawan oza
2011-12-04 1:47 ` Yao Qi
2011-12-04 8:26 ` oza Pawandeep
2011-12-04 11:33 ` oza Pawandeep
2011-12-04 13:29 ` Petr Hluzín
2011-12-04 14:46 ` Yao Qi
2011-12-04 17:00 ` oza Pawandeep
2011-12-04 23:46 ` Yao Qi
2011-12-05 5:35 ` oza Pawandeep
2011-12-05 8:12 ` Yao Qi
2011-12-05 16:02 ` oza Pawandeep
2011-12-19 6:26 ` oza Pawandeep
2011-12-20 19:11 ` Tom Tromey
2011-12-28 12:43 ` oza Pawandeep
2012-01-05 11:01 ` oza Pawandeep
2012-01-05 12:03 ` Eli Zaretskii
2012-01-05 16:17 ` Tom Tromey
2012-01-05 18:17 ` oza Pawandeep
2012-01-06 8:06 ` oza Pawandeep
2012-01-06 19:13 ` Tom Tromey
2012-01-07 6:31 ` oza Pawandeep
2012-01-09 16:25 ` Tom Tromey
2012-02-02 6:29 ` oza Pawandeep
[not found] ` <m38vkfoiut.fsf@fleche.redhat.com>
[not found] ` <CAK1A=4xrUBzcG1i7NHyEtmAjwx0nbYmkePFS9_kQcS3E1gaduA@mail.gmail.com>
[not found] ` <m3haz19ezl.fsf@fleche.redhat.com>
[not found] ` <CAK1A=4w+yq9AvRMukPcKpZnGjrVnPbE3zdScwRd1Skubt0KHWA@mail.gmail.com>
2012-03-07 5:35 ` oza Pawandeep
2012-03-08 16:32 ` Tom Tromey
2012-03-09 9:30 ` oza Pawandeep
2012-03-09 16:47 ` Tom Tromey
2012-03-12 6:23 ` oza Pawandeep
2012-03-12 6:55 ` Yao Qi
2012-03-12 9:14 ` oza Pawandeep
2012-03-12 15:32 ` oza Pawandeep
2012-03-12 19:43 ` Tom Tromey
2012-03-13 5:41 ` oza Pawandeep
2011-12-03 15:06 ` oza Pawandeep
2011-12-20 19:05 ` Tom Tromey
-- strict thread matches above, loose matches on Subject: below --
2011-08-10 17:09 chandra krishnappa
2011-08-11 1:34 ` Yao Qi
[not found] <BANLkTins056mmtd_9U_4iYXEeC2jRZSRsA@mail.gmail.com>
2011-06-06 17:42 ` chandra krishnappa
2011-07-05 8:47 ` oza Pawandeep
2011-05-24 7:19 paawan oza
[not found] <341905.10459.qm@web112513.mail.gq1.yahoo.com>
[not found] ` <m3d3m8xdf7.fsf@fleche.redhat.com>
[not found] ` <208397.95006.qm@web112517.mail.gq1.yahoo.com>
[not found] ` <4DA27006.1080607@codesourcery.com>
2011-04-16 21:03 ` [PATCH] arm reversible : progress <phase_2_complete> paawan oza
2011-04-20 19:16 ` [PATCH] arm reversible : <phase_2_complete> paawan oza
2011-04-21 20:55 ` Petr Hluzín
2011-04-22 5:49 ` paawan oza
2011-04-22 5:55 ` oza Pawandeep
2011-04-25 14:03 ` paawan oza
2011-05-01 1:20 ` Petr Hluzín
2011-05-02 14:47 ` Tom Tromey
2011-05-04 21:33 ` Petr Hluzín
2011-05-05 15:29 ` Tom Tromey
2011-05-07 13:50 ` paawan oza
2011-05-09 14:57 ` Tom Tromey
2011-05-10 5:42 ` paawan oza
2011-05-10 15:37 ` Tom Tromey
2011-05-12 5:06 ` paawan oza
2011-05-10 5:50 ` paawan oza
2011-05-12 21:21 ` Petr Hluzín
2011-05-24 6:44 ` paawan oza
2011-05-07 13:56 ` paawan oza
[not found] ` <172713.29831.qm__351.089161313389$1303740245$gmane$org@web112503.mail.gq1.yahoo.com>
2011-04-25 19:57 ` Tom Tromey
2011-04-28 18:26 ` paawan oza
2011-04-28 19:00 ` Tom Tromey
2011-04-28 19:22 ` paawan oza
[not found] ` <727567.12089.qm__13056.408687453$1304018591$gmane$org@web112511.mail.gq1.yahoo.com>
2011-04-28 19:36 ` Tom Tromey
2011-04-30 16:16 ` paawan oza
2011-05-02 13:28 ` Tom Tromey
2011-04-20 19:10 [PATCH] arm reversible <phase_2_complete> oza Pawandeep
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).