From 32f507ce5f66dd9c89a45854688f46bde33c5e3d Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 10 Nov 2010 09:20:50 +0100 Subject: Initial import of nios2sim (http://nios2sim.googlecode.com/svn/trunk/ r16) --- r_type_handler.c | 458 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 458 insertions(+) create mode 100644 r_type_handler.c (limited to 'r_type_handler.c') 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 +#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) +}; + + + -- cgit v1.2.3-54-g00ecf