3 // NEC specific instructions
21 // Simulate the various kinds of multiply and multiply-accumulate instructions.
22 // Perform an operation of the form:
24 // LHS (+/-) GPR[RS] * GPR[RT]
26 // and store it in the 64-bit accumulator. Optionally copy either LO or
27 // HI into a general purpose register.
29 // - RD is the destination register of the LO or HI move
30 // - RS are RT are the multiplication source registers
31 // - ACCUMULATE_P is true if LHS should be the value of the 64-bit accumulator,
32 // false if it should be 0.
33 // - STORE_HI_P is true if HI should be stored in RD, false if LO should be.
34 // - UNSIGNED_P is true if the operation should be unsigned.
35 // - SATURATE_P is true if the result should be saturated to a 32-bit value.
36 // - SUBTRACT_P is true if the right hand side should be subtraced from LHS,
37 // false if it should be added.
38 // - SHORT_P is true if RS and RT must be 16-bit numbers.
39 // - DOUBLE_P is true if the 64-bit accumulator is in LO, false it is a
40 // concatenation of the low 32 bits of HI and LO.
41 :function:::void:do_vr_mul_op:int rd, int rs, int rt, int accumulate_p, int store_hi_p, int unsigned_p, int saturate_p, int subtract_p, int short_p, int double_p
43 unsigned64 lhs, x, y, xcut, ycut, product, result;
45 check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
47 lhs = (!accumulate_p ? 0 : double_p ? LO : U8_4 (HI, LO));
51 /* Work out the canonical form of X and Y from their significant bits. */
54 /* Normal sign-extension rule for 32-bit operands. */
60 /* Operands must be zero-extended 16-bit numbers. */
66 /* Likewise but sign-extended. */
70 if (x != xcut || y != ycut)
71 sim_engine_abort (SD, CPU, CIA,
72 "invalid multiplication operand at 0x%08lx\n",
75 TRACE_ALU_INPUT2 (x, y);
77 ? V8_4 (x, 1) * V8_4 (y, 1)
78 : EXTEND32 (x) * EXTEND32 (y));
79 result = (subtract_p ? lhs - product : lhs + product);
82 /* Saturate the result to 32 bits. An unsigned, unsaturated
83 result is zero-extended to 64 bits, but unsigned overflow
84 causes all 64 bits to be set. */
85 if (!unsigned_p && (unsigned64) EXTEND32 (result) != result)
86 result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff);
87 else if (unsigned_p && (result >> 32) != 0)
88 result = (unsigned64) 0 - 1;
90 TRACE_ALU_RESULT (result);
96 LO = EXTEND32 (result);
97 HI = EXTEND32 (VH4_8 (result));
100 GPR[rd] = store_hi_p ? HI : LO;
103 // 32-bit rotate right of X by Y bits.
104 :function:::unsigned64:do_ror:unsigned32 x,unsigned32 y
111 TRACE_ALU_INPUT2 (x, y);
112 result = EXTEND32 (ROTR32 (x, y));
113 TRACE_ALU_RESULT (result);
118 :function:::unsigned64:do_dror:unsigned64 x,unsigned64 y
125 TRACE_ALU_INPUT2 (x, y);
126 result = ROTR64 (x, y);
127 TRACE_ALU_RESULT (result);
132 // VR4100 instructions.
134 000000,5.RS,5.RT,00000,00000,101000::32::MADD16
135 "madd16 r<RS>, r<RT>"
138 do_vr_mul_op (SD_, 0, RS, RT,
141 0 /* signed arithmetic */,
142 0 /* don't saturate */,
143 0 /* don't subtract */,
148 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
149 "dmadd16 r<RS>, r<RT>"
152 do_vr_mul_op (SD_, 0, RS, RT,
155 0 /* signed arithmetic */,
156 0 /* don't saturate */,
157 0 /* don't subtract */,
164 // VR4120 and VR4130 instructions.
166 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
167 "dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
170 do_vr_mul_op (SD_, RD, RS, RT,
173 0 /* don't subtract */,
178 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
179 "macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
182 do_vr_mul_op (SD_, RD, RS, RT,
185 0 /* don't subtract */,
191 // VR5400 and VR5500 instructions.
193 000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
194 "mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
198 do_vr_mul_op (SD_, RD, RS, RT,
199 0 /* don't accumulate */,
201 0 /* don't saturate */,
202 0 /* don't subtract */,
207 000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS
208 "muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
212 do_vr_mul_op (SD_, RD, RS, RT,
213 0 /* don't accumulate */,
215 0 /* don't saturate */,
221 000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
222 "macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
226 do_vr_mul_op (SD_, RD, RS, RT,
229 0 /* don't saturate */,
230 0 /* don't subtract */,
235 000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC
236 "msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
240 do_vr_mul_op (SD_, RD, RS, RT,
243 0 /* don't saturate */,
249 000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR
250 "ror r<RD>, r<RT>, <SHIFT>"
254 GPR[RD] = do_ror (SD_, GPR[RT], SHIFT);
257 000000,5.RS,5.RT,5.RD,00001,000110::32::RORV
258 "rorv r<RD>, r<RT>, r<RS>"
262 GPR[RD] = do_ror (SD_, GPR[RT], GPR[RS]);
265 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR
266 "dror r<RD>, r<RT>, <SHIFT>"
270 GPR[RD] = do_dror (SD_, GPR[RT], SHIFT);
273 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32
274 "dror32 r<RD>, r<RT>, <SHIFT>"
278 GPR[RD] = do_dror (SD_, GPR[RT], SHIFT + 32);
281 000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV
282 "drorv r<RD>, r<RT>, r<RS>"
286 GPR[RD] = do_dror (SD_, GPR[RT], GPR[RS]);
289 010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1
290 "luxc1 f<FD>, r<INDEX>(r<BASE>)"
294 COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD,
295 (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0));
298 010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1
299 "suxc1 f<FS>, r<INDEX>(r<BASE>)"
303 do_store (SD_, AccessLength_DOUBLEWORD,
304 (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0,
308 010000,1,19.*,100000:COP0:32::WAIT
312 011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR
317 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
322 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET