Re: [PATCH] arm reversible : <phase_2_complete>

paawan oza
2011-05-24T07:19:55Z

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