+// check_mult_hilo:
+//
+// Check for restriction (3) above (for ISAs/processors that have it)
+// for MULT ops, and record timestamps for restriction (1) above.
+//
+:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
+*mipsI:
+*mipsII:
+*mipsIII:
+*vr4100:
+*vr5000:
+{
+ int64_t time = sim_events_time (SD);
+ int ok = (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP"));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
+:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
+*mipsIV:
+*mipsV:
+{
+ int64_t time = sim_events_time (SD);
+ int ok = (! MIPS_MACH_HAS_MULT_HILO_HAZARD (SD)
+ || (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP")));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
+:function:::int:check_mult_hilo:hilo_history *hi, hilo_history *lo
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*mips64r6:
+*r3900:
+*micromips32:
+*micromips64:
+{
+ /* FIXME: could record the fact that a stall occured if we want */
+ int64_t time = sim_events_time (SD);
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return 1;
+}
+
+
+// check_div_hilo:
+//
+// Check for restriction (3) above (for ISAs/processors that have it)
+// for DIV ops, and record timestamps for restriction (1) above.
+//
+:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
+*mipsI:
+*mipsII:
+*mipsIII:
+*vr4100:
+*vr5000:
+*r3900:
+{
+ int64_t time = sim_events_time (SD);
+ int ok = (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP"));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
+:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
+*mipsIV:
+*mipsV:
+{
+ int64_t time = sim_events_time (SD);
+ int ok = (! MIPS_MACH_HAS_DIV_HILO_HAZARD (SD)
+ || (check_mf_cycles (SD_, hi, time, "OP")
+ && check_mf_cycles (SD_, lo, time, "OP")));
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return ok;
+}
+
+:function:::int:check_div_hilo:hilo_history *hi, hilo_history *lo
+*mips32:
+*mips32r2:
+*mips32r6:
+*mips64:
+*mips64r2:
+*micromips32:
+*micromips64:
+*mips64r6:
+{
+ int64_t time = sim_events_time (SD);
+ hi->op.timestamp = time;
+ lo->op.timestamp = time;
+ hi->op.cia = CIA;
+ lo->op.cia = CIA;
+ return 1;
+}
+
+
+// Helper:
+//
+// Check that the 64-bit instruction can currently be used, and signal
+// a ReservedInstruction exception if not.
+//
+
+:function:::void:check_u64:instruction_word insn
+*mipsIII:
+*mipsIV:
+*mipsV:
+*vr4100:
+*vr5000:
+*vr5400:
+*vr5500:
+*r3900:
+{
+ // The check should be similar to mips64 for any with PX/UX bit equivalents.
+}
+
+:function:::void:check_u64:instruction_word insn
+*mips16e:
+*mips64:
+*mips64r2:
+*mips32:
+*mips32r2:
+*mips32r6:
+*micromips64:
+*micromips32:
+*mips64r6:
+{
+#if 0 /* XXX FIXME: enable this only after some additional testing. */
+ if (UserMode && (SR & (status_UX|status_PX)) == 0)
+ SignalException (ReservedInstruction, insn);
+#endif
+}
+
+
+
+//
+// MIPS Architecture:
+//
+// CPU Instruction Set (mipsI - mipsV, mips32/r2, mips64/r2)
+//
+
+
+:function:::void:do_add:int rs, int rt, int rd
+{
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ {
+ ALU32_BEGIN (GPR[rs]);
+ ALU32_ADD (GPR[rt]);
+ ALU32_END (GPR[rd]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_addi:int rs, int rt, uint16_t immediate
+{
+ if (NotWordValue (GPR[rs]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate));
+ {
+ ALU32_BEGIN (GPR[rs]);
+ ALU32_ADD (EXTEND16 (immediate));
+ ALU32_END (GPR[rt]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_andi:int rs, int rt, unsigned int immediate
+{
+ TRACE_ALU_INPUT2 (GPR[rs], immediate);
+ GPR[rt] = GPR[rs] & immediate;
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_dadd:int rd, int rs, int rt
+{
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ {
+ ALU64_BEGIN (GPR[rs]);
+ ALU64_ADD (GPR[rt]);
+ ALU64_END (GPR[rd]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_daddi:int rt, int rs, int immediate
+{
+ TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate));
+ {
+ ALU64_BEGIN (GPR[rs]);
+ ALU64_ADD (EXTEND16 (immediate));
+ ALU64_END (GPR[rt]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_dsll32:int rd, int rt, int shift
+{
+ int s = 32 + shift;
+ TRACE_ALU_INPUT2 (GPR[rt], s);
+ GPR[rd] = GPR[rt] << s;
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dsra32:int rd, int rt, int shift
+{
+ int s = 32 + shift;
+ TRACE_ALU_INPUT2 (GPR[rt], s);
+ GPR[rd] = ((int64_t) GPR[rt]) >> s;
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dsrl32:int rd, int rt, int shift
+{
+ int s = 32 + shift;
+ TRACE_ALU_INPUT2 (GPR[rt], s);
+ GPR[rd] = (uint64_t) GPR[rt] >> s;
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dsub:int rd, int rs, int rt
+{
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ {
+ ALU64_BEGIN (GPR[rs]);
+ ALU64_SUB (GPR[rt]);
+ ALU64_END (GPR[rd]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_break:address_word instruction_0
+{
+ /* Check for some break instruction which are reserved for use by the
+ simulator. */
+ unsigned int break_code = instruction_0 & HALT_INSTRUCTION_MASK;
+ if (break_code == (HALT_INSTRUCTION & HALT_INSTRUCTION_MASK) ||
+ break_code == (HALT_INSTRUCTION2 & HALT_INSTRUCTION_MASK))
+ {
+ sim_engine_halt (SD, CPU, NULL, cia,
+ sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
+ }
+ else if (break_code == (BREAKPOINT_INSTRUCTION & HALT_INSTRUCTION_MASK) ||
+ break_code == (BREAKPOINT_INSTRUCTION2 & HALT_INSTRUCTION_MASK))
+ {
+ if (STATE & simDELAYSLOT)
+ PC = cia - 4; /* reference the branch instruction */
+ else
+ PC = cia;
+ SignalException (BreakPoint, instruction_0);
+ }
+
+ else
+ {
+ /* If we get this far, we're not an instruction reserved by the sim. Raise
+ the exception. */
+ SignalException (BreakPoint, instruction_0);
+ }
+}
+
+:function:::void:do_break16:address_word instruction_0
+{
+ if (STATE & simDELAYSLOT)
+ PC = cia - 2; /* reference the branch instruction */
+ else
+ PC = cia;
+ SignalException (BreakPoint, instruction_0);
+}
+
+:function:::void:do_clo:int rd, int rs
+{
+ uint32_t temp = GPR[rs];
+ uint32_t i, mask;
+ if (NotWordValue (GPR[rs]))
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[rs]);
+ for (mask = ((uint32_t)1<<31), i = 0; i < 32; ++i)
+ {
+ if ((temp & mask) == 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[rd] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_clz:int rd, int rs
+{
+ uint32_t temp = GPR[rs];
+ uint32_t i, mask;
+ if (NotWordValue (GPR[rs]))
+ Unpredictable ();
+ TRACE_ALU_INPUT1 (GPR[rs]);
+ for (mask = ((uint32_t)1<<31), i = 0; i < 32; ++i)
+ {
+ if ((temp & mask) != 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[rd] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dclo:int rd, int rs
+{
+ uint64_t temp = GPR[rs];
+ uint32_t i;
+ uint64_t mask;
+ TRACE_ALU_INPUT1 (GPR[rs]);
+ for (mask = ((uint64_t)1<<63), i = 0; i < 64; ++i)
+ {
+ if ((temp & mask) == 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[rd] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dclz:int rd, int rs
+{
+ uint64_t temp = GPR[rs];
+ uint32_t i;
+ uint64_t mask;
+ TRACE_ALU_INPUT1 (GPR[rs]);
+ for (mask = ((uint64_t)1<<63), i = 0; i < 64; ++i)
+ {
+ if ((temp & mask) != 0)
+ break;
+ mask >>= 1;
+ }
+ GPR[rd] = EXTEND32 (i);
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_lb:int rt, int offset, int base
+{
+ GPR[rt] = EXTEND8 (do_load (SD_, AccessLength_BYTE, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lh:int rt, int offset, int base
+{
+ GPR[rt] = EXTEND16 (do_load (SD_, AccessLength_HALFWORD, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lwr:int rt, int offset, int base
+{
+ GPR[rt] = EXTEND32 (do_load_right (SD_, AccessLength_WORD, GPR[base],
+ EXTEND16 (offset), GPR[rt]));
+}
+
+:function:::void:do_lwl:int rt, int offset, int base
+{
+ GPR[rt] = EXTEND32 (do_load_left (SD_, AccessLength_WORD, GPR[base],
+ EXTEND16 (offset), GPR[rt]));
+}
+
+:function:::void:do_lwc:int num, int rt, int offset, int base
+{
+ COP_LW (num, rt, do_load (SD_, AccessLength_WORD, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lw:int rt, int offset, int base
+{
+ GPR[rt] = EXTEND32 (do_load (SD_, AccessLength_WORD, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lwu:int rt, int offset, int base, address_word instruction_0
+{
+ check_u64 (SD_, instruction_0);
+ GPR[rt] = do_load (SD_, AccessLength_WORD, GPR[base], EXTEND16 (offset));
+}
+
+:function:::void:do_lhu:int rt, int offset, int base
+{
+ GPR[rt] = do_load (SD_, AccessLength_HALFWORD, GPR[base], EXTEND16 (offset));
+}
+
+:function:::void:do_ldc:int num, int rt, int offset, int base
+{
+ COP_LD (num, rt, do_load (SD_, AccessLength_DOUBLEWORD, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lbu:int rt, int offset, int base
+{
+ GPR[rt] = do_load (SD_, AccessLength_BYTE, GPR[base], EXTEND16 (offset));
+}
+
+:function:::void:do_ll:int rt, int insn_offset, int basereg
+{
+ address_word base = GPR[basereg];
+ address_word offset = EXTEND16 (insn_offset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+ if ((vaddr & 3) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, read_transfer,
+ sim_core_unaligned_signal);
+ }
+ else
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ unsigned int shift = 2;
+ unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);
+ unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));
+ LoadMemory (&memval, &memval1, AccessLength_WORD, paddr, vaddr,
+ isDATA, isREAL);
+ byte = ((vaddr & mask) ^ (bigend << shift));
+ GPR[rt] = EXTEND32 (memval >> (8 * byte));
+ LLBIT = 1;
+ }
+ }
+}
+
+:function:::void:do_lld:int rt, int roffset, int rbase
+{
+ address_word base = GPR[rbase];
+ address_word offset = EXTEND16 (roffset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+
+ if ((vaddr & 7) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, read_transfer,
+ sim_core_unaligned_signal);
+ }
+ else
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ LoadMemory (&memval, &memval1, AccessLength_DOUBLEWORD, paddr, vaddr,
+ isDATA, isREAL);
+ GPR[rt] = memval;
+ LLBIT = 1;
+ }
+ }
+}
+
+:function:::void:do_lui:int rt, int immediate
+{
+ TRACE_ALU_INPUT1 (immediate);
+ GPR[rt] = EXTEND32 (immediate << 16);
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_madd:int rs, int rt
+{
+ int64_t temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ + ((int64_t) EXTEND32 (GPR[rt]) * (int64_t) EXTEND32 (GPR[rs])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_dsp_madd:int ac, int rs, int rt
+{
+ int64_t temp;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac)))
+ + ((int64_t) EXTEND32 (GPR[rt]) * (int64_t) EXTEND32 (GPR[rs])));
+ DSPLO(ac) = EXTEND32 (temp);
+ DSPHI(ac) = EXTEND32 (VH4_8 (temp));
+ if (ac == 0)
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_maddu:int rs, int rt
+{
+ uint64_t temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ + ((uint64_t) VL4_8 (GPR[rs]) * (uint64_t) VL4_8 (GPR[rt])));
+ ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_dsp_maddu:int ac, int rs, int rt
+{
+ uint64_t temp;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac)))
+ + ((uint64_t) VL4_8 (GPR[rs]) * (uint64_t) VL4_8 (GPR[rt])));
+ if (ac == 0)
+ ACX += U8_4 (VL4_8 (HI), VL4_8 (LO)) < temp; /* SmartMIPS */
+ DSPLO(ac) = EXTEND32 (temp);
+ DSPHI(ac) = EXTEND32 (VH4_8 (temp));
+ if (ac == 0)
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_dsp_mfhi:int ac, int rd
+{
+ if (ac == 0)
+ do_mfhi (SD_, rd);
+ else
+ GPR[rd] = DSPHI(ac);
+}
+
+:function:::void:do_dsp_mflo:int ac, int rd
+{
+ if (ac == 0)
+ do_mflo (SD_, rd);
+ else
+ GPR[rd] = DSPLO(ac);
+}
+
+:function:::void:do_movn:int rd, int rs, int rt
+{
+ if (GPR[rt] != 0)
+ {
+ GPR[rd] = GPR[rs];
+ TRACE_ALU_RESULT (GPR[rd]);
+ }
+}
+
+:function:::void:do_movz:int rd, int rs, int rt
+{
+ if (GPR[rt] == 0)
+ {
+ GPR[rd] = GPR[rs];
+ TRACE_ALU_RESULT (GPR[rd]);
+ }
+}
+
+:function:::void:do_msub:int rs, int rt
+{
+ int64_t temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ - ((int64_t) EXTEND32 (GPR[rt]) * (int64_t) EXTEND32 (GPR[rs])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_dsp_msub:int ac, int rs, int rt
+{
+ int64_t temp;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac)))
+ - ((int64_t) EXTEND32 (GPR[rt]) * (int64_t) EXTEND32 (GPR[rs])));
+ DSPLO(ac) = EXTEND32 (temp);
+ DSPHI(ac) = EXTEND32 (VH4_8 (temp));
+ if (ac == 0)
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_msubu:int rs, int rt
+{
+ uint64_t temp;
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (HI), VL4_8 (LO))
+ - ((uint64_t) VL4_8 (GPR[rs]) * (uint64_t) VL4_8 (GPR[rt])));
+ LO = EXTEND32 (temp);
+ HI = EXTEND32 (VH4_8 (temp));
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_dsp_msubu:int ac, int rs, int rt
+{
+ uint64_t temp;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ temp = (U8_4 (VL4_8 (DSPHI(ac)), VL4_8 (DSPLO(ac)))
+ - ((uint64_t) VL4_8 (GPR[rs]) * (uint64_t) VL4_8 (GPR[rt])));
+ DSPLO(ac) = EXTEND32 (temp);
+ DSPHI(ac) = EXTEND32 (VH4_8 (temp));
+ if (ac == 0)
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_mthi:int rs
+{
+ check_mt_hilo (SD_, HIHISTORY);
+ HI = GPR[rs];
+}
+
+:function:::void:do_dsp_mthi:int ac, int rs
+{
+ if (ac == 0)
+ check_mt_hilo (SD_, HIHISTORY);
+ DSPHI(ac) = GPR[rs];
+}
+
+:function:::void:do_mtlo:int rs
+{
+ check_mt_hilo (SD_, LOHISTORY);
+ LO = GPR[rs];
+}
+
+:function:::void:do_dsp_mtlo:int ac, int rs
+{
+ if (ac == 0)
+ check_mt_hilo (SD_, LOHISTORY);
+ DSPLO(ac) = GPR[rs];
+}
+
+:function:::void:do_mul:int rd, int rs, int rt
+{
+ int64_t prod;
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = (((int64_t)(int32_t) GPR[rs])
+ * ((int64_t)(int32_t) GPR[rt]));
+ GPR[rd] = EXTEND32 (VL4_8 (prod));
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_dsp_mult:int ac, int rs, int rt
+{
+ int64_t prod;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = ((int64_t)(int32_t) GPR[rs])
+ * ((int64_t)(int32_t) GPR[rt]);
+ DSPLO(ac) = EXTEND32 (VL4_8 (prod));
+ DSPHI(ac) = EXTEND32 (VH4_8 (prod));
+ if (ac == 0)
+ {
+ ACX = 0; /* SmartMIPS */
+ TRACE_ALU_RESULT2 (HI, LO);
+ }
+}
+
+:function:::void:do_dsp_multu:int ac, int rs, int rt
+{
+ uint64_t prod;
+ if (ac == 0)
+ check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ prod = ((uint64_t)(uint32_t) GPR[rs])
+ * ((uint64_t)(uint32_t) GPR[rt]);
+ DSPLO(ac) = EXTEND32 (VL4_8 (prod));
+ DSPHI(ac) = EXTEND32 (VH4_8 (prod));
+ if (ac == 0)
+ TRACE_ALU_RESULT2 (HI, LO);
+}
+
+:function:::void:do_pref:int hint, int insn_offset, int insn_base
+{
+ address_word base = GPR[insn_base];
+ address_word offset = EXTEND16 (insn_offset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+ /* Prefetch (paddr, vaddr, isDATA, hint); */
+ }
+}
+
+:function:::void:do_sc:int rt, int offsetarg, int basereg, address_word instruction_0, int store_ll_bit
+{
+ uint32_t instruction = instruction_0;
+ address_word base = GPR[basereg];
+ address_word offset = EXTEND16 (offsetarg);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+
+ if ((vaddr & 3) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 4, vaddr, write_transfer,
+ sim_core_unaligned_signal);
+ }
+ else
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ uint64_t mask = (WITH_TARGET_WORD_BITSIZE == 64 ? 0x7 : 0x3);
+ address_word reverseendian =
+ (ReverseEndian ? (mask ^ AccessLength_WORD) : 0);
+ address_word bigendiancpu =
+ (BigEndianCPU ? (mask ^ AccessLength_WORD) : 0);
+ unsigned int byte;
+ paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverseendian));
+ byte = ((vaddr & mask) ^ bigendiancpu);
+ memval = ((uint64_t) GPR[rt] << (8 * byte));
+ if (LLBIT)
+ StoreMemory (AccessLength_WORD, memval, memval1, paddr, vaddr,
+ isREAL);
+ if (store_ll_bit)
+ GPR[rt] = LLBIT;
+ }
+ }
+}
+
+:function:::void:do_scd:int rt, int roffset, int rbase, int store_ll_bit
+{
+ address_word base = GPR[rbase];
+ address_word offset = EXTEND16 (roffset);
+ {
+ address_word vaddr = loadstore_ea (SD_, base, offset);
+ address_word paddr = vaddr;
+
+ if ((vaddr & 7) != 0)
+ {
+ SIM_CORE_SIGNAL (SD, CPU, cia, read_map, 8, vaddr, write_transfer,
+ sim_core_unaligned_signal);
+ }
+ else
+ {
+ uint64_t memval = 0;
+ uint64_t memval1 = 0;
+ memval = GPR[rt];
+ if (LLBIT)
+ StoreMemory (AccessLength_DOUBLEWORD, memval, memval1, paddr, vaddr,
+ isREAL);
+ if (store_ll_bit)
+ GPR[rt] = LLBIT;
+ }
+ }
+}
+
+:function:::void:do_sub:int rs, int rt, int rd
+{
+ if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt]))
+ Unpredictable ();
+ TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]);
+ {
+ ALU32_BEGIN (GPR[rs]);
+ ALU32_SUB (GPR[rt]);
+ ALU32_END (GPR[rd]); /* This checks for overflow. */
+ }
+ TRACE_ALU_RESULT (GPR[rd]);
+}
+
+:function:::void:do_sw:int rt, int offset, int base
+{
+ do_store (SD_, AccessLength_WORD, GPR[base], EXTEND16 (offset), GPR[rt]);
+}
+
+:function:::void:do_teq:int rs, int rt, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] == (signed_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_teqi:int rs, int immediate, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] == (signed_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tge:int rs, int rt, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] >= (signed_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tgei:int rs, int immediate, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] >= (signed_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tgeiu:int rs, int immediate, address_word instruction_0
+{
+ if ((unsigned_word) GPR[rs] >= (unsigned_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tgeu:int rs ,int rt, address_word instruction_0
+{
+ if ((unsigned_word) GPR[rs] >= (unsigned_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tlt:int rs, int rt, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] < (signed_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tlti:int rs, int immediate, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] < (signed_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tltiu:int rs, int immediate, address_word instruction_0
+{
+ if ((unsigned_word) GPR[rs] < (unsigned_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tltu:int rs, int rt, address_word instruction_0
+{
+ if ((unsigned_word) GPR[rs] < (unsigned_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tne:int rs, int rt, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] != (signed_word) GPR[rt])
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_tnei:int rs, int immediate, address_word instruction_0
+{
+ if ((signed_word) GPR[rs] != (signed_word) EXTEND16 (immediate))
+ SignalException (Trap, instruction_0);
+}
+
+:function:::void:do_abs_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, AbsoluteValue (ValueFPR (fs, fmt), fmt));
+}
+
+:function:::void:do_add_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, Add (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+}
+
+:function:::void:do_alnv_ps:int fd, int fs, int ft, int rs, address_word instruction_0
+{
+ uint64_t fsx;
+ uint64_t ftx;
+ uint64_t fdx;
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ fsx = ValueFPR (fs, fmt_ps);
+ if ((GPR[rs] & 0x3) != 0)
+ Unpredictable ();
+ if ((GPR[rs] & 0x4) == 0)
+ fdx = fsx;
+ else
+ {
+ ftx = ValueFPR (ft, fmt_ps);
+ if (BigEndianCPU)
+ fdx = PackPS (PSLower (fsx), PSUpper (ftx));
+ else
+ fdx = PackPS (PSLower (ftx), PSUpper (fsx));
+ }
+ StoreFPR (fd, fmt_ps, fdx);
+}
+
+:function:::void:do_c_cond_fmt:int cond, int fmt, int cc, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ Compare (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt, cond, cc);
+ TRACE_ALU_RESULT (ValueFCR (31));
+}
+
+:function:::void:do_ceil_fmt:int type, int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, type, Convert (FP_RM_TOPINF, ValueFPR (fs, fmt), fmt,
+ type));
+}
+
+:function:::void:do_cfc1:int rt, int fs
+{
+ check_fpu (SD_);
+ if (fs == 0 || fs == 25 || fs == 26 || fs == 28 || fs == 31)
+ {
+ unsigned_word fcr = ValueFCR (fs);
+ TRACE_ALU_INPUT1 (fcr);
+ GPR[rt] = fcr;
+ }
+ /* else NOP */
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_ctc1:int rt, int fs
+{
+ check_fpu (SD_);
+ TRACE_ALU_INPUT1 (GPR[rt]);
+ if (fs == 25 || fs == 26 || fs == 28 || fs == 31)
+ StoreFCR (fs, GPR[rt]);
+ /* else NOP */
+}
+
+:function:::void:do_cvt_d_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ if ((fmt == fmt_double) | 0)
+ SignalException (ReservedInstruction, instruction_0);
+ StoreFPR (fd, fmt_double, Convert (GETRM (), ValueFPR (fs, fmt), fmt,
+ fmt_double));
+}
+
+:function:::void:do_cvt_l_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ if ((fmt == fmt_long) | ((fmt == fmt_long) || (fmt == fmt_word)))
+ SignalException (ReservedInstruction, instruction_0);
+ StoreFPR (fd, fmt_long, Convert (GETRM (), ValueFPR (fs, fmt), fmt,
+ fmt_long));
+}
+
+:function:::void:do_cvt_ps_s:int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_ps, PackPS (ValueFPR (fs, fmt_single),
+ ValueFPR (ft, fmt_single)));
+}
+
+:function:::void:do_cvt_s_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ if ((fmt == fmt_single) | 0)
+ SignalException (ReservedInstruction, instruction_0);
+ StoreFPR (fd, fmt_single, Convert (GETRM (), ValueFPR (fs, fmt), fmt,
+ fmt_single));
+}
+
+:function:::void:do_cvt_s_pl:int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_single, PSLower (ValueFPR (fs, fmt_ps)));
+}
+
+:function:::void:do_cvt_s_pu:int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_single, PSUpper (ValueFPR (fs, fmt_ps)));
+}
+
+:function:::void:do_cvt_w_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ if ((fmt == fmt_word) | ((fmt == fmt_long) || (fmt == fmt_word)))
+ SignalException (ReservedInstruction, instruction_0);
+ StoreFPR (fd, fmt_word, Convert (GETRM (), ValueFPR (fs, fmt), fmt,
+ fmt_word));
+}
+
+:function:::void:do_div_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ StoreFPR (fd, fmt, Divide (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+}
+
+:function:::void:do_dmfc1b:int rt, int fs
+*mipsIV:
+*mipsV:
+*mips64:
+*mips64r2:
+*mips64r6:
+*vr4100:
+*vr5000:
+*r3900:
+*micromips64:
+{
+ if (SizeFGR () == 64)
+ GPR[rt] = FGR[fs];
+ else if ((fs & 0x1) == 0)
+ GPR[rt] = SET64HI (FGR[fs+1]) | FGR[fs];
+ else
+ GPR[rt] = SET64HI (0xDEADC0DE) | 0xBAD0BAD0;
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_dmtc1b:int rt, int fs
+{
+ if (SizeFGR () == 64)
+ StoreFPR (fs, fmt_uninterpreted_64, GPR[rt]);
+ else if ((fs & 0x1) == 0)
+ StoreFPR (fs, fmt_uninterpreted_64, GPR[rt]);
+ else
+ Unpredictable ();
+}
+
+:function:::void:do_floor_fmt:int type, int fmt, int fd, int fs
+{
+ check_fpu (SD_);
+ StoreFPR (fd, type, Convert (FP_RM_TOMINF, ValueFPR (fs, fmt), fmt,
+ type));
+}
+
+:function:::void:do_luxc1_32:int fd, int rindex, int rbase
+*mips32r2:
+*micromips32:
+{
+ address_word base = GPR[rbase];
+ address_word index = GPR[rindex];
+ address_word vaddr = base + index;
+ check_fpu (SD_);
+ if (SizeFGR () != 64)
+ Unpredictable ();
+ /* Arrange for the bottom 3 bits of (base + index) to be 0. */
+ if ((vaddr & 0x7) != 0)
+ index -= (vaddr & 0x7);
+ COP_LD (1, fd, do_load_double (SD_, base, index));
+}
+
+:function:::void:do_luxc1_64:int fd, int rindex, int rbase
+{
+ address_word base = GPR[rbase];
+ address_word index = GPR[rindex];
+ address_word vaddr = base + index;
+ if (SizeFGR () != 64)
+ Unpredictable ();
+ /* Arrange for the bottom 3 bits of (base + index) to be 0. */
+ if ((vaddr & 0x7) != 0)
+ index -= (vaddr & 0x7);
+ COP_LD (1, fd, do_load (SD_, AccessLength_DOUBLEWORD, base, index));
+
+}
+
+:function:::void:do_lwc1:int ft, int offset, int base
+{
+ check_fpu (SD_);
+ COP_LW (1, ft, do_load (SD_, AccessLength_WORD, GPR[base],
+ EXTEND16 (offset)));
+}
+
+:function:::void:do_lwxc1:int fd, int index, int base, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ COP_LW (1, fd, do_load (SD_, AccessLength_WORD, GPR[base], GPR[index]));
+}
+
+:function:::void:do_madd_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, MultiplyAdd (ValueFPR (fs, fmt), ValueFPR (ft, fmt),
+ ValueFPR (fr, fmt), fmt));
+}
+
+:function:::void:do_mfc1b:int rt, int fs
+{
+ check_fpu (SD_);
+ GPR[rt] = EXTEND32 (FGR[fs]);
+ TRACE_ALU_RESULT (GPR[rt]);
+}
+
+:function:::void:do_mov_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+}
+
+:function:::void:do_movtf:int tf, int rd, int rs, int cc
+{
+ check_fpu (SD_);
+ if (GETFCC(cc) == tf)
+ GPR[rd] = GPR[rs];
+}
+
+:function:::void:do_movtf_fmt:int tf, int fmt, int fd, int fs, int cc
+{
+ check_fpu (SD_);
+ if (fmt != fmt_ps)
+ {
+ if (GETFCC(cc) == tf)
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ else
+ StoreFPR (fd, fmt, ValueFPR (fd, fmt)); /* set fmt */
+ }
+ else
+ {
+ uint64_t fdx;
+ fdx = PackPS (PSUpper (ValueFPR ((GETFCC (cc+1) == tf) ? fs : fd,
+ fmt_ps)),
+ PSLower (ValueFPR ((GETFCC (cc+0) == tf) ? fs : fd,
+ fmt_ps)));
+ StoreFPR (fd, fmt_ps, fdx);
+ }
+}
+
+:function:::void:do_movn_fmt:int fmt, int fd, int fs, int rt
+{
+ check_fpu (SD_);
+ if (GPR[rt] != 0)
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ else
+ StoreFPR (fd, fmt, ValueFPR (fd, fmt));
+}
+
+:function:::void:do_movz_fmt:int fmt, int fd, int fs, int rt
+{
+ check_fpu (SD_);
+ if (GPR[rt] == 0)
+ StoreFPR (fd, fmt, ValueFPR (fs, fmt));
+ else
+ StoreFPR (fd, fmt, ValueFPR (fd, fmt));
+}
+
+:function:::void:do_msub_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, MultiplySub (ValueFPR (fs, fmt), ValueFPR (ft, fmt),
+ ValueFPR (fr, fmt), fmt));
+}
+
+:function:::void:do_mtc1b:int rt, int fs
+{
+ check_fpu (SD_);
+ StoreFPR (fs, fmt_uninterpreted_32, VL4_8 (GPR[rt]));
+}
+
+:function:::void:do_mul_fmt:int fmt, int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, Multiply (ValueFPR (fs, fmt), ValueFPR (ft, fmt), fmt));
+}
+
+:function:::void:do_neg_fmt:int fmt, int fd, int fs, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, Negate (ValueFPR (fs, fmt), fmt));
+}
+
+:function:::void:do_nmadd_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, NegMultiplyAdd (ValueFPR (fs, fmt), ValueFPR (ft, fmt),
+ ValueFPR (fr, fmt), fmt));
+}
+
+:function:::void:do_nmsub_fmt:int fmt, int fd, int fr, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ check_fmt_p (SD_, fmt, instruction_0);
+ StoreFPR (fd, fmt, NegMultiplySub (ValueFPR (fs, fmt), ValueFPR (ft, fmt),
+ ValueFPR (fr, fmt), fmt));
+}
+
+:function:::void:do_pll_ps:int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_ps, PackPS (PSLower (ValueFPR (fs, fmt_ps)),
+ PSLower (ValueFPR (ft, fmt_ps))));
+}
+
+:function:::void:do_plu_ps:int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_ps, PackPS (PSLower (ValueFPR (fs, fmt_ps)),
+ PSUpper (ValueFPR (ft, fmt_ps))));
+}
+
+:function:::void:do_pul_ps:int fd, int fs, int ft, address_word instruction_0
+{
+ check_fpu (SD_);
+ check_u64 (SD_, instruction_0);
+ StoreFPR (fd, fmt_ps, PackPS (PSUpper (ValueFPR (fs, fmt_ps)),
+ PSLower (ValueFPR (ft, fmt_ps))));
+}
+
+:function:::void:do_puu_ps:int fd, int fs, int ft, address_word instruction_0