cleanup: rename armv4_5 to arm for readability
[fw/openocd] / src / target / arm_simulator.c
index 5af2c129bea5e7969e72028cd7ff79fce4adb1cf..a0ffdde5e80bc91984b81bb2dc116d163d913822 100644 (file)
 #include "config.h"
 #endif
 
+#include "arm.h"
 #include "armv4_5.h"
 #include "arm_disassembler.h"
 #include "arm_simulator.h"
-#include "log.h"
-#include "binarybuffer.h"
+#include <helper/binarybuffer.h>
+#include "register.h"
+#include <helper/log.h>
 
 
-uint32_t arm_shift(uint8_t shift, uint32_t Rm, uint32_t shift_amount, uint8_t *carry)
+static uint32_t arm_shift(uint8_t shift, uint32_t Rm,
+               uint32_t shift_amount, uint8_t *carry)
 {
        uint32_t return_value = 0;
        shift_amount &= 0xff;
@@ -74,8 +77,11 @@ uint32_t arm_shift(uint8_t shift, uint32_t Rm, uint32_t shift_amount, uint8_t *c
        {
                if ((shift_amount > 0) && (shift_amount <= 32))
                {
-                       /* right shifts of unsigned values are guaranteed to be logical (shift in zeroes)
-                        * simulate an arithmetic shift (shift in signed-bit) by adding the signed-bit manually */
+                       /* C right shifts of unsigned values are guaranteed to
+                        * be logical (shift in zeroes); simulate an arithmetic
+                        * shift (shift in signed-bit) by adding the sign bit
+                        * manually
+                        */
                        return_value = Rm >> shift_amount;
                        if (Rm & 0x80000000)
                                return_value |= 0xffffffff << (32 - shift_amount);
@@ -123,12 +129,14 @@ uint32_t arm_shift(uint8_t shift, uint32_t Rm, uint32_t shift_amount, uint8_t *c
 }
 
 
-uint32_t arm_shifter_operand(struct arm_sim_interface *sim, int variant, union arm_shifter_operand shifter_operand, uint8_t *shifter_carry_out)
+static uint32_t arm_shifter_operand(struct arm_sim_interface *sim,
+               int variant, union arm_shifter_operand shifter_operand,
+               uint8_t *shifter_carry_out)
 {
        uint32_t return_value;
        int instruction_size;
 
-       if (sim->get_state(sim) == ARMV4_5_STATE_ARM)
+       if (sim->get_state(sim) == ARM_STATE_ARM)
                instruction_size = 4;
        else
                instruction_size = 2;
@@ -147,7 +155,9 @@ uint32_t arm_shifter_operand(struct arm_sim_interface *sim, int variant, union a
                if (shifter_operand.immediate_shift.Rm == 15)
                        Rm += 2 * instruction_size;
 
-               return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, shifter_operand.immediate_shift.shift_imm, shifter_carry_out);
+               return_value = arm_shift(shifter_operand.immediate_shift.shift,
+                               Rm, shifter_operand.immediate_shift.shift_imm,
+                               shifter_carry_out);
        }
        else if (variant == 2) /* register shift */
        {
@@ -158,7 +168,8 @@ uint32_t arm_shifter_operand(struct arm_sim_interface *sim, int variant, union a
                if (shifter_operand.register_shift.Rm == 15)
                        Rm += 2 * instruction_size;
 
-               return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, Rs, shifter_carry_out);
+               return_value = arm_shift(shifter_operand.immediate_shift.shift,
+                               Rm, Rs, shifter_carry_out);
        }
        else
        {
@@ -169,7 +180,7 @@ uint32_t arm_shifter_operand(struct arm_sim_interface *sim, int variant, union a
        return return_value;
 }
 
-int pass_condition(uint32_t cpsr, uint32_t opcode)
+static int pass_condition(uint32_t cpsr, uint32_t opcode)
 {
        switch ((opcode & 0xf0000000) >> 28)
        {
@@ -259,7 +270,7 @@ int pass_condition(uint32_t cpsr, uint32_t opcode)
        return 0;
 }
 
-int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode)
+static int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode)
 {
        return pass_condition(cpsr, (opcode & 0x0f00) << 20);
 }
@@ -268,14 +279,15 @@ int thumb_pass_branch_condition(uint32_t cpsr, uint16_t opcode)
  * if the dry_run_pc argument is provided, no state is changed,
  * but the new pc is stored in the variable pointed at by the argument
  */
-int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_sim_interface *sim)
+static int arm_simulate_step_core(struct target *target,
+               uint32_t *dry_run_pc, struct arm_sim_interface *sim)
 {
        uint32_t current_pc = sim->get_reg(sim, 15);
-       arm_instruction_t instruction;
+       struct arm_instruction instruction;
        int instruction_size;
        int retval = ERROR_OK;
 
-       if (sim->get_state(sim) == ARMV4_5_STATE_ARM)
+       if (sim->get_state(sim) == ARM_STATE_ARM)
        {
                uint32_t opcode;
 
@@ -313,13 +325,14 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                if (retval != ERROR_OK)
                        return retval;
                retval = thumb_evaluate_opcode(opcode, current_pc, &instruction);
-                if (retval != ERROR_OK)
+               if (retval != ERROR_OK)
                        return retval;
                instruction_size = 2;
 
-               /* check condition code (only for branch instructions) */
-               if (instruction.type == ARM_B &&
-                   !thumb_pass_branch_condition(sim->get_cpsr(sim, 0, 32), opcode))
+               /* check condition code (only for branch (1) instructions) */
+               if ((opcode & 0xf000) == 0xd000
+                               && !thumb_pass_branch_condition(
+                                       sim->get_cpsr(sim, 0, 32), opcode))
                {
                        if (dry_run_pc)
                        {
@@ -351,64 +364,66 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
        /* branch instructions */
        if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX))
        {
-               uint32_t target;
+               uint32_t target_address;
 
                if (instruction.info.b_bl_bx_blx.reg_operand == -1)
                {
-                       target = instruction.info.b_bl_bx_blx.target_address;
+                       target_address = instruction.info.b_bl_bx_blx.target_address;
                }
                else
                {
-                       target = sim->get_reg_mode(sim, instruction.info.b_bl_bx_blx.reg_operand);
+                       target_address = sim->get_reg_mode(sim, instruction.info.b_bl_bx_blx.reg_operand);
                        if (instruction.info.b_bl_bx_blx.reg_operand == 15)
                        {
-                               target += 2 * instruction_size;
+                               target_address += 2 * instruction_size;
                        }
                }
 
                if (dry_run_pc)
                {
-                       *dry_run_pc = target & ~1;
+                       *dry_run_pc = target_address & ~1;
                        return ERROR_OK;
                }
                else
                {
                        if (instruction.type == ARM_B)
                        {
-                               sim->set_reg(sim, 15, target);
+                               sim->set_reg(sim, 15, target_address);
                        }
                        else if (instruction.type == ARM_BL)
                        {
                                uint32_t old_pc = sim->get_reg(sim, 15);
-                               sim->set_reg_mode(sim, 14, old_pc + 4);
-                               sim->set_reg(sim, 15, target);
+                               int T = (sim->get_state(sim) == ARM_STATE_THUMB);
+                               sim->set_reg_mode(sim, 14, old_pc + 4 + T);
+                               sim->set_reg(sim, 15, target_address);
                        }
                        else if (instruction.type == ARM_BX)
                        {
-                               if (target & 0x1)
+                               if (target_address & 0x1)
                                {
-                                       sim->set_state(sim, ARMV4_5_STATE_THUMB);
+                                       sim->set_state(sim, ARM_STATE_THUMB);
                                }
                                else
                                {
-                                       sim->set_state(sim, ARMV4_5_STATE_ARM);
+                                       sim->set_state(sim, ARM_STATE_ARM);
                                }
-                               sim->set_reg(sim, 15, target & 0xfffffffe);
+                               sim->set_reg(sim, 15, target_address & 0xfffffffe);
                        }
                        else if (instruction.type == ARM_BLX)
                        {
                                uint32_t old_pc = sim->get_reg(sim, 15);
-                               sim->set_reg_mode(sim, 14, old_pc + 4);
+                               int T = (sim->get_state(sim) == ARM_STATE_THUMB);
+                               sim->set_reg_mode(sim, 14, old_pc + 4 + T);
 
-                               if (target & 0x1)
+                               if (target_address & 0x1)
                                {
-                                       sim->set_state(sim, ARMV4_5_STATE_THUMB);
+                                       sim->set_state(sim, ARM_STATE_THUMB);
                                }
                                else
                                {
-                                       sim->set_state(sim, ARMV4_5_STATE_ARM);
+                                       sim->set_state(sim, ARM_STATE_ARM);
                                }
-                               sim->set_reg(sim, 15, target & 0xfffffffe);
+                               sim->set_reg(sim, 15, target_address & 0xfffffffe);
                        }
 
                        return ERROR_OK;
@@ -429,7 +444,10 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                else
                        Rn = 0;
 
-               shifter_operand = arm_shifter_operand(sim, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out);
+               shifter_operand = arm_shifter_operand(sim,
+                               instruction.info.data_proc.variant,
+                               instruction.info.data_proc.shifter_operand,
+                               &carry_out);
 
                /* adjust Rn in case the PC is being read */
                if (instruction.info.data_proc.Rn == 15)
@@ -465,24 +483,24 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                if (dry_run_pc)
                {
                        if (instruction.info.data_proc.Rd == 15)
-                       {
-                               *dry_run_pc = Rd;
-                               return ERROR_OK;
-                       }
+                               *dry_run_pc = Rd & ~1;
                        else
-                       {
                                *dry_run_pc = current_pc + instruction_size;
-                       }
 
                        return ERROR_OK;
                }
                else
                {
+                       if (instruction.info.data_proc.Rd == 15) {
+                               sim->set_reg_mode(sim, 15, Rd & ~1);
+                               if (Rd & 1)
+                                       sim->set_state(sim, ARM_STATE_THUMB);
+                               else
+                                       sim->set_state(sim, ARM_STATE_ARM);
+                               return ERROR_OK;
+                       }
                        sim->set_reg_mode(sim, instruction.info.data_proc.Rd, Rd);
                        LOG_WARNING("no updating of flags yet");
-
-                       if (instruction.info.data_proc.Rd == 15)
-                               return ERROR_OK;
                }
        }
        /* compare instructions (CMP, CMN, TST, TEQ) */
@@ -501,7 +519,7 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
        /* load register instructions */
        else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
        {
-               uint32_t load_address = 0, modified_address = 0, load_value;
+               uint32_t load_address = 0, modified_address = 0, load_value = 0;
                uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store.Rn);
 
                /* adjust Rn in case the PC is being read */
@@ -518,7 +536,8 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                else if (instruction.info.load_store.offset_mode == 1)
                {
                        uint32_t offset;
-                       uint32_t Rm = sim->get_reg_mode(sim, instruction.info.load_store.offset.reg.Rm);
+                       uint32_t Rm = sim->get_reg_mode(sim,
+                                       instruction.info.load_store.offset.reg.Rm);
                        uint8_t shift = instruction.info.load_store.offset.reg.shift;
                        uint8_t shift_imm = instruction.info.load_store.offset.reg.shift_imm;
                        uint8_t carry = sim->get_cpsr(sim, 29, 1);
@@ -538,43 +557,42 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                if (instruction.info.load_store.index_mode == 0)
                {
                        /* offset mode
-                        * we load from the modified address, but don't change the base address register */
+                        * we load from the modified address, but don't change
+                        * the base address register
+                        */
                        load_address = modified_address;
                        modified_address = Rn;
                }
                else if (instruction.info.load_store.index_mode == 1)
                {
                        /* pre-indexed mode
-                        * we load from the modified address, and write it back to the base address register */
+                        * we load from the modified address, and write it
+                        * back to the base address register
+                        */
                        load_address = modified_address;
                }
                else if (instruction.info.load_store.index_mode == 2)
                {
                        /* post-indexed mode
-                        * we load from the unmodified address, and write the modified address back */
-                        load_address = Rn;
+                        * we load from the unmodified address, and write the
+                        * modified address back
+                        */
+                       load_address = Rn;
                }
 
                if ((!dry_run_pc) || (instruction.info.load_store.Rd == 15))
                {
-                       if ((retval = target_read_u32(target, load_address, &load_value)) != ERROR_OK)
-                       {
+                       retval = target_read_u32(target, load_address, &load_value);
+                       if (retval != ERROR_OK)
                                return retval;
-                       }
                }
 
                if (dry_run_pc)
                {
                        if (instruction.info.load_store.Rd == 15)
-                       {
-                               *dry_run_pc = load_value;
-                               return ERROR_OK;
-                       }
+                               *dry_run_pc = load_value & ~1;
                        else
-                       {
                                *dry_run_pc = current_pc + instruction_size;
-                       }
-
                        return ERROR_OK;
                }
                else
@@ -584,10 +602,16 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                        {
                                sim->set_reg_mode(sim, instruction.info.load_store.Rn, modified_address);
                        }
-                       sim->set_reg_mode(sim, instruction.info.load_store.Rd, load_value);
 
-                       if (instruction.info.load_store.Rd == 15)
+                       if (instruction.info.load_store.Rd == 15) {
+                               sim->set_reg_mode(sim, 15, load_value & ~1);
+                               if (load_value & 1)
+                                       sim->set_state(sim, ARM_STATE_THUMB);
+                               else
+                                       sim->set_state(sim, ARM_STATE_ARM);
                                return ERROR_OK;
+                       }
+                       sim->set_reg_mode(sim, instruction.info.load_store.Rd, load_value);
                }
        }
        /* load multiple instruction */
@@ -636,28 +660,34 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                {
                        if (instruction.info.load_store_multiple.register_list & 0x8000)
                        {
-                               *dry_run_pc = load_values[15];
+                               *dry_run_pc = load_values[15] & ~1;
                                return ERROR_OK;
                        }
                }
                else
                {
-                       enum armv4_5_mode mode = sim->get_mode(sim);
                        int update_cpsr = 0;
 
                        if (instruction.info.load_store_multiple.S)
                        {
                                if (instruction.info.load_store_multiple.register_list & 0x8000)
                                        update_cpsr = 1;
-                               else
-                                       mode = ARMV4_5_MODE_USR;
                        }
 
                        for (i = 0; i < 16; i++)
                        {
                                if (instruction.info.load_store_multiple.register_list & (1 << i))
                                {
-                                       sim->set_reg_mode(sim, i, load_values[i]);
+                                       if (i == 15) {
+                                               uint32_t val = load_values[i];
+                                       sim->set_reg_mode(sim, i, val & ~1);
+                                       if (val & 1)
+                                               sim->set_state(sim, ARM_STATE_THUMB);
+                                       else
+                                               sim->set_state(sim, ARM_STATE_ARM);
+                                       } else {
+                                               sim->set_reg_mode(sim, i, load_values[i]);
+                                       }
                                }
                        }
 
@@ -686,9 +716,9 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                }
                else
                {
-                       uint32_t Rn = sim->get_reg_mode(sim, instruction.info.load_store_multiple.Rn);
+                       uint32_t Rn = sim->get_reg_mode(sim,
+                                       instruction.info.load_store_multiple.Rn);
                        int bits_set = 0;
-                       enum armv4_5_mode mode = sim->get_mode(sim);
 
                        for (i = 0; i < 16; i++)
                        {
@@ -696,11 +726,6 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
                                        bits_set++;
                        }
 
-                       if (instruction.info.load_store_multiple.S)
-                       {
-                               mode = ARMV4_5_MODE_USR;
-                       }
-
                        switch (instruction.info.load_store_multiple.addressing_mode)
                        {
                                case 0: /* Increment after */
@@ -728,7 +753,8 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
 
                        /* base register writeback */
                        if (instruction.info.load_store_multiple.W)
-                               sim->set_reg_mode(sim, instruction.info.load_store_multiple.Rn, Rn);
+                               sim->set_reg_mode(sim,
+                                       instruction.info.load_store_multiple.Rn, Rn);
 
                }
        }
@@ -755,80 +781,80 @@ int arm_simulate_step_core(target_t *target, uint32_t *dry_run_pc, struct arm_si
 
 static uint32_t armv4_5_get_reg(struct arm_sim_interface *sim, int reg)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       return buf_get_u32(armv4_5->core_cache->reg_list[reg].value, 0, 32);
+       return buf_get_u32(arm->core_cache->reg_list[reg].value, 0, 32);
 }
 
 static void armv4_5_set_reg(struct arm_sim_interface *sim, int reg, uint32_t value)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       buf_set_u32(armv4_5->core_cache->reg_list[reg].value, 0, 32, value);
+       buf_set_u32(arm->core_cache->reg_list[reg].value, 0, 32, value);
 }
 
 static uint32_t armv4_5_get_reg_mode(struct arm_sim_interface *sim, int reg)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       return buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, reg).value, 0, 32);
+       return buf_get_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
+                       arm->core_mode, reg).value, 0, 32);
 }
 
 static void armv4_5_set_reg_mode(struct arm_sim_interface *sim, int reg, uint32_t value)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, reg).value, 0, 32, value);
+       buf_set_u32(ARMV4_5_CORE_REG_MODE(arm->core_cache,
+                       arm->core_mode, reg).value, 0, 32, value);
 }
 
 static uint32_t armv4_5_get_cpsr(struct arm_sim_interface *sim, int pos, int bits)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       return buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, pos, bits);
+       return buf_get_u32(arm->cpsr->value, pos, bits);
 }
 
-static enum armv4_5_state armv4_5_get_state(struct arm_sim_interface *sim)
+static enum arm_state armv4_5_get_state(struct arm_sim_interface *sim)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       return armv4_5->core_state;
+       return arm->core_state;
 }
 
-static void armv4_5_set_state(struct arm_sim_interface *sim, enum armv4_5_state mode)
+static void armv4_5_set_state(struct arm_sim_interface *sim, enum arm_state mode)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       armv4_5->core_state = mode;
+       arm->core_state = mode;
 }
 
 
-static enum armv4_5_mode armv4_5_get_mode(struct arm_sim_interface *sim)
+static enum arm_mode armv4_5_get_mode(struct arm_sim_interface *sim)
 {
-       armv4_5_common_t *armv4_5 = (armv4_5_common_t *)sim->user_data;
+       struct arm *arm = (struct arm *)sim->user_data;
 
-       return armv4_5->core_mode;
+       return arm->core_mode;
 }
 
 
 
-int arm_simulate_step(target_t *target, uint32_t *dry_run_pc)
+int arm_simulate_step(struct target *target, uint32_t *dry_run_pc)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-
+       struct arm *arm = target_to_arm(target);
        struct arm_sim_interface sim;
 
-       sim.user_data=armv4_5;
-       sim.get_reg=&armv4_5_get_reg;
-       sim.set_reg=&armv4_5_set_reg;
-       sim.get_reg_mode=&armv4_5_get_reg_mode;
-       sim.set_reg_mode=&armv4_5_set_reg_mode;
-       sim.get_cpsr=&armv4_5_get_cpsr;
-       sim.get_mode=&armv4_5_get_mode;
-       sim.get_state=&armv4_5_get_state;
-       sim.set_state=&armv4_5_set_state;
+       sim.user_data = arm;
+       sim.get_reg = &armv4_5_get_reg;
+       sim.set_reg = &armv4_5_set_reg;
+       sim.get_reg_mode = &armv4_5_get_reg_mode;
+       sim.set_reg_mode = &armv4_5_set_reg_mode;
+       sim.get_cpsr = &armv4_5_get_cpsr;
+       sim.get_mode = &armv4_5_get_mode;
+       sim.get_state = &armv4_5_get_state;
+       sim.set_state = &armv4_5_set_state;
 
        return arm_simulate_step_core(target, dry_run_pc, &sim);
-
 }