summaryrefslogtreecommitdiff
path: root/r_type_handler.c
diff options
context:
space:
mode:
Diffstat (limited to 'r_type_handler.c')
-rw-r--r--r_type_handler.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/r_type_handler.c b/r_type_handler.c
new file mode 100644
index 0000000..a5d5d1d
--- /dev/null
+++ b/r_type_handler.c
@@ -0,0 +1,458 @@
+/*
+ Nios-sim - one simple NIOSII simulator only for personal interest and fun.
+ Copyright (C) 2010 chysun2000@gmail.com
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <stdio.h>
+#include "public.h"
+#include "niosii.h"
+#include "instruction.h"
+
+static uint32_t wrctl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->ctrl_regs[instr->n] = cpu->gp_regs[instr->a];
+
+ return PC_INC_NORMAL;
+}
+
+
+static uint32_t eret(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[estatus];
+ cpu->pc = cpu->gp_regs[ea];
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t roli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = (instr->n) ;
+ uint32_t value = cpu->gp_regs[instr->a];
+ uint32_t temp = 0;
+
+ temp = value >> (32 - shift_bit);
+ cpu->gp_regs[instr->c] = value << shift_bit;
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->c] | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t rol(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = cpu->gp_regs[instr->b] & 0x1F;
+ uint32_t temp = (cpu->gp_regs[instr->a]) >> (32 - shift_bit);
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] << shift_bit) | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushp(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t ret(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->pc = cpu->gp_regs[ra];
+
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t nor(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = ~(cpu->gp_regs[instr->a] | cpu->gp_regs[instr->b]);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxuu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint64_t temp = 0;
+
+ temp = (uint32_t)cpu->gp_regs[instr->a];
+ temp = temp * (uint32_t)cpu->gp_regs[instr->b];
+ cpu->gp_regs[instr->c] = ((uint32_t)(temp >> 32)) & (0xFFFFFFFF);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpge(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) >= (int32_t)(cpu->gp_regs[instr->b])){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else {
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t bret(struct NIOS_CPU * cpu, uint32_t code)
+{
+
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[bstatus];
+ cpu->pc = cpu->gp_regs[ba];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t ror(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t shift_bit = cpu->gp_regs[instr->b] & 0x1F;
+ uint32_t temp = cpu->gp_regs[instr->a] << (32 - shift_bit);
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] >> shift_bit) | temp;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t flushi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t jmp(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->pc = cpu->gp_regs[instr->a];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t and(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] & cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmplt(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if ((int32_t)(cpu->gp_regs[instr->a]) < (int32_t)(cpu->gp_regs[instr->b])){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t slli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] << instr->n;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sll(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] << (cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t wrprs(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t or(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] | cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxsu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int64_t a = (int32_t)(cpu->gp_regs[instr->a]);
+ int64_t temp = 0;
+
+ temp = a * cpu->gp_regs[instr->b];
+ cpu->gp_regs[instr->c] = (uint32_t)((temp >> 32));
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpne(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] != cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+static uint32_t srli(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] >> (uint32_t)(instr->n);
+ return PC_INC_NORMAL;
+}
+static uint32_t srl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] >> (cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t nextpc(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->pc + 4;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t callr(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ cpu->gp_regs[ra] = cpu->pc + 4;
+ cpu->pc = cpu->gp_regs[instr->a];
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t xor(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ uint32_t a = cpu->gp_regs[instr->a];
+ uint32_t b = cpu->gp_regs[instr->b];
+
+ cpu->gp_regs[instr->c] = a ^ b;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mulxss(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ int32_t b = (int32_t)cpu->gp_regs[instr->b];
+ uint64_t temp = 0;
+
+ temp = a * b;
+ cpu->gp_regs[instr->c] = (uint32_t) (temp >> 32);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpeq(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if(cpu->gp_regs[instr->a] == cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t divu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->b] != 0){
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] / cpu->gp_regs[instr->b];
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t div(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ int32_t b = (int32_t)cpu->gp_regs[instr->b];
+
+ if (b != 0){
+ cpu->gp_regs[instr->c] = a / b;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t rdctl(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->ctrl_regs[instr->n];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t mul(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = (cpu->gp_regs[instr->a] * cpu->gp_regs[instr->b]) & 0xFFFFFFFF;
+ return PC_INC_NORMAL;
+}
+
+static uint32_t cmpgeu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] >= cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else{
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t initi(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t trap(struct NIOS_CPU * cpu, uint32_t code)
+{
+ cpu->ctrl_regs[estatus] = cpu->ctrl_regs[status];
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[status] & 0xFFFFFFFC;
+ cpu->gp_regs[ea] = cpu->pc + 4;
+ cpu->pc = EXCEPTION_HANDLER_ADDR;
+ return PC_INC_BY_INSTR;
+}
+
+static uint32_t cmpltu(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ if (cpu->gp_regs[instr->a] < cpu->gp_regs[instr->b]){
+ cpu->gp_regs[instr->c] = 1;
+ }
+ else {
+ cpu->gp_regs[instr->c] = 0;
+ }
+ return PC_INC_NORMAL;
+}
+
+static uint32_t add(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] + cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t instr_break(struct NIOS_CPU * cpu, uint32_t code)
+{
+#ifdef NIOS_SIM_SUPPORT_BREAK
+ cpu->ctrl_regs[bstatus] = cpu->ctrl_regs[status];
+ cpu->ctrl_regs[status] = cpu->ctrl_regs[status] & 0xFFFFFFFC;
+ cpu->gp_regs[ba] = cpu->pc + 4;
+ cpu->pc = BREAK_HANDLER_ADDRESS;
+ return PC_INC_BY_INSTR;
+#else
+ return PC_INC_NORMAL;
+#endif
+}
+
+static uint32_t instr_sync(struct NIOS_CPU * cpu, uint32_t code)
+{
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sub(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ cpu->gp_regs[instr->c] = cpu->gp_regs[instr->a] - cpu->gp_regs[instr->b];
+ return PC_INC_NORMAL;
+}
+
+static uint32_t srai(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+
+ int32_t a = (int32_t)cpu->gp_regs[instr->a];
+ cpu->gp_regs[instr->c] = a >> (uint32_t)(instr->n);
+ return PC_INC_NORMAL;
+}
+
+static uint32_t sra(struct NIOS_CPU * cpu, uint32_t code)
+{
+ def_r_type_code;
+ int32_t a = (int32_t) cpu->gp_regs[instr->a];
+
+ cpu->gp_regs[instr->c] = a >> (uint32_t)(cpu->gp_regs[instr->b] & 0x1F);
+ return PC_INC_NORMAL;
+}
+
+#define R_TYPE_HANDLER_COUNT (0x40)
+
+struct r_type_handler r_type_handlers[R_TYPE_HANDLER_COUNT] = {
+ [ERET] = handler_item(eret),
+ [ROLI] = handler_item(roli),
+ [ROL] = handler_item(rol),
+ [FLUSHP] = handler_item(flushp),
+ [RET] = handler_item(ret),
+ [NOR] = handler_item(nor),
+ [MULXUU] = handler_item(mulxuu),
+ [CMPGE] = handler_item(cmpge),
+ [BRET] = handler_item(bret),
+ [ROR] = handler_item(ror),
+ [FLUSHI] = handler_item(flushi),
+ [JMP] = handler_item(jmp),
+ [AND] = handler_item(and),
+ [CMPLT] = handler_item(cmplt),
+ [SLLI] = handler_item(slli),
+ [SLL] = handler_item(sll),
+ [WRPRS] = handler_item(wrprs),
+ [OR] = handler_item(or),
+ [MULXSU] = handler_item(mulxsu),
+ [CMPNE] = handler_item(cmpne),
+ [SRLI] = handler_item(srli),
+ [SRL] = handler_item(srl),
+ [NEXTPC] = handler_item(nextpc),
+ [CALLR] = handler_item(callr),
+ [XOR] = handler_item(xor),
+ [MULXSS] = handler_item(mulxss),
+ [CMPEQ] = handler_item(cmpeq),
+ [DIVU] = handler_item(divu),
+ [DIV] = handler_item(div),
+ [RDCTL] = handler_item(rdctl),
+ [MUL] = handler_item(mul),
+ [CMPGEU] = handler_item(cmpgeu),
+ [INITI] = handler_item(initi),
+ [TRAP] = handler_item(trap),
+ [WRCTL] = handler_item(wrctl),
+ [CMPLTU] = handler_item(cmpltu),
+ [ADD] = handler_item(add),
+ [BREAK] = handler_item(instr_break),
+ [SYNC] = handler_item(instr_sync),
+ [SUB] = handler_item(sub),
+ [SRAI] = handler_item(srai),
+ [SRA] = handler_item(sra)
+};
+
+
+