/* 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) };