diff options
-rw-r--r-- | instruction.c | 518 | ||||
-rw-r--r-- | instruction.h | 15 |
2 files changed, 329 insertions, 204 deletions
diff --git a/instruction.c b/instruction.c index 1846832..ecdaa45 100644 --- a/instruction.c +++ b/instruction.c @@ -41,7 +41,7 @@ static int unimplemented(struct nios2 *cpu, uint32_t code) * Used as a placeholder for all instructions which do not have an effect on the * simulator (e.g. flush, sync) */ -static int nop(struct nios2 *cpu, uint32_t code) +static int nop(struct nios2 *cpu __unused, uint32_t code __unused) { /* Nothing to do here */ return PC_INC_NORMAL; @@ -79,9 +79,14 @@ static int jmpi(struct nios2 *cpu, uint32_t code) * I-Type instructions */ +/* rB <- 0x000000 : Mem8[rA + @(IMM16)] */ static int ldbu(struct nios2 *cpu, uint32_t code) { I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + int32_t addr = gp_regs[instr->a] + (int16_t) instr->imm16; + + gp_regs[instr->b] = memory_get_byte(cpu->mem, addr); return PC_INC_NORMAL; } @@ -107,9 +112,9 @@ static int br(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } -static int ldhu(struct nios2 *cpu, uint32_t code) +static int ldhu(struct nios2 *cpu __unused, uint32_t code __unused) { - I_TYPE(instr, code); + /* TODO */ return PC_INC_NORMAL; } @@ -125,6 +130,65 @@ static int andi(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* */ +static int sth(struct nios2 *cpu __unused, uint32_t code __unused) +{ + /* TODO */ + return PC_INC_NORMAL; +} + +/* + * if ((signed) rA >= (signed) rB) + * PC <- PC + 4 + @(IMM16) + * else + * PC <- PC + 4 + */ +static int bge(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if ((int32_t) gp_regs[instr->a] >= (int32_t) gp_regs[instr->b]) + cpu->pc += 4 + (instr->imm16 & 0xFFFC); + else + cpu->pc += 4; + + return PC_INC_BY_INSTR; +} + +/* */ +static int ldh(struct nios2 *cpu __unused, uint32_t code __unused) +{ + /* TODO */ + return PC_INC_NORMAL; +} + +/* + * if ((signed) rA < (signed) @(IMM16) + * rB <- 1 + * else + * rB <- 0 + */ +static int cmplti(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if ((int32_t) gp_regs[instr->a] < (int32_t) ((int16_t) instr->imm16)) + gp_regs[instr->b] = 1; + else + gp_regs[instr->b] = 0; + + return PC_INC_NORMAL; +} + +/* Initializes the data cache line currently caching address rA + @(IMM16) */ +static int initda(struct nios2 *cpu __unused, uint32_t code __unused) +{ + /* TODO */ + return PC_INC_NORMAL; +} + /* rB <- rA | IMM16 */ static int ori(struct nios2 *cpu, uint32_t code) { @@ -135,6 +199,14 @@ static int ori(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* */ +static int stw(struct nios2 *cpu, uint32_t code) +{ + /* TODO */ + + return PC_INC_NORMAL; +} + /* * if ((signed) rA < (signed) rB) * PC <- PC + 4 + @(IMM16) @@ -146,7 +218,7 @@ static int blt(struct nios2 *cpu, uint32_t code) I_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - if (((int32_t) gp_regs[instr->a]) < ((int32_t) gp_regs[instr->b])) + if ((int32_t) gp_regs[instr->a] < (int32_t) gp_regs[instr->b]) cpu->pc += 4 + (int16_t)(instr->imm16 & 0xFFFC); else cpu->pc += 4; @@ -164,6 +236,25 @@ static int xori(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* + * if (rA != rB) + * PC <- PC + 4 + @(IMM16) + * else + * PC <- PC + 4 + */ +static int bne(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; +} + /* rB <- (rA * @(IMM16))(31..0) */ static int muli(struct nios2 *cpu, uint32_t code) { @@ -173,10 +264,10 @@ static int muli(struct nios2 *cpu, uint32_t code) /* Raise exception if instruction is not implemented */ if (!cpu->has_mul) - return INSTR_EXECPTION; + return EXCEPTION(NIOS2_EX_UNIMPLEMENTED); tmp = gp_regs[instr->a] * ((int16_t) instr->imm16); - gp_regs[instr->b] = (uint32_t) (tmp & BIT_MASK(32)); + gp_regs[instr->b] = (uint32_t) (tmp & BIT_MASK_FILL(32)); return PC_INC_NORMAL; } @@ -210,6 +301,14 @@ static int andhi(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* */ +static int initd(struct nios2 *cpu, uint32_t code) +{ + /* TODO */ + + return PC_INC_NORMAL; +} + /* Prototype only, defined below */ static int handle_r_type_instr(struct nios2 *cpu, uint32_t code); @@ -224,58 +323,70 @@ static int xorhi(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } -static instruction_handler i_type_instr_handlers[I_TYPE_COUNT] = { - [CALL] = call, - [JMPI] = jmpi, - [LDBU] = ldbu, - [ADDI] = addi, - [STB] = unimplemented, - [BR] = br, - [LDB] = unimplemented, - [CMPGEI] = unimplemented, - [LDHU] = ldhu, - [ANDI] = andi, - [STH] = unimplemented, - [BGE] = unimplemented, - [LDH] = unimplemented, - [CMPLTI] = unimplemented, - [INITDA] = unimplemented, - [ORI] = ori, - [STW] = unimplemented, - [BLT] = blt, - [LDW] = unimplemented, - [CMPNEI] = unimplemented, - [FLUSHDA] = nop, - [XORI] = xori, - [BNE] = unimplemented, - [CMPEQI] = unimplemented, - [LDBUIO] = unimplemented, - [MULI] = muli, - [STBIO] = unimplemented, - [BEQ] = beq, - [LDBIO] = unimplemented, - [CMPGEUI] = unimplemented, - [LDHUIO] = unimplemented, - [ANDHI] = andhi, - [STHIO] = unimplemented, - [BGEU] = unimplemented, - [LDHIO] = unimplemented, - [CMPLTUI] = unimplemented, - [CUSTOM] = unimplemented, - [INITD] = unimplemented, - [ORHI] = unimplemented, - [STWIO] = unimplemented, - [BLTU] = unimplemented, - [LDWIO] = unimplemented, - [R_TYPE] = handle_r_type_instr, - [FLUSHD] = nop, - [XORHI] = xorhi, +static struct instruction i_type_instructions[I_TYPE_COUNT] = { + [CALL] = INSTRUCTION(call), + [JMPI] = INSTRUCTION(jmpi), + [LDBU] = INSTRUCTION(ldbu), + [ADDI] = INSTRUCTION(addi), + [STB] = INSTRUCTION_UNIMPLEMENTED(stb), + [BR] = INSTRUCTION(br), + [LDB] = INSTRUCTION_UNIMPLEMENTED(ldb), + [CMPGEI] = INSTRUCTION_UNIMPLEMENTED(cmpgei), + [LDHU] = INSTRUCTION(ldhu), + [ANDI] = INSTRUCTION(andi), + [STH] = INSTRUCTION(sth), + [BGE] = INSTRUCTION(bge), + [LDH] = INSTRUCTION(ldh), + [CMPLTI] = INSTRUCTION(cmplti), + [INITDA] = INSTRUCTION(initda), + [ORI] = INSTRUCTION(ori), + [STW] = INSTRUCTION(stw), + [BLT] = INSTRUCTION(blt), + [LDW] = INSTRUCTION_UNIMPLEMENTED(ldw), + [CMPNEI] = INSTRUCTION_UNIMPLEMENTED(cmpnei), + [FLUSHDA] = INSTRUCTION_NOP(flushda), + [XORI] = INSTRUCTION(xori), + [BNE] = INSTRUCTION(bne), + [CMPEQI] = INSTRUCTION_UNIMPLEMENTED(cmpeqi), + [LDBUIO] = INSTRUCTION_UNIMPLEMENTED(ldbuio), + [MULI] = INSTRUCTION(muli), + [STBIO] = INSTRUCTION_UNIMPLEMENTED(stbio), + [BEQ] = INSTRUCTION(beq), + [LDBIO] = INSTRUCTION_UNIMPLEMENTED(ldbio), + [CMPGEUI] = INSTRUCTION_UNIMPLEMENTED(cmpgeui), + [LDHUIO] = INSTRUCTION_UNIMPLEMENTED(ldhuio), + [ANDHI] = INSTRUCTION(andhi), + [STHIO] = INSTRUCTION_UNIMPLEMENTED(sthio), + [BGEU] = INSTRUCTION_UNIMPLEMENTED(bgeu), + [LDHIO] = INSTRUCTION_UNIMPLEMENTED(ldhio), + [CMPLTUI] = INSTRUCTION_UNIMPLEMENTED(cmpltui), + [CUSTOM] = INSTRUCTION_UNIMPLEMENTED(custom), + [INITD] = INSTRUCTION(initd), + [ORHI] = INSTRUCTION_UNIMPLEMENTED(orhi), + [STWIO] = INSTRUCTION_UNIMPLEMENTED(stwio), + [BLTU] = INSTRUCTION_UNIMPLEMENTED(bltu), + [LDWIO] = INSTRUCTION_UNIMPLEMENTED(ldwio), + [R_TYPE] = { "<R-type instruction>", handle_r_type_instr }, + [FLUSHD] = INSTRUCTION_NOP(flushd), + [XORHI] = INSTRUCTION(xorhi), }; /* * R-Type instructions */ +/* + * status <- estatus + * PC <- ea + */ +static int eret(struct nios2 *cpu, uint32_t code __unused) +{ + cpu->ctrl_regs[status] = cpu->ctrl_regs[estatus]; + cpu->pc = cpu->gp_regs[ea]; + + return PC_INC_BY_INSTR; +} + /* rC <- rA rotated left IMM5 bit positions */ static int roli(struct nios2 *cpu, uint32_t code) { @@ -295,13 +406,29 @@ static int rol(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 = gp_regs[instr->b] & BIT_MASK(5); + uint32_t shift_bits = gp_regs[instr->b] & BIT_MASK_FILL(5); - gp_regs[instr->c] = (a << shift_bits) | (a >> (32 - shift_bits)); + gp_regs[instr->c] = (a << shift_bits) | (a >> (32 - shift_bits)); return PC_INC_NORMAL; } +/* */ +static int flushp(struct nios2 *cpu __unused, uint32_t code __unused) +{ + /* TODO */ + + return PC_INC_NORMAL; +} + +/* PC <- ra */ +static int ret(struct nios2 *cpu, uint32_t code __unused) +{ + cpu->pc = cpu->gp_regs[ra]; + + return PC_INC_BY_INSTR; +} + /* rC <- ~(A | rB) */ static int nor(struct nios2 *cpu, uint32_t code) { @@ -313,6 +440,37 @@ static int nor(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* rC <- rA rotated right rb(4..0) bit positions */ +static int ror(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 = gp_regs[instr->b] & BIT_MASK_FILL(5); + + gp_regs[instr->c] = (a << (32 - shift_bits)) | (a >> shift_bits); + + return PC_INC_NORMAL; +} + +/* */ +static int flushi(struct nios2 *cpu, uint32_t code) +{ + /* TODO */ + + return PC_INC_NORMAL; +} + +/* PC <- rA */ +static int jmp(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + + cpu->pc = cpu->gp_regs[instr->a]; + + return PC_INC_BY_INSTR; +} + /* rC <- rA & rB */ static int and(struct nios2 *cpu, uint32_t code) { @@ -360,7 +518,7 @@ static int sll(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] << (gp_regs[instr->b] & BIT_MASK(5)); + gp_regs[instr->c] = gp_regs[instr->a] << (gp_regs[instr->b] & BIT_MASK_FILL(5)); return PC_INC_NORMAL; } @@ -412,7 +570,7 @@ static int srl(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] >> (gp_regs[instr->b] & BIT_MASK(5)); + gp_regs[instr->c] = gp_regs[instr->a] >> (gp_regs[instr->b] & BIT_MASK_FILL(5)); return PC_INC_NORMAL; } @@ -454,11 +612,11 @@ static int divu(struct nios2 *cpu, uint32_t code) uint32_t *gp_regs = cpu->gp_regs; if (!cpu->has_div) - return INSTR_EXECPTION; + return EXCEPTION(NIOS2_EX_UNIMPLEMENTED); /* Division by zero? */ if (gp_regs[instr->b] == 0) - return INSTR_EXECPTION; + return EXCEPTION(NIOS2_EX_DIV_ERR); gp_regs[instr->c] = gp_regs[instr->a] / gp_regs[instr->b]; @@ -473,15 +631,18 @@ static int div(struct nios2 *cpu, uint32_t code) int32_t a, b; if (!cpu->has_div) - return INSTR_EXECPTION; + return EXCEPTION(NIOS2_EX_UNIMPLEMENTED); + a = (int32_t) gp_regs[instr->a]; b = (int32_t) gp_regs[instr->b]; /* Division by zero? */ - if (instr->b == 0) - return INSTR_EXECPTION; + if (b == 0) + return EXCEPTION(NIOS2_EX_DIV_ERR); + /* Divide overflow? */ + if (a == 0x80000000 && b == 0xFFFFFFFF) + return EXCEPTION(NIOS2_EX_DIV_ERR); - a = (int32_t) gp_regs[instr->a]; gp_regs[instr->c] = (uint32_t)(a / b); return PC_INC_NORMAL; @@ -494,13 +655,56 @@ static int rdctl(struct nios2 *cpu, uint32_t code) /* Instruction only allowed in supervisor mode */ if (!nios2_in_supervisor_mode(cpu)) - return INSTR_EXECPTION; + return EXCEPTION(NIOS2_EX_SUPERVISOR_ONLY_I); cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->opx.imm5]; return PC_INC_NORMAL; } +/* */ +static int initi(struct nios2 *cpu __unused, uint32_t code __unused) +{ + /* TODO */ + + return PC_INC_NORMAL; +} + +/* + * estatus <- status + * PIE <- 0 + * U <- 0 + * ea <- PC + 4 + * PC <- exception handler address + */ +static int trap(struct nios2 *cpu, uint32_t code __unused) +{ + uint32_t *gp_regs = cpu->gp_regs; + uint32_t *ctrl_regs = cpu->ctrl_regs; + + ctrl_regs[estatus] = ctrl_regs[status]; + clear_bit(NIOS2_STATUS_PIE, &ctrl_regs[status]); + clear_bit(NIOS2_STATUS_U, &ctrl_regs[status]); + gp_regs[ea] = cpu->pc + 4; + cpu->pc = cpu->exception_handler_addr; + + return PC_INC_BY_INSTR; +} + +/* ctlN <- rA */ +static int wrctl(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + + /* Instruction only allowed in supervisor mode */ + if (!nios2_in_supervisor_mode(cpu)) + return EXCEPTION(NIOS2_EX_SUPERVISOR_ONLY_I); + + cpu->ctrl_regs[instr->opx.imm5] = cpu->gp_regs[instr->a]; + + return PC_INC_NORMAL; +} + /* rC <- rA + rB */ static int add(struct nios2 *cpu, uint32_t code) { @@ -523,48 +727,48 @@ static int sub(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } -static instruction_handler r_type_instr_handlers[R_TYPE_COUNT] = { - [ERET] = unimplemented, - [ROLI] = roli, - [ROL] = rol, - [FLUSHP] = nop, - [RET] = unimplemented, - [NOR] = nor, - [MULXUU] = unimplemented, - [CMPGE] = unimplemented, - [BRET] = unimplemented, - [ROR] = unimplemented, - [FLUSHI] = nop, - [JMP] = unimplemented, - [AND] = and, - [CMPLT] = cmplt, - [SLLI] = slli, - [SLL] = sll, - [OR] = or, - [MULXSU] = unimplemented, - [CMPNE] = cmpne, - [SRLI] = srli, - [SRL] = srl, - [NEXTPC] = unimplemented, - [CALLR] = unimplemented, - [XOR] = xor, - [MULXSS] = unimplemented, - [CMPEQ] = cmpeq, - [DIVU] = divu, - [DIV] = div, - [RDCTL] = rdctl, - [MUL] = unimplemented, - [CMPGEU] = unimplemented, - [INITI] = unimplemented, - [TRAP] = unimplemented, - [WRCTL] = unimplemented, - [CMPLTU] = unimplemented, - [ADD] = add, - [BREAK] = unimplemented, - [SYNC] = nop, - [SUB] = sub, - [SRAI] = unimplemented, - [SRA] = unimplemented, +static struct instruction r_type_instructions[R_TYPE_COUNT] = { + [ERET] = INSTRUCTION(eret), + [ROLI] = INSTRUCTION(roli), + [ROL] = INSTRUCTION(rol), + [FLUSHP] = INSTRUCTION(flushp), + [RET] = INSTRUCTION(ret), + [NOR] = INSTRUCTION(nor), + [MULXUU] = INSTRUCTION_UNIMPLEMENTED(mulxuu), + [CMPGE] = INSTRUCTION_UNIMPLEMENTED(cmpge), + [BRET] = INSTRUCTION_UNIMPLEMENTED(bret), + [ROR] = INSTRUCTION(ror), + [FLUSHI] = INSTRUCTION(flushi), + [JMP] = INSTRUCTION(jmp), + [AND] = INSTRUCTION(and), + [CMPLT] = INSTRUCTION(cmplt), + [SLLI] = INSTRUCTION(slli), + [SLL] = INSTRUCTION(sll), + [OR] = INSTRUCTION(or), + [MULXSU] = INSTRUCTION_UNIMPLEMENTED(mulxsu), + [CMPNE] = INSTRUCTION(cmpne), + [SRLI] = INSTRUCTION(srli), + [SRL] = INSTRUCTION(srl), + [NEXTPC] = INSTRUCTION_UNIMPLEMENTED(nextpc), + [CALLR] = INSTRUCTION_UNIMPLEMENTED(callr), + [XOR] = INSTRUCTION(xor), + [MULXSS] = INSTRUCTION_UNIMPLEMENTED(mulxss), + [CMPEQ] = INSTRUCTION(cmpeq), + [DIVU] = INSTRUCTION(divu), + [DIV] = INSTRUCTION(div), + [RDCTL] = INSTRUCTION(rdctl), + [MUL] = INSTRUCTION_UNIMPLEMENTED(mul), + [CMPGEU] = INSTRUCTION_UNIMPLEMENTED(cmpgeu), + [INITI] = INSTRUCTION(initi), + [TRAP] = INSTRUCTION(trap), + [WRCTL] = INSTRUCTION(wrctl), + [CMPLTU] = INSTRUCTION_UNIMPLEMENTED(cmpltu), + [ADD] = INSTRUCTION(add), + [BREAK] = INSTRUCTION_UNIMPLEMENTED(break), + [SYNC] = INSTRUCTION(nop), + [SUB] = INSTRUCTION(sub), + [SRAI] = INSTRUCTION_UNIMPLEMENTED(srai), + [SRA] = INSTRUCTION_UNIMPLEMENTED(sra), }; static int handle_r_type_instr(struct nios2 *cpu, uint32_t code) @@ -578,7 +782,7 @@ static int handle_r_type_instr(struct nios2 *cpu, uint32_t code) return INSTR_ERR; } - handle_instr = r_type_instr_handlers[opx]; + handle_instr = r_type_instructions[opx].handler; if (unlikely(handle_instr == NULL)) { err("Invalid instruction %08x\n", code); return INSTR_ERR; @@ -593,100 +797,8 @@ instruction_handler instruction_get_handler(uint32_t code) if (unlikely(op >= I_TYPE_COUNT)) return NULL; - return i_type_instr_handlers[op]; -} - -static const char *i_type_instr_strings[I_TYPE_COUNT] = { - [CALL] = "call", - [JMPI] = "jmpi", - [LDBU] = "ldbu", - [ADDI] = "addi", - [STB] = "stb", - [BR] = "br", - [LDB] = "ldb", - [CMPGEI] = "cmpgei", - [LDHU] = "ldhu", - [ANDI] = "andi", - [STH] = "sth", - [BGE] = "bge", - [LDH] = "ldh", - [CMPLTI] = "cmplti", - [INITDA] = "initda", - [ORI] = "ori", - [STW] = "stw", - [BLT] = "blt", - [LDW] = "ldw", - [CMPNEI] = "cmpnei", - [FLUSHDA] = "nop", - [XORI] = "xori", - [BNE] = "bne", - [CMPEQI] = "cmpeqi", - [LDBUIO] = "ldbuio", - [MULI] = "muli", - [STBIO] = "stbio", - [BEQ] = "beq", - [LDBIO] = "ldbio", - [CMPGEUI] = "cmpgeui", - [LDHUIO] = "ldhuio", - [ANDHI] = "andhi", - [STHIO] = "sthio", - [BGEU] = "bgeu", - [LDHIO] = "ldhio", - [CMPLTUI] = "cmpltui", - [CUSTOM] = "custom", - [INITD] = "initd", - [ORHI] = "orhi", - [STWIO] = "stwio", - [BLTU] = "bltu", - [LDWIO] = "ldwio", - [R_TYPE] = "<R-type instruction>", - [FLUSHD] = "flushd", - [XORHI] = "xorhi", -}; - -static const char *r_type_instr_strings[R_TYPE_COUNT] = { - [ERET] = "eret", - [ROLI] = "roli", - [ROL] = "rol", - [FLUSHP] = "flushp", - [RET] = "ret", - [NOR] = "nor", - [MULXUU] = "mulxuu", - [CMPGE] = "cmpge", - [BRET] = "bret", - [ROR] = "ror", - [FLUSHI] = "flushi", - [JMP] = "jmp", - [AND] = "and", - [CMPLT] = "cmplt", - [SLLI] = "slli", - [SLL] = "sll", - [OR] = "or", - [MULXSU] = "mulxsu", - [CMPNE] = "cmpne", - [SRLI] = "srli", - [SRL] = "srl", - [NEXTPC] = "nextpc", - [CALLR] = "callr", - [XOR] = "xor", - [MULXSS] = "mulxss", - [CMPEQ] = "cmpeq", - [DIVU] = "divu", - [DIV] = "div", - [RDCTL] = "rdctl", - [MUL] = "mul", - [CMPGEU] = "cmpgeu", - [INITI] = "initi", - [TRAP] = "trap", - [WRCTL] = "wrctl", - [CMPLTU] = "cmpltu", - [ADD] = "add", - [BREAK] = "break", - [SYNC] = "sync", - [SUB] = "sub", - [SRAI] = "srai", - [SRA] = "sra", -}; + return i_type_instructions[op].handler; +} const char *instruction_get_string(uint32_t code) { @@ -698,7 +810,7 @@ const char *instruction_get_string(uint32_t code) uint32_t opx = get_opxcode(code); if (unlikely(opx >= R_TYPE_COUNT)) return ""; - return r_type_instr_strings[opx]; - }else - return i_type_instr_strings[op]; + return r_type_instructions[opx].name; + } else + return i_type_instructions[op].name; } diff --git a/instruction.h b/instruction.h index 1053936..5a268d3 100644 --- a/instruction.h +++ b/instruction.h @@ -202,13 +202,26 @@ enum { #define INSTR_ERR -1 /* Error in instruction */ #define PC_INC_NORMAL 0 /* Normal PC increment after instruction */ #define PC_INC_BY_INSTR 1 /* PC got incremented by instruction */ -#define INSTR_EXECPTION 2 /* Instruction generated an exception */ +#define INSTR_EXCEPTION_BASE 255 /* Instruction generated an exception */ + +#define EXCEPTION(cause) (INSTR_EXCEPTION_BASE + (cause)) +#define IS_EXCEPTION(ret) ((ret) >= INSTR_EXCEPTION_BASE) +#define EXCEPTION_CAUSE(ret) ((uint8_t)((ret) - INSTR_EXCEPTION_BASE)) /* Forward declaration */ struct nios2; typedef int (*instruction_handler)(struct nios2 *cpu, uint32_t opcode); +struct instruction { + const char *name; + instruction_handler handler; +}; + +#define INSTRUCTION(name) { __stringify(name), name } +#define INSTRUCTION_NOP(name) { __stringify(name), nop } +#define INSTRUCTION_UNIMPLEMENTED(name) { __stringify(name), unimplemented } + extern instruction_handler instruction_get_handler(uint32_t code); extern const char *instruction_get_string(uint32_t code); |