URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_66/] [or1ksim/] [cpu/] [or32/] [insnset.c] - Rev 1342
Go to most recent revision | Compare with Previous | Blame | View Log
/* execute.c -- Instruction specific functions. Copyright (C) 1999 Damjan Lampret, lampret@opencores.org 2000-2002 Marko Mlinar, markom@opencores.org This file is part of OpenRISC 1000 Architectural Simulator. 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ INSTRUCTION (l_add) { signed long temp1, temp2, temp3; signed char temp4; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp2 = (signed long)PARAM2; temp3 = (signed long)PARAM1; temp1 = temp2 + temp3; SET_PARAM0(temp1); set_ov_flag (temp1); if (ARITH_SET_FLAG) { flag = temp1 == 0; setsprbits(SPR_SR, SPR_SR_F, flag); } if ((unsigned long) temp1 < (unsigned long) temp2) setsprbits(SPR_SR, SPR_SR_CY, 1); else setsprbits(SPR_SR, SPR_SR_CY, 0); temp4 = temp1; if (temp4 == temp1) or1k_mstats.byteadd++; } INSTRUCTION (l_addc) { signed long temp1, temp2, temp3; signed char temp4; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp2 = (signed long)PARAM2; temp3 = (signed long)PARAM1; temp1 = temp2 + temp3 + getsprbits(SPR_SR, SPR_SR_CY); SET_PARAM0(temp1); set_ov_flag (temp1); if (ARITH_SET_FLAG) { flag = temp1 == 0; setsprbits(SPR_SR, SPR_SR_F, flag); } if ((unsigned long) temp1 < (unsigned long) temp2) setsprbits(SPR_SR, SPR_SR_CY, 1); else setsprbits(SPR_SR, SPR_SR_CY, 0); temp4 = temp1; if (temp4 == temp1) or1k_mstats.byteadd++; } INSTRUCTION (l_sw) { int old_cyc = 0; IFF (config.cpu.dependstats) current->func_unit = it_store; IFF (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; set_mem32(PARAM0, PARAM1, &breakpoint); if (config.cpu.sbuf_len) { int t = runtime.sim.mem_cycles; runtime.sim.mem_cycles = old_cyc; sbuf_store (t - old_cyc); } } INSTRUCTION (l_sb) { int old_cyc = 0; IFF (config.cpu.dependstats) current->func_unit = it_store; IFF (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; set_mem8(PARAM0, PARAM1, &breakpoint); if (config.cpu.sbuf_len) { int t = runtime.sim.mem_cycles; runtime.sim.mem_cycles = old_cyc; sbuf_store (t- old_cyc); } } INSTRUCTION (l_sh) { int old_cyc = 0; IFF (config.cpu.dependstats) current->func_unit = it_store; IFF (config.cpu.sbuf_len) old_cyc = runtime.sim.mem_cycles; set_mem16(PARAM0, PARAM1, &breakpoint); if (config.cpu.sbuf_len) { int t = runtime.sim.mem_cycles; runtime.sim.mem_cycles = old_cyc; sbuf_store (t - old_cyc); } } INSTRUCTION (l_lwz) { unsigned long val; IFF (config.cpu.dependstats) current->func_unit = it_load; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem32(PARAM1, &breakpoint); /* If eval operand produced exception don't set anything */ if (!pending.valid) SET_PARAM0(val); } INSTRUCTION (l_lbs) { signed char val; IFF (config.cpu.dependstats) current->func_unit = it_load; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem8(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!pending.valid) SET_PARAM0(val); } INSTRUCTION (l_lbz) { unsigned char val; IFF (config.cpu.dependstats) current->func_unit = it_load; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem8(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!pending.valid) SET_PARAM0(val); } INSTRUCTION (l_lhs) { signed short val; IFF (config.cpu.dependstats) current->func_unit = it_load; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem16(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!pending.valid) SET_PARAM0(val); } INSTRUCTION (l_lhz) { unsigned short val; IFF (config.cpu.dependstats) current->func_unit = it_load; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem16(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!pending.valid) SET_PARAM0(val); } INSTRUCTION (l_movhi) { IFF (config.cpu.dependstats) current->func_unit = it_movimm; SET_PARAM0(PARAM1 << 16); } INSTRUCTION (l_and) { unsigned long temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp1 = PARAM1 & PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); if (ARITH_SET_FLAG) { flag = temp1 == 0; setsprbits(SPR_SR, SPR_SR_F, flag); } } INSTRUCTION (l_or) { unsigned long temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp1 = PARAM1 | PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_xor) { unsigned long temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp1 = PARAM1 ^ PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_sub) { signed long temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp1 = (signed long)PARAM1 - (signed long)PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } /*int mcount = 0;*/ INSTRUCTION (l_mul) { signed long temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp1 = PARAM1 * PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /*if (!(mcount++ & 1023)) { PRINTF ("[%i]\n",mcount); }*/ } INSTRUCTION (l_div) { signed long temp3, temp2, temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp3 = PARAM2; temp2 = PARAM1; if (temp3) temp1 = temp2 / temp3; else { except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr); return; } set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_divu) { unsigned long temp3, temp2, temp1; IFF (config.cpu.dependstats) current->func_unit = it_arith; temp3 = PARAM2; temp2 = PARAM1; if (temp3) temp1 = temp2 / temp3; else { except_handle(EXCEPT_ILLEGAL, iqueue[0].insn_addr); return; } set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 16; */ } INSTRUCTION (l_sll) { unsigned long temp1; IFF (config.cpu.dependstats) current->func_unit = it_shift; temp1 = PARAM1 << PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_sra) { signed long temp1; IFF (config.cpu.dependstats) current->func_unit = it_shift; temp1 = (signed)PARAM1 >> PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_srl) { unsigned long temp1; IFF (config.cpu.dependstats) current->func_unit = it_shift; temp1 = PARAM1 >> PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_bf) { if (config.bpb.enabled) { int fwd = (PARAM0 >= pc) ? 1 : 0; IFF (config.cpu.dependstats) current->func_unit = it_branch; or1k_mstats.bf[flag][fwd]++; bpb_update(current->insn_addr, flag); } if (flag) { pcdelay = pc + (signed)PARAM0 * 4; btic_update(pcnext); next_delay_insn = 1; } else { btic_update(pc); } } INSTRUCTION (l_bnf) { if (config.bpb.enabled) { int fwd = (PARAM0 >= pc) ? 1 : 0; IFF (config.cpu.dependstats) current->func_unit = it_branch; or1k_mstats.bnf[!flag][fwd]++; bpb_update(current->insn_addr, flag == 0); } if (flag == 0) { pcdelay = pc + (signed)PARAM0 * 4; btic_update(pcnext); next_delay_insn = 1; } else { btic_update(pc); } } INSTRUCTION (l_j) { pcdelay = pc + (signed)PARAM0 * 4; IFF (config.cpu.dependstats) current->func_unit = it_jump; next_delay_insn = 1; } INSTRUCTION (l_jal) { pcdelay = pc + (signed)PARAM0 * 4; IFF (config.cpu.dependstats) current->func_unit = it_jump; set_reg32(LINK_REGNO, pc + 8); next_delay_insn = 1; if (config.sim.profile) { struct mem_entry *entry; struct label_entry *tmp; if (verify_memoryarea(pcdelay) && (tmp = get_label (pcdelay))) fprintf (runtime.sim.fprof, "+%08X %08lX %08X %s\n", runtime.sim.cycles, pc + 8, pcdelay, tmp->name); else fprintf (runtime.sim.fprof, "+%08X %08X %08X @%08X\n", runtime.sim.cycles, pc + 8, pcdelay, pcdelay); } } INSTRUCTION (l_jalr) { IFF (config.cpu.dependstats) current->func_unit = it_jump; pcdelay = PARAM0; set_reg32(LINK_REGNO, pc + 8); next_delay_insn = 1; } INSTRUCTION (l_jr) { IFF (config.cpu.dependstats) current->func_unit = it_jump; pcdelay = PARAM0; next_delay_insn = 1; if (config.sim.profile) fprintf (runtime.sim.fprof, "-%08X %08X\n", runtime.sim.cycles, pcdelay); } INSTRUCTION (l_rfe) { IFF (config.cpu.dependstats) current->func_unit = it_exception; pcnext = mfspr(SPR_EPCR_BASE); mtspr(SPR_SR, mfspr(SPR_ESR_BASE)); } INSTRUCTION (l_nop) { unsigned long stackaddr; int k = PARAM0; IFF (config.cpu.dependstats) current->func_unit = it_nop; switch (k) { case NOP_NOP: break; case NOP_EXIT: PRINTF("exit(%d)\n", evalsim_reg32 (3)); fprintf(stderr, "@reset : cycles %lld, insn #%lld\n", runtime.sim.reset_cycles, runtime.cpu.reset_instructions); fprintf(stderr, "@exit : cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions); fprintf(stderr, " diff : cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.sim.reset_cycles, runtime.cpu.instructions - runtime.cpu.reset_instructions); if (config.debug.gdb_enabled) set_stall_state (1); else runtime.sim.cont_run = 0; break; case NOP_CNT_RESET: PRINTF("****************** counters reset ******************\n"); PRINTF("cycles %lld, insn #%lld\n", runtime.sim.cycles, runtime.cpu.instructions); PRINTF("****************** counters reset ******************\n"); runtime.sim.reset_cycles = runtime.sim.cycles; runtime.cpu.reset_instructions = runtime.cpu.instructions; break; case NOP_PRINTF: stackaddr = evalsim_reg32(4); simprintf(stackaddr, evalsim_reg32(3)); debug(5, "simprintf %x\n", stackaddr); break; case NOP_REPORT: PRINTF("report(0x%x);\n", evalsim_reg32(3)); default: if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST) PRINTF("report %i (0x%x);\n", k - NOP_REPORT_FIRST, evalsim_reg32(3)); break; } } INSTRUCTION (l_sfeq) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = PARAM0 == PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfne) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = PARAM0 != PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgts) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (signed)PARAM0 > (signed)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfges) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (signed)PARAM0 >= (signed)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sflts) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (signed)PARAM0 < (signed)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfles) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (signed)PARAM0 <= (signed)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgtu) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (unsigned)PARAM0 > (unsigned)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgeu) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (unsigned)PARAM0 >= (unsigned)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfltu) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (unsigned)PARAM0 < (unsigned)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfleu) { IFF (config.cpu.dependstats) current->func_unit = it_compare; flag = (unsigned)PARAM0 <= (unsigned)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_extbs) { unsigned char x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((signed long)x); } INSTRUCTION (l_extbz) { unsigned char x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((unsigned long)x); } INSTRUCTION (l_exths) { unsigned short x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((signed long)x); } INSTRUCTION (l_exthz) { unsigned short x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((unsigned long)x); } INSTRUCTION (l_extws) { unsigned int x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((signed long)x); } INSTRUCTION (l_extwz) { unsigned int x; IFF (config.cpu.dependstats) current->func_unit = it_move; x = PARAM1; SET_PARAM0((unsigned long)x); } INSTRUCTION (l_mtspr) { unsigned long regno = PARAM0 + PARAM2; unsigned long value = PARAM1; if (runtime.sim.fspr_log) { fprintf(runtime.sim.fspr_log, "Write to SPR : [%08lX] <- [%08lX]\n", regno, value); } IFF (config.cpu.dependstats) current->func_unit = it_move; if (mfspr(SPR_SR) & SPR_SR_SM) mtspr(regno, value); else { PRINTF("WARNING: trying to write SPR while SR[SUPV] is cleared.\n"); runtime.sim.cont_run = 0; } } INSTRUCTION (l_mfspr) { unsigned long regno = PARAM1 + PARAM2; unsigned long value = mfspr(regno); if (runtime.sim.fspr_log) { fprintf(runtime.sim.fspr_log, "Read from SPR : [%08lX] -> [%08lX]\n", regno, value); } IFF (config.cpu.dependstats) current->func_unit = it_move; if (mfspr(SPR_SR) & SPR_SR_SM) SET_PARAM0(value); else { SET_PARAM0(0); PRINTF("WARNING: trying to read SPR while SR[SUPV] is cleared.\n"); runtime.sim.cont_run = 0; } } INSTRUCTION (l_sys) { except_handle(EXCEPT_SYSCALL, mfspr(SPR_EEAR_BASE)); } INSTRUCTION (l_trap) { /* TODO: some SR related code here! */ except_handle(EXCEPT_TRAP, mfspr(SPR_EEAR_BASE)); } INSTRUCTION (l_mac) { sprword lo, hi; LONGEST l; long x, y; IFF (config.cpu.dependstats) current->func_unit = it_mac; lo = mfspr (SPR_MACLO); hi = mfspr (SPR_MACHI); x = PARAM0; y = PARAM1; PRINTF ("[%08x,%08x]\t", (unsigned long)(x), (unsigned long)(y)); l = (ULONGEST)lo | ((LONGEST)hi << 32); l += (LONGEST) x * (LONGEST) y; /* This implementation is very fast - it needs only one cycle for mac. */ lo = ((ULONGEST)l) & 0xFFFFFFFF; hi = ((LONGEST)l) >> 32; mtspr (SPR_MACLO, lo); mtspr (SPR_MACHI, hi); PRINTF ("(%08lx,%08lx)\n", hi, lo); } INSTRUCTION (l_msb) { sprword lo, hi; LONGEST l; long x, y; IFF (config.cpu.dependstats) current->func_unit = it_mac; lo = mfspr (SPR_MACLO); hi = mfspr (SPR_MACHI); x = PARAM0; y = PARAM1; PRINTF ("[%08x,%08x]\t", (unsigned long)(x), (unsigned long)(y)); l = (ULONGEST)lo | ((LONGEST)hi << 32); l -= x * y; /* This implementation is very fast - it needs only one cycle for msb. */ lo = ((ULONGEST)l) & 0xFFFFFFFF; hi = ((LONGEST)l) >> 32; mtspr (SPR_MACLO, lo); mtspr (SPR_MACHI, hi); PRINTF ("(%08lx,%08lx)\n", hi, lo); } INSTRUCTION (l_macrc) { sprword lo, hi; LONGEST l; IFF (config.cpu.dependstats) current->func_unit = it_mac; /* No need for synchronization here -- all MAC instructions are 1 cycle long. */ lo = mfspr (SPR_MACLO); hi = mfspr (SPR_MACHI); l = (ULONGEST) lo | ((LONGEST)hi << 32); l >>= 28; //PRINTF ("<%08x>\n", (unsigned long)l); SET_PARAM0((long)l); mtspr (SPR_MACLO, 0); mtspr (SPR_MACHI, 0); } INSTRUCTION (l_cmov) { IFF (config.cpu.dependstats) current->func_unit = it_move; SET_PARAM0(flag ? PARAM1 : PARAM2); } INSTRUCTION (l_ff1) { IFF (config.cpu.dependstats) current->func_unit = it_arith; SET_PARAM0(ffs(PARAM1)); } /******* Floating point instructions *******/ /* Single precision */ INSTRUCTION (lf_add_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0((machword)((float)PARAM1 + (float)PARAM2)); } INSTRUCTION (lf_div_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0((machword)((float)PARAM1 / (float)PARAM2)); } INSTRUCTION (lf_ftoi_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; // set_operand32(0, freg[get_operand(1)], &breakpoint); } INSTRUCTION (lf_itof_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; // freg[get_operand(0)] = eval_operand32(1, &breakpoint); } INSTRUCTION (lf_madd_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0((machword)((float)PARAM0 + (float)PARAM1 * (float)PARAM2)); } INSTRUCTION (lf_mul_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0((machword)((float)PARAM1 * (float)PARAM2)); } INSTRUCTION (lf_rem_s) { float temp = (float)PARAM1 / (float)PARAM2; IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0(temp - (machword)temp); } INSTRUCTION (lf_sfeq_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 == (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfge_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 >= (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfgt_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 > (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfle_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 <= (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sflt_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 < (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfne_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; flag = (float)PARAM0 != (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sub_s) { IFF (config.cpu.dependstats) current->func_unit = it_float; SET_PARAM0((machword)((float)PARAM1 - (float)PARAM2)); } /******* Custom instructions *******/ INSTRUCTION (l_cust1) { /*int destr = current->insn >> 21; int src1r = current->insn >> 15; int src2r = current->insn >> 9;*/ } INSTRUCTION (l_cust2) { } INSTRUCTION (l_cust3) { } INSTRUCTION (l_cust4) { }
Go to most recent revision | Compare with Previous | Blame | View Log