diff options
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | instruction.c | 587 | ||||
-rw-r--r-- | instruction.h | 13 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | nios2.c | 16 | ||||
-rw-r--r-- | nios2.h | 19 | ||||
-rw-r--r-- | nios2sim-ng.h | 4 | ||||
-rw-r--r-- | niosii.h | 6 | ||||
-rw-r--r-- | simulator.c | 12 | ||||
-rw-r--r-- | srec.c | 3 |
10 files changed, 590 insertions, 78 deletions
@@ -7,7 +7,9 @@ OBJS = main.o image.o elf.o srec.o nios2.o instruction.o DEFS = -DVERSION="\"$(VERSION)\"" -DDEBUG -CFLAGS += -g -W -Wall -Wno-packed-bitfield-compat $(DEFS) +CFLAGS += -g -W -Wall -Wextra -Wstrict-prototypes -Wmissing-prototypes \ + -Wno-packed-bitfield-compat \ + $(DEFS) LDFLAGS += -lelf all: prepare $(P) diff --git a/instruction.c b/instruction.c index b6671d1..1846832 100644 --- a/instruction.c +++ b/instruction.c @@ -26,28 +26,52 @@ static inline uint32_t get_opxcode(uint32_t code) return instr->opx.opx11; } -static int unsupported(struct nios2 *cpu, uint32_t code) +/* + * Used as a placeholder for instructions not yet implemented by the simulator. + */ +static int unimplemented(struct nios2 *cpu, uint32_t code) { - info("Unsupported instructtion %08x @ PC %08x\n", code, cpu->pc); + info("Unsupported instruction %s (%08x) @ PC %08x\n", + instruction_get_string(code), code, cpu->pc); return PC_INC_NORMAL; } /* + * 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) +{ + /* Nothing to do here */ + return PC_INC_NORMAL; +} + +/* * J-Type instructions */ +/* + * ra <- PC + 4 + * PC <- (PC(31..28) : IMM26 * 4) + */ static int call(struct nios2 *cpu, uint32_t code) { J_TYPE(instr, code); + cpu->gp_regs[ra] = cpu->pc + 4; + cpu->pc = (instr->imm26 * 4) | (cpu->pc & 0xF0000000); + return PC_INC_BY_INSTR; } +/* PC <- (PC(31..28) : IMM26 * 4) */ static int jmpi(struct nios2 *cpu, uint32_t code) { J_TYPE(instr, code); + cpu->pc = (instr->imm26 * 4) | (cpu->pc & 0xF0000000); + return PC_INC_BY_INSTR; } @@ -62,13 +86,24 @@ static int ldbu(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* rB <- rA + IMM16 */ static int addi(struct nios2 *cpu, uint32_t code) { I_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rB <- rA + IMM16 */ gp_regs[instr->b] = gp_regs[instr->a] + (int16_t) (instr->imm16); + + return PC_INC_NORMAL; +} + +/* PC <- PC + 4 + IMM16 */ +static int br(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + + cpu->pc += 4 + (instr->imm16 & 0xFFFC); + return PC_INC_NORMAL; } @@ -79,96 +114,457 @@ static int ldhu(struct nios2 *cpu, uint32_t code) return PC_INC_NORMAL; } +/* rB <- rA & IMM16 */ static int andi(struct nios2 *cpu, uint32_t code) { I_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rB <- rA & IMM16 */ - gp_regs[instr->b] = gp_regs[instr->a] & (int32_t) (instr->imm16 & BIT_MASK(16)); + gp_regs[instr->b] = gp_regs[instr->a] & instr->imm16; + return PC_INC_NORMAL; } +/* rB <- rA | IMM16 */ static int ori(struct nios2 *cpu, uint32_t code) { I_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rB <- rA | IMM16 */ - gp_regs[instr->b] = gp_regs[instr->a] | (int32_t) (instr->imm16 & BIT_MASK(16)); + gp_regs[instr->b] = gp_regs[instr->a] | instr->imm16; return PC_INC_NORMAL; } +/* + * if ((signed) rA < (signed) rB) + * PC <- PC + 4 + @(IMM16) + * else + * PC <- PC + 4 + */ +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])) + cpu->pc += 4 + (int16_t)(instr->imm16 & 0xFFFC); + else + cpu->pc += 4; + + return PC_INC_BY_INSTR; +} + +/* rB <- rA ^ IMM16 */ static int xori(struct nios2 *cpu, uint32_t code) { I_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rB <- rA ^ IMM16 */ - gp_regs[instr->b] = gp_regs[instr->a] ^ (int32_t) (instr->imm16 & BIT_MASK(16)); + gp_regs[instr->b] = gp_regs[instr->a] ^ instr->imm16; + return PC_INC_NORMAL; +} + +/* rB <- (rA * @(IMM16))(31..0) */ +static int muli(struct nios2 *cpu, uint32_t code) +{ + I_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + uint64_t tmp; + + /* Raise exception if instruction is not implemented */ + if (!cpu->has_mul) + return INSTR_EXECPTION; + + tmp = gp_regs[instr->a] * ((int16_t) instr->imm16); + gp_regs[instr->b] = (uint32_t) (tmp & BIT_MASK(32)); return PC_INC_NORMAL; } /* + * if (rA == rB) + * PC <- PC + 4 + @(IMM16) + * else + * PC <- PC + 4 + */ +static int beq(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 : 0x0000) */ +static int andhi(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; +} + +/* Prototype only, defined below */ +static int handle_r_type_instr(struct nios2 *cpu, uint32_t code); + +/* rB <- rA ^ (IMM16 : 0x0000) */ +static int xorhi(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; +} + +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, +}; + +/* * R-Type instructions */ +/* rC <- rA rotated left IMM5 bit positions */ +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; + + gp_regs[instr->c] = (a << shift_bits) | (a >> (32 - shift_bits)); + + return PC_INC_NORMAL; +} + +/* rC <- rA rotated left rB(4..0) bit positions */ +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); + + gp_regs[instr->c] = (a << shift_bits) | (a >> (32 - shift_bits)); + + return PC_INC_NORMAL; +} + +/* rC <- ~(A | rB) */ +static int nor(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]); + + return PC_INC_NORMAL; +} + +/* rC <- rA & rB */ static int and(struct nios2 *cpu, uint32_t code) { R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rC <- rA & rB */ gp_regs[instr->c] = gp_regs[instr->a] & gp_regs[instr->b]; + + return PC_INC_NORMAL; +} + +/* + * if ((signed) rA < (signed) rB) + * rC <- 1 + * else + * rC <- 0 + */ +static int cmplt(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if (((int32_t) gp_regs[instr->a]) < ((int32_t) gp_regs[instr->b])) + gp_regs[instr->c] = 1; + else + gp_regs[instr->c] = 0; + + return PC_INC_NORMAL; +} + +/* rC <- rA << IMM5 */ +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; + + return PC_INC_NORMAL; +} + +/* rC <- rA << rB(4..0) */ +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)); + return PC_INC_NORMAL; } +/* rC <- rA | rB */ static int or(struct nios2 *cpu, uint32_t code) { R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rC <- rA | rB */ gp_regs[instr->c] = gp_regs[instr->a] | gp_regs[instr->b]; + return PC_INC_NORMAL; } -static int add(struct nios2 *cpu, uint32_t code) +/* + * if (rA != rB) + * rC <- 1 + * else + * rC <- 0 + */ +static int cmpne(struct nios2 *cpu, uint32_t code) { R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rC <- rA + rB */ - gp_regs[instr->c] = gp_regs[instr->a] + gp_regs[instr->b]; + if (gp_regs[instr->a] != gp_regs[instr->b]) + gp_regs[instr->c] = 1; + else + gp_regs[instr->c] = 0; + return PC_INC_NORMAL; } -static int sync(struct nios2 *cpu, uint32_t code) +/* rC <- (unsigned) rA >> ((unsigned) IMM5)*/ +static int srli(struct nios2 *cpu, uint32_t code) { - /* Nothing to do here */ + R_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + gp_regs[instr->c] = gp_regs[instr->a] >> instr->opx.imm5; + + return PC_INC_NORMAL; +} + +/* rC <- (unsigned) rA >> ((unsigned) rB(4..0))*/ +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)); + return PC_INC_NORMAL; } +/* rC <- rA ^ rB */ +static int xor(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]; + + return PC_INC_NORMAL; +} + +/* + * if (rA == rB) + * rC <- 1 + * else + * rC <- 0 + */ +static int cmpeq(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if (gp_regs[instr->a] == gp_regs[instr->b]) + gp_regs[instr->c] = 1; + else + gp_regs[instr->c] = 0; + + return PC_INC_NORMAL; +} + +/* rC <- rA / rB */ +static int divu(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + + if (!cpu->has_div) + return INSTR_EXECPTION; + + /* Division by zero? */ + if (gp_regs[instr->b] == 0) + return INSTR_EXECPTION; + + gp_regs[instr->c] = gp_regs[instr->a] / gp_regs[instr->b]; + + return PC_INC_NORMAL; +} + +/* rC <- rA / rB */ +static int div(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + uint32_t *gp_regs = cpu->gp_regs; + int32_t a, b; + + if (!cpu->has_div) + return INSTR_EXECPTION; + + b = (int32_t) gp_regs[instr->b]; + + /* Division by zero? */ + if (instr->b == 0) + return INSTR_EXECPTION; + + a = (int32_t) gp_regs[instr->a]; + gp_regs[instr->c] = (uint32_t)(a / b); + + return PC_INC_NORMAL; +} + +/* rC <- ctlN */ +static int rdctl(struct nios2 *cpu, uint32_t code) +{ + R_TYPE(instr, code); + + /* Instruction only allowed in supervisor mode */ + if (!nios2_in_supervisor_mode(cpu)) + return INSTR_EXECPTION; + + cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->opx.imm5]; + + return PC_INC_NORMAL; +} + +/* rC <- rA + rB */ +static int add(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]; + + return PC_INC_NORMAL; +} + +/* rC <- rA - rB */ static int sub(struct nios2 *cpu, uint32_t code) { R_TYPE(instr, code); uint32_t *gp_regs = cpu->gp_regs; - /* rC <- rA - rB */ gp_regs[instr->c] = gp_regs[instr->a] - gp_regs[instr->b]; + return PC_INC_NORMAL; } static instruction_handler r_type_instr_handlers[R_TYPE_COUNT] = { - [AND] = and, - [OR] = or, - [ADD] = add, - - [BREAK] = unsupported, - [SYNC] = sync, - [SUB] = sub, - [SRAI] = unsupported, - [SRA] = unsupported, + [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 int handle_r_type_instr(struct nios2 *cpu, uint32_t code) @@ -191,38 +587,6 @@ static int handle_r_type_instr(struct nios2 *cpu, uint32_t code) return handle_instr(cpu, code); } -static instruction_handler i_type_instr_handlers[I_TYPE_COUNT] = { - [CALL] = call, - [JMPI] = jmpi, - [LDBU] = ldbu, - [ADDI] = addi, - [STB] = unsupported, - [BR] = unsupported, - [LDB] = unsupported, - [CMPGEI] = unsupported, - [LDHU] = ldhu, - [ANDI] = andi, - [STH] = unsupported, - [BGE] = unsupported, - [LDH] = unsupported, - [CMPLTI] = unsupported, - [INITDA] = unsupported, - [ORI] = ori, - [STW] = unsupported, - [BLT] = unsupported, - [LDW] = unsupported, - [CMPNEI] = unsupported, - [FLUSHDA] = unsupported, - [XORI] = xori, - [BNE] = unsupported, - - [BLTU] = unsupported, - [LDWIO] = unsupported, - [R_TYPE] = handle_r_type_instr, - [FLUSHD] = unsupported, - [XORHI] = unsupported, -}; - instruction_handler instruction_get_handler(uint32_t code) { uint32_t op = get_opcode(code); @@ -231,3 +595,110 @@ instruction_handler instruction_get_handler(uint32_t code) 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", +}; + +const char *instruction_get_string(uint32_t code) +{ + uint32_t op = get_opcode(code); + + if (unlikely(op >= I_TYPE_COUNT)) + return ""; + else if (op == R_TYPE) { + 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]; +} diff --git a/instruction.h b/instruction.h index f53c995..1053936 100644 --- a/instruction.h +++ b/instruction.h @@ -37,7 +37,7 @@ struct r_type { union { uint16_t opx11:11; struct { - uint8_t n:5; + uint8_t imm5:5; uint8_t opx6:6; } __packed; } opx; @@ -196,9 +196,13 @@ enum { }; #define R_TYPE_COUNT 0x40 -#define INSTR_ERR -1 -#define PC_INC_NORMAL 0 -#define PC_INC_BY_INSTR 1 +/* + * Return values for instruction handlers + */ +#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 */ /* Forward declaration */ struct nios2; @@ -206,5 +210,6 @@ struct nios2; typedef int (*instruction_handler)(struct nios2 *cpu, uint32_t opcode); extern instruction_handler instruction_get_handler(uint32_t code); +extern const char *instruction_get_string(uint32_t code); #endif /* _INSTRUCTION_H_ */ @@ -118,7 +118,7 @@ int main(int argc, char *argv[]) int image_format = FORMAT_ELF; uint8_t *mem_base; size_t mem_size = DEFAULT_MEM_SIZE; - bool has_mmu = false; + struct nios2 cpu; int c; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1) { @@ -130,7 +130,7 @@ int main(int argc, char *argv[]) mem_size = parse_mem_size(optarg); break; case 'M': - has_mmu = true; + cpu.has_mmu = true; case 'e': image_format = FORMAT_ELF; break; @@ -17,6 +17,22 @@ void nios2_cpu_reset(struct nios2 *cpu) { memset(cpu, 0x00, sizeof(struct nios2)); + cpu->mode = NIOS2_SUPERVISOR_MODE; +} + +bool nios2_in_user_mode(struct nios2 *cpu) +{ + if (!cpu->has_mmu) + return false; + else if (cpu->mode != NIOS2_USER_MODE) + return false; + else + return true; +} + +bool nios2_in_supervisor_mode(struct nios2 *cpu) +{ + return !nios2_in_user_mode(cpu); } uint32_t nios2_cpu_fetch_instr(struct nios2 *cpu, uint32_t *mem_base) @@ -25,9 +25,18 @@ struct nios2 { uint32_t ctrl_regs[NIOS2_CTRL_REG_COUNT]; /* Program counter */ uint32_t pc; + /* User or Supervisor mode */ + int mode; + + /* Configurable processor features */ + bool has_mul; /* mul, muli */ + bool has_mulx; /* mulxss, mulxsu, mulxuu */ + bool has_div; /* div, divu */ + + bool has_mmu; /* Memory Management Unit */ }; -/* Aliases for general-purpors registers */ +/* Aliases for general-purpose registers */ enum { zero = 0, at, @@ -59,9 +68,17 @@ enum { config, mpubase, mpuacc, +}; +enum { + NIOS2_SUPERVISOR_MODE, + NIOS2_USER_MODE, }; extern void nios2_cpu_reset(struct nios2 *cpu); +extern bool nios2_in_user_mode(struct nios2 *cpu); +extern bool nios2_in_supervisor_mode(struct nios2 *cpu); +extern uint32_t nios2_cpu_fetch_instr(struct nios2 *cpu, uint32_t *mem_base); +extern int nios2_cpu_execute_instr(struct nios2 *cpu, uint32_t instr); #endif /* _NIOS2_H_ */ diff --git a/nios2sim-ng.h b/nios2sim-ng.h index e4f4bcf..9be1d0d 100644 --- a/nios2sim-ng.h +++ b/nios2sim-ng.h @@ -5,18 +5,20 @@ #ifndef _NIOS2SIM_NG_H_ #define _NIOS2SIM_NG_H_ -#include <stdlib.h> #include <stdint.h> #include <stdbool.h> #include "bits.h" #include "compiler.h" +#include "util.h" extern bool verbose; #define __round_mask(x, y) ((__typeof__(x))((y) - 1)) #define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1) +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + #define err(fmt, args...) fprintf(stderr, "Error: " fmt, ##args) #define warn(fmt, args...) fprintf(stderr, "Warning: " fmt, ##args) #define info(fmt, args...) fprintf(stdout, fmt, ##args) @@ -75,12 +75,12 @@ struct i_type_code{ uint32_t imm16:16; uint32_t b:5; uint32_t a:5; -}__attribute__ ((__packed__)); +} __attribute__ ((__packed__)); struct j_type_code{ uint32_t op:6; uint32_t imm26:26; -}__attribute__ ((__packed__)); +} __attribute__ ((__packed__)); struct r_type_code{ uint32_t op:6; @@ -89,7 +89,7 @@ struct r_type_code{ uint32_t c:5; uint32_t b:5; uint32_t a:5; -}__attribute__ ((__packed__)); +} __attribute__ ((__packed__)); #define handler_item(func) {.handler = func} diff --git a/simulator.c b/simulator.c index e4880e9..fb41893 100644 --- a/simulator.c +++ b/simulator.c @@ -357,16 +357,16 @@ static void dump_call_stack(void) printf("============================================================\n"); } -void simulating(void) +void simulator_run(void) { - struct image_info * info = get_image_info(); - struct NIOS_CPU * cpu = NULL; + struct image_info *info = get_image_info(); + struct NIOS_CPU *cpu = NULL; uint32_t code = 0; uint32_t exec_result = 0; - + /* register the segment fault and Ctrl-C handler */ register_signal_handler(); - + /* init cpu*/ reset_cpu(); cpu = get_nios_cpu(); @@ -381,7 +381,7 @@ void simulating(void) /* main loop to simulating the execute of NIOSII */ printf("Enter simulating ..................\n"); - while(1){ + while (1) { /* Get the instruction */ code = get_instruct(cpu, info->mem_base, info->base_addr); @@ -9,8 +9,7 @@ */ #include <stdio.h> -#include <stdint.h> -#include <stdbool.h> +#include <stdlib.h> #include <string.h> #include "nios2sim-ng.h" |