diff options
Diffstat (limited to 'i_type_handler.c')
-rw-r--r-- | i_type_handler.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/i_type_handler.c b/i_type_handler.c new file mode 100644 index 0000000..be1ff76 --- /dev/null +++ b/i_type_handler.c @@ -0,0 +1,496 @@ +/* + 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 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) +}; + +/*----------------------------------------------------------------------------*/ + |