URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [nog_patch_60/] [or1ksim/] [cpu/] [or32/] [insnset.c] - Rev 1438
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) { orreg_t temp1, temp2, temp3; int8_t temp4; temp2 = (orreg_t)PARAM2; temp3 = (orreg_t)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 ((uorreg_t) temp1 < (uorreg_t) 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) { orreg_t temp1, temp2, temp3; int8_t temp4; temp2 = (orreg_t)PARAM2; temp3 = (orreg_t)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 ((uorreg_t) temp1 < (uorreg_t) 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; if (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; if (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; if (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) { uint32_t val; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem32(PARAM1, &breakpoint); /* If eval operand produced exception don't set anything */ if (!except_pending) SET_PARAM0(val); } INSTRUCTION (l_lbs) { int8_t val; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem8(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!except_pending) SET_PARAM0(val); } INSTRUCTION (l_lbz) { uint8_t val; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem8(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!except_pending) SET_PARAM0(val); } INSTRUCTION (l_lhs) { int16_t val; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem16(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!except_pending) SET_PARAM0(val); } INSTRUCTION (l_lhz) { uint16_t val; if (config.cpu.sbuf_len) sbuf_load (); val = eval_mem16(PARAM1, &breakpoint); /* If eval opreand produced exception don't set anything */ if (!except_pending) SET_PARAM0(val); } INSTRUCTION (l_movhi) { SET_PARAM0(PARAM1 << 16); } INSTRUCTION (l_and) { uorreg_t temp1; 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) { uorreg_t temp1; temp1 = PARAM1 | PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_xor) { uorreg_t temp1; temp1 = PARAM1 ^ PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_sub) { orreg_t temp1; temp1 = (orreg_t)PARAM1 - (orreg_t)PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); } /*int mcount = 0;*/ INSTRUCTION (l_mul) { orreg_t temp1; temp1 = (orreg_t)PARAM1 * (orreg_t)PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /*if (!(mcount++ & 1023)) { PRINTF ("[%i]\n",mcount); }*/ } INSTRUCTION (l_div) { orreg_t temp3, temp2, temp1; temp3 = PARAM2; temp2 = PARAM1; if (temp3) temp1 = temp2 / temp3; else { except_handle(EXCEPT_ILLEGAL, cpu_state.pc); return; } set_ov_flag (temp1); SET_PARAM0(temp1); } INSTRUCTION (l_divu) { uorreg_t temp3, temp2, temp1; temp3 = PARAM2; temp2 = PARAM1; if (temp3) temp1 = temp2 / temp3; else { except_handle(EXCEPT_ILLEGAL, cpu_state.pc); return; } set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 16; */ } INSTRUCTION (l_sll) { uorreg_t temp1; temp1 = PARAM1 << PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_sra) { orreg_t temp1; temp1 = (orreg_t)PARAM1 >> PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_srl) { uorreg_t temp1; temp1 = PARAM1 >> PARAM2; set_ov_flag (temp1); SET_PARAM0(temp1); /* runtime.sim.cycles += 2; */ } INSTRUCTION (l_bf) { if (config.bpb.enabled) { int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0; or1k_mstats.bf[flag][fwd]++; bpb_update(current->insn_addr, flag); } if (flag) { cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; btic_update(pcnext); next_delay_insn = 1; } else { btic_update(cpu_state.pc); } } INSTRUCTION (l_bnf) { if (config.bpb.enabled) { int fwd = (PARAM0 >= cpu_state.pc) ? 1 : 0; or1k_mstats.bnf[!flag][fwd]++; bpb_update(current->insn_addr, flag == 0); } if (flag == 0) { cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; btic_update(pcnext); next_delay_insn = 1; } else { btic_update(cpu_state.pc); } } INSTRUCTION (l_j) { cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; next_delay_insn = 1; } INSTRUCTION (l_jal) { cpu_state.pc_delay = cpu_state.pc + (orreg_t)PARAM0 * 4; set_reg(LINK_REGNO, cpu_state.pc + 8); next_delay_insn = 1; if (config.sim.profile) { struct label_entry *tmp; if (verify_memoryarea(cpu_state.pc_delay) && (tmp = get_label (cpu_state.pc_delay))) fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" %s\n", runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay, tmp->name); else fprintf (runtime.sim.fprof, "+%08llX %"PRIxADDR" %"PRIxADDR" @%"PRIxADDR"\n", runtime.sim.cycles, cpu_state.pc + 8, cpu_state.pc_delay, cpu_state.pc_delay); } } INSTRUCTION (l_jalr) { cpu_state.pc_delay = PARAM0; set_reg(LINK_REGNO, cpu_state.pc + 8); next_delay_insn = 1; } INSTRUCTION (l_jr) { cpu_state.pc_delay = PARAM0; next_delay_insn = 1; if (config.sim.profile) fprintf (runtime.sim.fprof, "-%08llX %"PRIxADDR"\n", runtime.sim.cycles, cpu_state.pc_delay); } INSTRUCTION (l_rfe) { pcnext = mfspr(SPR_EPCR_BASE); mtspr(SPR_SR, mfspr(SPR_ESR_BASE)); } INSTRUCTION (l_nop) { oraddr_t stackaddr; uint32_t k = PARAM0; switch (k) { case NOP_NOP: break; case NOP_EXIT: PRINTF("exit(%"PRIdREG")\n", evalsim_reg (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_reg(4); simprintf(stackaddr, evalsim_reg(3)); debug(5, "simprintf %x\n", stackaddr); break; case NOP_REPORT: PRINTF("report(0x%"PRIxREG");\n", evalsim_reg(3)); default: if (k >= NOP_REPORT_FIRST && k <= NOP_REPORT_LAST) PRINTF("report %i (0x%"PRIxREG");\n", k - NOP_REPORT_FIRST, evalsim_reg(3)); break; } } INSTRUCTION (l_sfeq) { flag = PARAM0 == PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfne) { flag = PARAM0 != PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgts) { flag = (orreg_t)PARAM0 > (orreg_t)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfges) { flag = (orreg_t)PARAM0 >= (orreg_t)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sflts) { flag = (orreg_t)PARAM0 < (orreg_t)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfles) { flag = (orreg_t)PARAM0 <= (orreg_t)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgtu) { flag = PARAM0 > PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfgeu) { flag = PARAM0 >= PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfltu) { flag = PARAM0 < PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_sfleu) { flag = PARAM0 <= PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (l_extbs) { int8_t x; x = PARAM1; SET_PARAM0((orreg_t)x); } INSTRUCTION (l_extbz) { uint8_t x; x = PARAM1; SET_PARAM0((uorreg_t)x); } INSTRUCTION (l_exths) { int16_t x; x = PARAM1; SET_PARAM0((orreg_t)x); } INSTRUCTION (l_exthz) { uint16_t x; x = PARAM1; SET_PARAM0((uorreg_t)x); } INSTRUCTION (l_extws) { int32_t x; x = PARAM1; SET_PARAM0((orreg_t)x); } INSTRUCTION (l_extwz) { uint32_t x; x = PARAM1; SET_PARAM0((uorreg_t)x); } INSTRUCTION (l_mtspr) { uint16_t regno = PARAM0 + PARAM2; uorreg_t value = PARAM1; if (runtime.sim.fspr_log) { fprintf(runtime.sim.fspr_log, "Write to SPR : [%08"PRIx16"] <- [%08"PRIx32"]\n", regno, value); } 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) { uint16_t regno = PARAM1 + PARAM2; uorreg_t value = mfspr(regno); if (runtime.sim.fspr_log) { fprintf(runtime.sim.fspr_log, "Read from SPR : [%08"PRIx16"] -> [%08"PRIx32"]\n", regno, value); } 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; orreg_t x, y; lo = mfspr (SPR_MACLO); hi = mfspr (SPR_MACHI); x = PARAM0; y = PARAM1; PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, 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; orreg_t x, y; lo = mfspr (SPR_MACLO); hi = mfspr (SPR_MACHI); x = PARAM0; y = PARAM1; PRINTF ("[%"PRIxREG",%"PRIxREG"]\t", x, 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; /* 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((orreg_t)l); mtspr (SPR_MACLO, 0); mtspr (SPR_MACHI, 0); } INSTRUCTION (l_cmov) { SET_PARAM0(flag ? PARAM1 : PARAM2); } INSTRUCTION (l_ff1) { SET_PARAM0(ffs(PARAM1)); } /******* Floating point instructions *******/ /* Single precision */ INSTRUCTION (lf_add_s) { SET_PARAM0((float)PARAM1 + (float)PARAM2); } INSTRUCTION (lf_div_s) { SET_PARAM0((float)PARAM1 / (float)PARAM2); } INSTRUCTION (lf_ftoi_s) { // set_operand32(0, freg[get_operand(1)], &breakpoint); } INSTRUCTION (lf_itof_s) { // freg[get_operand(0)] = eval_operand32(1, &breakpoint); } INSTRUCTION (lf_madd_s) { SET_PARAM0((float)PARAM0 + (float)PARAM1 * (float)PARAM2); } INSTRUCTION (lf_mul_s) { SET_PARAM0((float)PARAM1 * (float)PARAM2); } INSTRUCTION (lf_rem_s) { float temp = (float)PARAM1 / (float)PARAM2; SET_PARAM0(temp - (uint32_t)temp); } INSTRUCTION (lf_sfeq_s) { flag = (float)PARAM0 == (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfge_s) { flag = (float)PARAM0 >= (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfgt_s) { flag = (float)PARAM0 > (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfle_s) { flag = (float)PARAM0 <= (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sflt_s) { flag = (float)PARAM0 < (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sfne_s) { flag = (float)PARAM0 != (float)PARAM1; setsprbits(SPR_SR, SPR_SR_F, flag); } INSTRUCTION (lf_sub_s) { SET_PARAM0((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