diff options
-rw-r--r-- | instruction.c | 57 | ||||
-rw-r--r-- | instruction.h | 11 |
2 files changed, 49 insertions, 19 deletions
diff --git a/instruction.c b/instruction.c index ecdaa45..4e288db 100644 --- a/instruction.c +++ b/instruction.c @@ -23,7 +23,7 @@ static inline uint32_t get_opcode(uint32_t code) static inline uint32_t get_opxcode(uint32_t code) { R_TYPE(instr, code); - return instr->opx.opx11; + return instr->opx6; } /* @@ -62,6 +62,7 @@ static int call(struct nios2 *cpu, uint32_t code) cpu->gp_regs[ra] = cpu->pc + 4; cpu->pc = (instr->imm26 * 4) | (cpu->pc & 0xF0000000); + dbg("pc after call: %08x\n", cpu->pc); return PC_INC_BY_INSTR; } @@ -112,6 +113,7 @@ static int br(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* */ static int ldhu(struct nios2 *cpu __unused, uint32_t code __unused) { /* TODO */ @@ -200,7 +202,7 @@ static int ori(struct nios2 *cpu, uint32_t code) } /* */ -static int stw(struct nios2 *cpu, uint32_t code) +static int stw(struct nios2 *cpu __unused, uint32_t code __unused) { /* TODO */ @@ -302,13 +304,43 @@ static int andhi(struct nios2 *cpu, uint32_t code) } /* */ -static int initd(struct nios2 *cpu, uint32_t code) +static int initd(struct nios2 *cpu __unused, uint32_t code __unused) { /* TODO */ return PC_INC_NORMAL; } +/* rB <- rA | (IMM16 : 0x0000) */ +static int orhi(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + gp_regs[instr->b] = gp_regs[instr->a] | (instr->imm16 << 16); + + return PC_INC_NORMAL; +} + +/* + * if ((unsigned) rA < (unsigned) rB) + * PC <- PC + 4 + @(IMM16) + * else + * PC <- PC + 4 + */ +static int bltu(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if (gp_regs[instr->a] < gp_regs[instr->b]) + cpu->pc += 4 + (int16_t)(instr->imm16 & 0xFFFC); + else + cpu->pc += 4; + + return PC_INC_BY_INSTR; +} + /* Prototype only, defined below */ static int handle_r_type_instr(struct nios2 *cpu, uint32_t code); @@ -362,9 +394,9 @@ static struct instruction i_type_instructions[I_TYPE_COUNT] = { [CMPLTUI] = INSTRUCTION_UNIMPLEMENTED(cmpltui), [CUSTOM] = INSTRUCTION_UNIMPLEMENTED(custom), [INITD] = INSTRUCTION(initd), - [ORHI] = INSTRUCTION_UNIMPLEMENTED(orhi), + [ORHI] = INSTRUCTION(orhi), [STWIO] = INSTRUCTION_UNIMPLEMENTED(stwio), - [BLTU] = INSTRUCTION_UNIMPLEMENTED(bltu), + [BLTU] = INSTRUCTION(bltu), [LDWIO] = INSTRUCTION_UNIMPLEMENTED(ldwio), [R_TYPE] = { "<R-type instruction>", handle_r_type_instr }, [FLUSHD] = INSTRUCTION_NOP(flushd), @@ -393,7 +425,7 @@ static int roli(struct nios2 *cpu, uint32_t code) R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; uint32_t a = gp_regs[instr->a]; - uint32_t shift_bits = instr->opx.imm5; + uint32_t shift_bits = instr->imm5; gp_regs[instr->c] = (a << shift_bits) | (a >> (32 - shift_bits)); @@ -454,7 +486,7 @@ static int ror(struct nios2 *cpu, uint32_t code) } /* */ -static int flushi(struct nios2 *cpu, uint32_t code) +static int flushi(struct nios2 *cpu __unused, uint32_t code __unused) { /* TODO */ @@ -507,7 +539,7 @@ static int slli(struct nios2 *cpu, uint32_t code) R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - gp_regs[instr->c] = gp_regs[instr->a] << instr->opx.imm5; + gp_regs[instr->c] = gp_regs[instr->a] << instr->imm5; return PC_INC_NORMAL; } @@ -559,7 +591,7 @@ static int srli(struct nios2 *cpu, uint32_t code) R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - gp_regs[instr->c] = gp_regs[instr->a] >> instr->opx.imm5; + gp_regs[instr->c] = gp_regs[instr->a] >> instr->imm5; return PC_INC_NORMAL; } @@ -640,7 +672,7 @@ static int div(struct nios2 *cpu, uint32_t code) if (b == 0) return EXCEPTION(NIOS2_EX_DIV_ERR); /* Divide overflow? */ - if (a == 0x80000000 && b == 0xFFFFFFFF) + if ((uint32_t) a == 0x80000000 && (uint32_t) b == 0xFFFFFFFF) return EXCEPTION(NIOS2_EX_DIV_ERR); gp_regs[instr->c] = (uint32_t)(a / b); @@ -657,7 +689,7 @@ static int rdctl(struct nios2 *cpu, uint32_t code) if (!nios2_in_supervisor_mode(cpu)) return EXCEPTION(NIOS2_EX_SUPERVISOR_ONLY_I); - cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->opx.imm5]; + cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->imm5]; return PC_INC_NORMAL; } @@ -700,7 +732,7 @@ static int wrctl(struct nios2 *cpu, uint32_t code) if (!nios2_in_supervisor_mode(cpu)) return EXCEPTION(NIOS2_EX_SUPERVISOR_ONLY_I); - cpu->ctrl_regs[instr->opx.imm5] = cpu->gp_regs[instr->a]; + cpu->ctrl_regs[instr->imm5] = cpu->gp_regs[instr->a]; return PC_INC_NORMAL; } @@ -797,6 +829,7 @@ instruction_handler instruction_get_handler(uint32_t code) if (unlikely(op >= I_TYPE_COUNT)) return NULL; + dbg("%s (%08x)\n", i_type_instructions[op].name, code); return i_type_instructions[op].handler; } diff --git a/instruction.h b/instruction.h index 5a268d3..8d9c366 100644 --- a/instruction.h +++ b/instruction.h @@ -34,13 +34,10 @@ struct r_type { * Some R-Type instructions embed a small immediate value in the * low-order bits of OPX. */ - union { - uint16_t opx11:11; - struct { - uint8_t imm5:5; - uint8_t opx6:6; - } __packed; - } opx; + struct { + uint8_t imm5:5; + uint8_t opx6:6; + } __packed; uint8_t c:5; uint8_t b:5; uint8_t a:5; |