summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--instruction.c587
-rw-r--r--instruction.h13
-rw-r--r--main.c4
-rw-r--r--nios2.c16
-rw-r--r--nios2.h19
-rw-r--r--nios2sim-ng.h4
-rw-r--r--niosii.h6
-rw-r--r--simulator.c12
-rw-r--r--srec.c3
10 files changed, 590 insertions, 78 deletions
diff --git a/Makefile b/Makefile
index 88796be..a5638ff 100644
--- a/Makefile
+++ b/Makefile
@@ -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_ */
diff --git a/main.c b/main.c
index 13526bf..0fdcc6f 100644
--- a/main.c
+++ b/main.c
@@ -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;
diff --git a/nios2.c b/nios2.c
index 4586c20..87eb3f3 100644
--- a/nios2.c
+++ b/nios2.c
@@ -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)
diff --git a/nios2.h b/nios2.h
index 15edbe8..eb13b95 100644
--- a/nios2.h
+++ b/nios2.h
@@ -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)
diff --git a/niosii.h b/niosii.h
index cd4ba80..9cbef49 100644
--- a/niosii.h
+++ b/niosii.h
@@ -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);
diff --git a/srec.c b/srec.c
index 146af46..7c3aaf4 100644
--- a/srec.c
+++ b/srec.c
@@ -9,8 +9,7 @@
*/
#include <stdio.h>
-#include <stdint.h>
-#include <stdbool.h>
+#include <stdlib.h>
#include <string.h>
#include "nios2sim-ng.h"