/* 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 ldbu(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int32_t addr = 0; addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16); cpu->gp_regs[instr->b] = get_byte(addr) & 0x000000FF; return PC_INC_NORMAL; } static uint32_t addi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16); return PC_INC_NORMAL; } static uint32_t stb(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t addr = 0; addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16); store_byte(addr, (cpu->gp_regs[instr->b] & 0xFF)); return PC_INC_NORMAL; } static uint32_t br(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t imm16 = (int16_t)instr->imm16; cpu->pc = cpu->pc + 4 + (int16_t)(imm16 & 0xFFFC); return PC_INC_BY_INSTR; } static uint32_t ldb(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16); cpu->gp_regs[instr->b] = (int)((char)(get_byte(addr))); return PC_INC_NORMAL; } static uint32_t cmpgei(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if ((int32_t)(cpu->gp_regs[instr->a]) >= (int32_t)((int16_t)(instr->imm16))){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t cmplti(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if ((int32_t)(cpu->gp_regs[instr->a]) < (int32_t)((int16_t)(instr->imm16))){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t ldhu(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t offset = (int16_t) instr->imm16; int16_t value = 0; value = get_half_word((int16_t)offset + cpu->gp_regs[instr->a]); cpu->gp_regs[instr->b] = ((uint32_t)value) & 0xFFFF; return PC_INC_NORMAL; } static uint32_t andi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t temp = instr->imm16; temp = temp & 0xFFFF; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] & temp; return PC_INC_NORMAL; } static uint32_t sth(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t offset = (int16_t)instr->imm16; uint32_t addr = 0; addr = cpu->gp_regs[instr->a] + (int16_t)offset; store_half_word(addr, (uint16_t)(cpu->gp_regs[instr->b] & 0xFFFF)); return PC_INC_NORMAL; } static uint32_t bge(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int32_t a = (int32_t)(cpu->gp_regs[instr->a]); int32_t b = (int32_t)(cpu->gp_regs[instr->b]); if (a >= b){ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC); } else{ cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t ldh(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t value = 0; value = (int16_t)get_half_word(cpu->gp_regs[instr->a] + (int16_t)(instr->imm16)); cpu->gp_regs[instr->b] = (int32_t)value; return PC_INC_NORMAL; } static uint32_t initda(struct NIOS_CPU * cpu, uint32_t code) { #if 0 def_i_type_code; #endif return PC_INC_NORMAL; } static uint32_t ori(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int32_t temp = (int16_t)instr->imm16; temp = temp & 0xFFFF; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] | temp; return PC_INC_NORMAL; } static uint32_t stw(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t offset = (int16_t)(instr->imm16); store_word(cpu->gp_regs[instr->a] + (int16_t)offset, cpu->gp_regs[instr->b]); return PC_INC_NORMAL; } static uint32_t blt(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int32_t a = (int32_t)(cpu->gp_regs[instr->a]); int32_t b = (int32_t)(cpu->gp_regs[instr->b]); int16_t imm16 = (int16_t)(instr->imm16); if (a < b){ cpu->pc = cpu->pc + 4 + (int16_t)(imm16 & 0xFFFC); } else{ cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t ldw(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t offset = (int16_t)(instr->imm16); cpu->gp_regs[instr->b] = get_word(cpu->gp_regs[instr->a] + (int16_t)offset); return PC_INC_NORMAL; } static uint32_t cmpnei(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t value = (int16_t)(instr->imm16); if (cpu->gp_regs[instr->a] != (int16_t)value){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t flushda(struct NIOS_CPU * cpu, uint32_t code) { #if 0 def_i_type_code; #endif return PC_INC_NORMAL; } static uint32_t xori(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t value = 0; value = (uint16_t)instr->imm16; value &= 0xFFFF; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] ^ value; return PC_INC_NORMAL; } static uint32_t bne(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if (cpu->gp_regs[instr->a] != cpu->gp_regs[instr->b]){ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC); } else { cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t cmpeqi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if(cpu->gp_regs[instr->a] == (int32_t)(instr->imm16)){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t ldbuio(struct NIOS_CPU * cpu, uint32_t code) { return ldbu(cpu, code); } static uint32_t muli(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; unsigned long long data = 0; uint32_t a = cpu->gp_regs[instr->a]; int32_t b = (int32_t)((int16_t)instr->imm16); data = (a * b); cpu->gp_regs[instr->b] = (uint32_t)(data & 0xFFFFFFFF); return PC_INC_NORMAL; } static uint32_t stbio(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t addr = cpu->gp_regs[instr->a] + (int16_t)(instr->imm16); store_byte(addr, (uint8_t)(cpu->gp_regs[instr->b] & 0xFF)); return PC_INC_NORMAL; } static uint32_t beq(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int16_t temp = (int16_t)instr->imm16; if (cpu->gp_regs[instr->a] == cpu->gp_regs[instr->b]){ cpu->pc = cpu->pc + 4 + (int16_t)(temp & 0xFFFC); } else{ cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t ldbio(struct NIOS_CPU * cpu, uint32_t code) { return ldb(cpu, code); } static uint32_t cmpgeui(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t value = 0; value = (uint32_t)(((uint16_t)(instr->imm16)) & 0xFFFF); if ((uint32_t)(cpu->gp_regs[instr->a]) >= value){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t ldhuio(struct NIOS_CPU * cpu, uint32_t code) { return ldhu(cpu, code); } static uint32_t andhi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; int32_t value = 0; int32_t temp = (int32_t)(instr->imm16); value = temp << 16; value = value & 0xFFFF0000; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] & value; return PC_INC_NORMAL; } static uint32_t sthio(struct NIOS_CPU * cpu, uint32_t code) { return sth(cpu, code); } static uint32_t bgeu(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if (cpu->gp_regs[instr->a] >= cpu->gp_regs[instr->b]){ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)(instr->imm16) & 0xFFFC); } else{ cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t ldhio(struct NIOS_CPU * cpu, uint32_t code) { return ldh(cpu, code); } static uint32_t cmpltui(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if (cpu->gp_regs[instr->a] < ((uint32_t)((uint16_t)instr->imm16) & 0xFFFF)){ cpu->gp_regs[instr->b] = 1; } else{ cpu->gp_regs[instr->b] = 0; } return PC_INC_NORMAL; } static uint32_t custom(struct NIOS_CPU * cpu, uint32_t code) { return custom_instr(cpu, code); } static uint32_t initd(struct NIOS_CPU * cpu, uint32_t code) { return PC_INC_NORMAL; } static uint32_t orhi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] | (((uint32_t)((uint16_t)instr->imm16) << 16) & 0xFFFF0000); return PC_INC_NORMAL; } static uint32_t stwio(struct NIOS_CPU * cpu, uint32_t code) { return stw(cpu, code); } static uint32_t bltu(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; if (cpu->gp_regs[instr->a] < cpu->gp_regs[instr->b]){ cpu->pc = cpu->pc + 4 + (int16_t)((int16_t)instr->imm16 & 0xFFFC); } else{ cpu->pc = cpu->pc + 4; } return PC_INC_BY_INSTR; } static uint32_t ldwio(struct NIOS_CPU * cpu, uint32_t code) { return ldw(cpu, code); } static uint32_t rdprs(struct NIOS_CPU * cpu, uint32_t code) { return PC_INC_NORMAL; } static uint32_t flushd(struct NIOS_CPU * cpu, uint32_t code) { return PC_INC_NORMAL; } static uint32_t xorhi(struct NIOS_CPU * cpu, uint32_t code) { def_i_type_code; uint32_t value = (uint16_t)(instr->imm16); value = value << 16; value = value & 0xFFFF0000; cpu->gp_regs[instr->b] = cpu->gp_regs[instr->a] ^ value; return PC_INC_NORMAL; } /*----------------------------------------------------------------------------*/ #define I_TYPE_HANDLER_COUNT (0x40) struct i_type_handler i_type_handlers[I_TYPE_HANDLER_COUNT] = { [LDBU] = handler_item(ldbu), [ADDI] = handler_item(addi), [STB] = handler_item(stb), [BR] = handler_item(br), [LDB] = handler_item(ldb), [CMPGEI] = handler_item(cmpgei), [LDHU] = handler_item(ldhu), [ANDI] = handler_item(andi), [STH] = handler_item(sth), [BGE] = handler_item(bge), [LDH] = handler_item(ldh), [CMPLTI] = handler_item(cmplti), [INITDA] = handler_item(initda), [ORI] = handler_item(ori), [STW] = handler_item(stw), [BLT] = handler_item(blt), [LDW] = handler_item(ldw), [CMPNEI] = handler_item(cmpnei), [FLUSHDA] = handler_item(flushda), [XORI] = handler_item(xori), [BNE] = handler_item(bne), [CMPEQI] = handler_item(cmpeqi), [LDBUIO] = handler_item(ldbuio), [MULI] = handler_item(muli), [STBIO] = handler_item(stbio), [BEQ] = handler_item(beq), [LDBIO] = handler_item(ldbio), [CMPGEUI] = handler_item(cmpgeui), [LDHUIO] = handler_item(ldhuio), [ANDHI] = handler_item(andhi), [STHIO] = handler_item(sthio), [BGEU] = handler_item(bgeu), [LDHIO] = handler_item(ldhio), [CMPLTUI] = handler_item(cmpltui), [CUSTOM] = handler_item(custom), [INITD] = handler_item(initd), [ORHI] = handler_item(orhi), [STWIO] = handler_item(stwio), [BLTU] = handler_item(bltu), [LDWIO] = handler_item(ldwio), [RDPRS] = handler_item(rdprs), [FLUSHD] = handler_item(flushd), [XORHI] = handler_item(xorhi) }; /*----------------------------------------------------------------------------*/