From 436bbeff7fff48a2157c5d1a0740c10f6191d000 Mon Sep 17 00:00:00 2001 From: Ko- Date: Fri, 28 Jun 2019 16:53:11 +0200 Subject: [PATCH] Add support for LDR/STR T3 with imm12 immediate --- libsim/src/cpu.cpp | 44 ++++++++++++++++++++++++++++++++++++++++++++ libsim/src/cpu.h | 2 ++ libsim/src/opcodes.h | 6 ++++++ 3 files changed, 52 insertions(+) diff --git a/libsim/src/cpu.cpp b/libsim/src/cpu.cpp index c619f8a..f9a4a28 100644 --- a/libsim/src/cpu.cpp +++ b/libsim/src/cpu.cpp @@ -309,10 +309,18 @@ Step_status Cpu::step(void) { this->execute_op32_str_imm(ins16, ins16_b); } + else if (TEST_INS32(OP32_STR_IMM12)) + { + this->execute_op32_str_imm12(ins16, ins16_b); + } else if (TEST_INS32(OP32_LDR_IMM)) { this->execute_op32_ldr_imm(ins16, ins16_b); } + else if (TEST_INS32(OP32_LDR_IMM12)) + { + this->execute_op32_ldr_imm12(ins16, ins16_b); + } else if (TEST_INS32(OP32_LDRB_IMM)) { this->execute_op32_ldrb_imm(ins16, ins16_b); @@ -1969,6 +1977,23 @@ void Cpu::execute_op32_branch_misc(uint16_t ins16, uint16_t ins16_b) } +void Cpu::execute_op32_str_imm12(uint16_t ins16, uint16_t ins16_b) +{ + /* STR(immediate) A6.7.119/T3 */ + CPU_LOG_TRACE("OP32_STR_IMM12\n"); + this->pc += 4; + unsigned int rn = GET_FIELD(ins16, 0, 4); + unsigned int rt = GET_FIELD(ins16_b, 12, 4); + unsigned int imm12 = GET_FIELD(ins16_b, 0, 12); + uint32_t current_rn = this->regs[rn].read(); + this->reg_a.write(current_rn); + uint32_t d_addr = current_rn + imm12; + uint32_t current_rt = this->regs[rt].read(); + this->reg_b.write(current_rt); + this->ram.write32(d_addr, current_rt); +} + + void Cpu::execute_op32_str_imm(uint16_t ins16, uint16_t ins16_b) { /* STR(immediate) A6.7.119/T4 */ @@ -2041,6 +2066,25 @@ void Cpu::execute_op32_ldr_imm(uint16_t ins16, uint16_t ins16_b) this->regs[rt].write(data); } + +void Cpu::execute_op32_ldr_imm12(uint16_t ins16, uint16_t ins16_b) +{ + /* LDR(immediate) A6.7.42/T3 */ + CPU_LOG_TRACE("OP32_LDR_IMM12\n"); + this->pc += 4; + unsigned int rn = GET_FIELD(ins16, 0, 4); + unsigned int rt = GET_FIELD(ins16_b, 12, 4); + unsigned int imm12 = GET_FIELD(ins16_b, 0, 12); + uint32_t current_rn = this->regs[rn].read(); + this->reg_a.write(current_rn); + uint32_t d_addr = current_rn + imm12; + uint32_t data = this->ram.read32(d_addr); + uint32_t current_rt = this->regs[rt].read(); + this->reg_b.write(current_rt); + this->regs[rt].write(data); +} + + void Cpu::execute_op32_ldrb_imm(uint16_t ins16, uint16_t ins16_b) { /* LDRB (imm) A6.7.45/T2 */ diff --git a/libsim/src/cpu.h b/libsim/src/cpu.h index 98a0ab2..2efa4c5 100644 --- a/libsim/src/cpu.h +++ b/libsim/src/cpu.h @@ -128,7 +128,9 @@ class Cpu void execute_op32_data_reg(uint16_t ins16, uint16_t ins16_b); void execute_op32_branch_misc(uint16_t ins16, uint16_t ins16_b); void execute_op32_str_imm(uint16_t ins16, uint16_t ins16_b); + void execute_op32_str_imm12(uint16_t ins16, uint16_t ins16_b); void execute_op32_ldr_imm(uint16_t ins16, uint16_t ins16_b); + void execute_op32_ldr_imm12(uint16_t ins16, uint16_t ins16_b); void execute_op32_ldrb_imm(uint16_t ins16, uint16_t ins16_b); void execute_op32_ldrb_imm_alt(uint16_t ins16, uint16_t ins16_b); void execute_op32_ldrb_reg(uint16_t ins16, uint16_t ins16_b); diff --git a/libsim/src/opcodes.h b/libsim/src/opcodes.h index d3f0383..9e69e5d 100644 --- a/libsim/src/opcodes.h +++ b/libsim/src/opcodes.h @@ -150,9 +150,15 @@ #define OP32_STR_IMM_MASK 0xfff00800U #define OP32_STR_IMM_VAL 0xf8400800U +#define OP32_STR_IMM12_MASK 0xfff00000U +#define OP32_STR_IMM12_VAL 0xf8c00000U + #define OP32_LDR_IMM_MASK 0xfff00800U #define OP32_LDR_IMM_VAL 0xf8500800U +#define OP32_LDR_IMM12_MASK 0xfff00000U +#define OP32_LDR_IMM12_VAL 0xf8d00000U + #define OP32_LDRB_IMM_MASK 0xfff00000U #define OP32_LDRB_IMM_VAL 0xf8900000U