1// -*- C -*-
2//
3// NEC specific instructions
4//
5
6:%s::::MFHI:int hi
7{
8  return hi ? "hi" : "";
9}
10
11:%s::::SAT:int s
12{
13  return s ? "s" : "";
14}
15
16:%s::::UNS:int u
17{
18  return u ? "u" : "";
19}
20
21// Simulate the various kinds of multiply and multiply-accumulate instructions.
22// Perform an operation of the form:
23//
24//	LHS (+/-) GPR[RS] * GPR[RT]
25//
26// and store it in the 64-bit accumulator.  Optionally copy either LO or
27// HI into a general purpose register.
28//
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
42{
43  unsigned64 lhs, x, y, xcut, ycut, product, result;
44
45  check_mult_hilo (SD_, HIHISTORY, LOHISTORY);
46
47  lhs = (!accumulate_p ? 0 : double_p ? LO : U8_4 (HI, LO));
48  x = GPR[rs];
49  y = GPR[rt];
50
51  /* Work out the canonical form of X and Y from their significant bits.  */
52  if (!short_p)
53    {
54      /* Normal sign-extension rule for 32-bit operands.  */
55      xcut = EXTEND32 (x);
56      ycut = EXTEND32 (y);
57    }
58  else if (unsigned_p)
59    {
60      /* Operands must be zero-extended 16-bit numbers.  */
61      xcut = x & 0xffff;
62      ycut = y & 0xffff;
63    }
64  else
65    {
66      /* Likewise but sign-extended.  */
67      xcut = EXTEND16 (x);
68      ycut = EXTEND16 (y);
69    }
70  if (x != xcut || y != ycut)
71    sim_engine_abort (SD, CPU, CIA,
72		      "invalid multiplication operand at 0x%08lx\n",
73		      (long) CIA);
74
75  TRACE_ALU_INPUT2 (x, y);
76  product = (unsigned_p
77	     ? V8_4 (x, 1) * V8_4 (y, 1)
78	     : EXTEND32 (x) * EXTEND32 (y));
79  result = (subtract_p ? lhs - product : lhs + product);
80  if (saturate_p)
81    {
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;
89    }
90  TRACE_ALU_RESULT (result);
91
92  if (double_p)
93    LO = result;
94  else
95    {
96      LO = EXTEND32 (result);
97      HI = EXTEND32 (VH4_8 (result));
98    }
99  if (rd != 0)
100    GPR[rd] = store_hi_p ? HI : LO;
101}
102
103// VR4100 instructions.
104
105000000,5.RS,5.RT,00000,00000,101000::32::MADD16
106"madd16 r<RS>, r<RT>"
107*vr4100:
108{
109  do_vr_mul_op (SD_, 0, RS, RT,
110		1 /* accumulate */,
111		0 /* store in LO */,
112		0 /* signed arithmetic */,
113		0 /* don't saturate */,
114		0 /* don't subtract */,
115		1 /* short */,
116		0 /* single */);
117}
118
119000000,5.RS,5.RT,00000,00000,101001::64::DMADD16
120"dmadd16 r<RS>, r<RT>"
121*vr4100:
122{
123  do_vr_mul_op (SD_, 0, RS, RT,
124		1 /* accumulate */,
125		0 /* store in LO */,
126		0 /* signed arithmetic */,
127		0 /* don't saturate */,
128		0 /* don't subtract */,
129		1 /* short */,
130		1 /* double */);
131}
132
133
134
135// VR4120 and VR4130 instructions.
136
137000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC
138"dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
139*vr4120:
140{
141  do_vr_mul_op (SD_, RD, RS, RT,
142		1 /* accumulate */,
143		MFHI, UNS, SAT,
144		0 /* don't subtract */,
145		SAT /* short */,
146		1 /* double */);
147}
148
149000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120
150"macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>"
151*vr4120:
152{
153  do_vr_mul_op (SD_, RD, RS, RT,
154		1 /* accumulate */,
155		MFHI, UNS, SAT,
156		0 /* don't subtract */,
157		SAT /* short */,
158		0 /* single */);
159}
160
161
162// VR5400 and VR5500 instructions.
163
164000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL
165"mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
166*vr5400:
167*vr5500:
168{
169  do_vr_mul_op (SD_, RD, RS, RT,
170		0 /* don't accumulate */,
171		MFHI, UNS,
172		0 /* don't saturate */,
173		0 /* don't subtract */,
174		0 /* not short */,
175		0 /* single */);
176}
177
178000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS
179"muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
180*vr5400:
181*vr5500:
182{
183  do_vr_mul_op (SD_, RD, RS, RT,
184		0 /* don't accumulate */,
185		MFHI, UNS,
186		0 /* don't saturate */,
187		1 /* subtract */,
188		0 /* not short */,
189		0 /* single */);
190}
191
192000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx
193"macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
194*vr5400:
195*vr5500:
196{
197  do_vr_mul_op (SD_, RD, RS, RT,
198		1 /* accumulate */,
199		MFHI, UNS,
200		0 /* don't saturate */,
201		0 /* don't subtract */,
202		0 /* not short */,
203		0 /* single */);
204}
205
206000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC
207"msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>"
208*vr5400:
209*vr5500:
210{
211  do_vr_mul_op (SD_, RD, RS, RT,
212		1 /* accumulate */,
213		MFHI, UNS,
214		0 /* don't saturate */,
215		1 /* subtract */,
216		0 /* not short */,
217		0 /* single */);
218}
219
220
221010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1
222"luxc1 f<FD>, r<INDEX>(r<BASE>)"
223*vr5500:
224{
225  check_fpu (SD_);
226  COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD,
227			  (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0));
228}
229
230010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1
231"suxc1 f<FS>, r<INDEX>(r<BASE>)"
232*vr5500:
233{
234  check_fpu (SD_);
235  do_store (SD_, AccessLength_DOUBLEWORD,
236	    (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0,
237	    COP_SD (1, FS));
238}
239
240010000,1,19.*,100000:COP0:32::WAIT
241"wait"
242*vr5500:
243
244011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR
245"mfdr r<RT>, r<DR>"
246*vr5400:
247*vr5500:
248
249011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR
250"mtdr r<RT>, r<DR>"
251*vr5400:
252*vr5500:
253
254011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET
255"dret"
256*vr5400:
257*vr5500:
258