Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 104 additions & 3 deletions libsim/src/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -405,6 +413,10 @@ Step_status Cpu::step(void)
{
this->execute_op16_cond_branch(ins16);
}
else if (TEST_INS16(OP16_UNCOND_BRANCH))
{
this->execute_op16_uncond_branch(ins16);
}
else if (TEST_INS16(OP16_LD_LITERAL_POOL))
{
this->execute_op16_ld_literal_pool(ins16);
Expand All @@ -413,6 +425,10 @@ Step_status Cpu::step(void)
{
this->execute_op16_ldrb_imm(ins16);
}
else if (TEST_INS16(OP16_LDR_REG))
{
this->execute_op16_ldr_reg(ins16);
}
else if (TEST_INS16(OP16_LDRB_REG))
{
this->execute_op16_ldrb_reg(ins16);
Expand All @@ -421,6 +437,10 @@ Step_status Cpu::step(void)
{
this->execute_op16_strb_imm(ins16);
}
else if (TEST_INS16(OP16_STR_REG))
{
this->execute_op16_str_reg(ins16);
}
else if (TEST_INS16(OP16_STRB_REG))
{
this->execute_op16_strb_reg(ins16);
Expand Down Expand Up @@ -1006,7 +1026,7 @@ void Cpu::execute_op16_special_data_branch(uint16_t ins16)
{
case 0 ... 3: /* ADD REG A6.7.4/T2 */
{
rd = GET_FIELD(ins16, 0, 2) | (GET_BIT(ins16, 7) << 3);
rd = GET_FIELD(ins16, 0, 3) | (GET_BIT(ins16, 7) << 3);
rm = GET_FIELD(ins16, 3, 4);
uint32_t current_rd = this->regs[rd].read();
uint32_t current_rm = this->regs[rm].read();
Expand All @@ -1023,7 +1043,7 @@ void Cpu::execute_op16_special_data_branch(uint16_t ins16)
break;
case 5 ... 7: /* CMP REG A6.7.28/T2 */
{
rd = GET_FIELD(ins16, 0, 2) | (GET_BIT(ins16, 7) << 3);
rd = GET_FIELD(ins16, 0, 3) | (GET_BIT(ins16, 7) << 3);
rm = GET_FIELD(ins16, 3, 4);
uint32_t current_rd = this->regs[rd].read();
uint32_t current_rm = this->regs[rm].read();
Expand All @@ -1039,7 +1059,7 @@ void Cpu::execute_op16_special_data_branch(uint16_t ins16)
break;
case 8 ... 11: /* MOV REG A6.7.76/T1 */
{
rd = GET_FIELD(ins16, 0, 2) | (GET_BIT(ins16, 7) << 3);
rd = GET_FIELD(ins16, 0, 3) | (GET_BIT(ins16, 7) << 3);
rm = GET_FIELD(ins16, 3, 4);
uint32_t current_rm = this->regs[rm].read();
this->reg_b.write(current_rm);
Expand Down Expand Up @@ -1143,6 +1163,17 @@ void Cpu::execute_op16_cond_branch(uint16_t ins16)
}


void Cpu::execute_op16_uncond_branch(uint16_t ins16)
{
/* unconditional branch A6.7.12/T2 */
CPU_LOG_TRACE("OP16_UNCOND_BRANCH\n");
int8_t imm11 = (int8_t)GET_FIELD(ins16, 0, 11) & 0x7ff;
int32_t offset = imm11*2;
unsigned int cond = 14; /*always*/
this->execute_conditional_branch(cond, offset, false);
}


void Cpu::execute_op16_ld_literal_pool(uint16_t ins16)
{
/* LDR (literal pool) A6.7.43/T1 */
Expand Down Expand Up @@ -1205,6 +1236,23 @@ void Cpu::execute_op16_ldrb_reg(uint16_t ins16)
this->regs[rt].write(data);
}

void Cpu::execute_op16_ldr_reg(uint16_t ins16)
{
/* LDRB (reg) A6.7.47/T1 */
CPU_LOG_TRACE("OP16_LDR_REG\n");
this->pc += 2;
unsigned int rt = GET_FIELD(ins16, 0, 3);
unsigned int rn = GET_FIELD(ins16, 3, 3);
unsigned int rm = GET_FIELD(ins16, 6, 3);
uint32_t current_rn = this->regs[rn].read();
this->reg_a.write(current_rn);
uint32_t current_rm = this->regs[rm].read();
this->reg_b.write(current_rm);
uint32_t addr = current_rn + current_rm;
uint32_t data = this->ram.read32(addr);
this->regs[rt].write(data);
}

void Cpu::execute_op16_strb_imm(uint16_t ins16)
{
/* LDRB (imm) A6.7.121/T1 */
Expand Down Expand Up @@ -1238,6 +1286,23 @@ void Cpu::execute_op16_strb_reg(uint16_t ins16)
this->ram.write8(addr, current_rt);
}

void Cpu::execute_op16_str_reg(uint16_t ins16)
{
/* LDRB (imm) A6.7.122/T1 */
CPU_LOG_TRACE("OP16_STR_REG\n");
this->pc += 2;
unsigned int rn = GET_FIELD(ins16, 3, 3);
uint32_t current_rn = this->regs[rn].read();
this->reg_a.write(current_rn);
unsigned int rm = GET_FIELD(ins16, 6, 3);
uint32_t current_rm = this->regs[rm].read();
uint32_t addr = current_rn + current_rm;
unsigned int rt = GET_FIELD(ins16, 0, 3);
uint32_t current_rt = this->regs[rt].read();
this->reg_a.write(current_rt);
this->ram.write32(addr, current_rt);
}

void Cpu::execute_op16_rev(uint16_t ins16)
{
/* REV A6.7.100/T1 */
Expand Down Expand Up @@ -1969,6 +2034,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 */
Expand Down Expand Up @@ -2041,6 +2123,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 */
Expand Down
5 changes: 5 additions & 0 deletions libsim/src/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,17 @@ class Cpu
void execute_op16_nop(void);
void execute_op16_breakpoint(uint16_t ins16);
void execute_op16_cond_branch(uint16_t ins16);
void execute_op16_uncond_branch(uint16_t ins16);
void execute_op16_ld_literal_pool(uint16_t ins16);
void execute_op32_ldmia(uint16_t ins16, uint16_t ins16_b);
void execute_op16_str_imm(uint16_t ins16);
void execute_op16_ld_imm(uint16_t ins16);
void execute_op16_ldrb_imm(uint16_t ins16);
void execute_op16_ldrb_reg(uint16_t ins16);
void execute_op16_ldr_reg(uint16_t ins16);
void execute_op16_strb_imm(uint16_t ins16);
void execute_op16_strb_reg(uint16_t ins16);
void execute_op16_str_reg(uint16_t ins16);
void execute_op16_rev(uint16_t ins16);
void execute_op16_rev16(uint16_t ins16);
void execute_op16_revsh(uint16_t ins16);
Expand All @@ -128,7 +131,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);
Expand Down
15 changes: 15 additions & 0 deletions libsim/src/opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@
#define OP16_LDRB_IMM_MASK 0xf800
#define OP16_LDRB_IMM_VAL 0x7800

#define OP16_LDR_REG_MASK 0xfe00
#define OP16_LDR_REG_VAL 0x5800

#define OP16_LDRB_REG_MASK 0xfe00
#define OP16_LDRB_REG_VAL 0x5c00

Expand All @@ -71,6 +74,9 @@
#define OP16_STRB_REG_MASK 0xfe00
#define OP16_STRB_REG_VAL 0x5400

#define OP16_STR_REG_MASK 0xfe00
#define OP16_STR_REG_VAL 0x5000

#define OP16_STR_IMM_MASK 0xf800
#define OP16_STR_IMM_VAL 0x6000

Expand All @@ -89,6 +95,9 @@
#define OP16_COND_BRANCH_MASK 0xf000
#define OP16_COND_BRANCH_VAL 0xd000

#define OP16_UNCOND_BRANCH_MASK 0xf800
#define OP16_UNCOND_BRANCH_VAL 0xe000

#define OP16_SHIFT_IMM_ADD_SUB_MOV_CMP_MASK 0xc000
#define OP16_SHIFT_IMM_ADD_SUB_MOV_CMP_VAL 0x0000

Expand Down Expand Up @@ -150,9 +159,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

Expand Down