Commit | Line | Data |
---|---|---|
c906108c SS |
1 | // -*- C -*- |
2 | // | |
3 | // NEC specific instructions | |
4 | // | |
5 | ||
4c54fc26 CD |
6 | :%s::::MFHI:int hi |
7 | { | |
8 | return hi ? "hi" : ""; | |
9 | } | |
c906108c | 10 | |
4c54fc26 CD |
11 | :%s::::SAT:int s |
12 | { | |
13 | return s ? "s" : ""; | |
14 | } | |
c906108c | 15 | |
4c54fc26 | 16 | :%s::::UNS:int u |
c906108c | 17 | { |
4c54fc26 | 18 | return u ? "u" : ""; |
c906108c SS |
19 | } |
20 | ||
4c54fc26 CD |
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 | |
c906108c | 42 | { |
4c54fc26 CD |
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); | |
bcd0068e CD |
76 | product = (unsigned_p |
77 | ? V8_4 (x, 1) * V8_4 (y, 1) | |
78 | : EXTEND32 (x) * EXTEND32 (y)); | |
4c54fc26 CD |
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; | |
c906108c SS |
101 | } |
102 | ||
4c54fc26 CD |
103 | // 32-bit rotate right of X by Y bits. |
104 | :function:::unsigned64:do_ror:unsigned32 x,unsigned32 y | |
105 | *vr5400: | |
106 | *vr5500: | |
c906108c | 107 | { |
4c54fc26 CD |
108 | unsigned64 result; |
109 | ||
110 | y &= 31; | |
111 | TRACE_ALU_INPUT2 (x, y); | |
112 | result = EXTEND32 (ROTR32 (x, y)); | |
113 | TRACE_ALU_RESULT (result); | |
c906108c SS |
114 | return result; |
115 | } | |
116 | ||
4c54fc26 CD |
117 | // Likewise 64-bit |
118 | :function:::unsigned64:do_dror:unsigned64 x,unsigned64 y | |
119 | *vr5400: | |
120 | *vr5500: | |
c906108c | 121 | { |
4c54fc26 CD |
122 | unsigned64 result; |
123 | ||
124 | y &= 63; | |
125 | TRACE_ALU_INPUT2 (x, y); | |
126 | result = ROTR64 (x, y); | |
127 | TRACE_ALU_RESULT (result); | |
c906108c SS |
128 | return result; |
129 | } | |
130 | ||
4c54fc26 CD |
131 | |
132 | // VR4100 instructions. | |
133 | ||
134 | 000000,5.RS,5.RT,00000,00000,101000::32::MADD16 | |
135 | "madd16 r<RS>, r<RT>" | |
c906108c SS |
136 | *vr4100: |
137 | { | |
4c54fc26 CD |
138 | do_vr_mul_op (SD_, 0, RS, RT, |
139 | 1 /* accumulate */, | |
140 | 0 /* store in LO */, | |
141 | 0 /* signed arithmetic */, | |
142 | 0 /* don't saturate */, | |
143 | 0 /* don't subtract */, | |
144 | 1 /* short */, | |
145 | 0 /* single */); | |
c906108c SS |
146 | } |
147 | ||
4c54fc26 CD |
148 | 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16 |
149 | "dmadd16 r<RS>, r<RT>" | |
c906108c SS |
150 | *vr4100: |
151 | { | |
4c54fc26 CD |
152 | do_vr_mul_op (SD_, 0, RS, RT, |
153 | 1 /* accumulate */, | |
154 | 0 /* store in LO */, | |
155 | 0 /* signed arithmetic */, | |
156 | 0 /* don't saturate */, | |
157 | 0 /* don't subtract */, | |
158 | 1 /* short */, | |
159 | 1 /* double */); | |
c906108c SS |
160 | } |
161 | ||
162 | ||
163 | ||
4c54fc26 CD |
164 | // VR4120 and VR4130 instructions. |
165 | ||
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>" | |
168 | *vr4120: | |
c906108c | 169 | { |
4c54fc26 CD |
170 | do_vr_mul_op (SD_, RD, RS, RT, |
171 | 1 /* accumulate */, | |
172 | MFHI, UNS, SAT, | |
173 | 0 /* don't subtract */, | |
174 | SAT /* short */, | |
175 | 1 /* double */); | |
c906108c SS |
176 | } |
177 | ||
4c54fc26 CD |
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>" | |
180 | *vr4120: | |
181 | { | |
182 | do_vr_mul_op (SD_, RD, RS, RT, | |
183 | 1 /* accumulate */, | |
184 | MFHI, UNS, SAT, | |
185 | 0 /* don't subtract */, | |
186 | SAT /* short */, | |
187 | 0 /* single */); | |
188 | } | |
c906108c | 189 | |
4c54fc26 CD |
190 | |
191 | // VR5400 and VR5500 instructions. | |
192 | ||
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>" | |
195 | *vr5400: | |
196 | *vr5500: | |
c906108c | 197 | { |
4c54fc26 CD |
198 | do_vr_mul_op (SD_, RD, RS, RT, |
199 | 0 /* don't accumulate */, | |
200 | MFHI, UNS, | |
201 | 0 /* don't saturate */, | |
202 | 0 /* don't subtract */, | |
203 | 0 /* not short */, | |
204 | 0 /* single */); | |
c906108c SS |
205 | } |
206 | ||
4c54fc26 CD |
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>" | |
209 | *vr5400: | |
210 | *vr5500: | |
211 | { | |
212 | do_vr_mul_op (SD_, RD, RS, RT, | |
213 | 0 /* don't accumulate */, | |
214 | MFHI, UNS, | |
215 | 0 /* don't saturate */, | |
216 | 1 /* subtract */, | |
217 | 0 /* not short */, | |
218 | 0 /* single */); | |
219 | } | |
220 | ||
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>" | |
223 | *vr5400: | |
224 | *vr5500: | |
225 | { | |
226 | do_vr_mul_op (SD_, RD, RS, RT, | |
227 | 1 /* accumulate */, | |
228 | MFHI, UNS, | |
229 | 0 /* don't saturate */, | |
230 | 0 /* don't subtract */, | |
231 | 0 /* not short */, | |
232 | 0 /* single */); | |
233 | } | |
234 | ||
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>" | |
237 | *vr5400: | |
238 | *vr5500: | |
239 | { | |
240 | do_vr_mul_op (SD_, RD, RS, RT, | |
241 | 1 /* accumulate */, | |
242 | MFHI, UNS, | |
243 | 0 /* don't saturate */, | |
244 | 1 /* subtract */, | |
245 | 0 /* not short */, | |
246 | 0 /* single */); | |
247 | } | |
248 | ||
249 | 000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR | |
250 | "ror r<RD>, r<RT>, <SHIFT>" | |
251 | *vr5400: | |
252 | *vr5500: | |
253 | { | |
254 | GPR[RD] = do_ror (SD_, GPR[RT], SHIFT); | |
255 | } | |
256 | ||
257 | 000000,5.RS,5.RT,5.RD,00001,000110::32::RORV | |
258 | "rorv r<RD>, r<RT>, r<RS>" | |
259 | *vr5400: | |
260 | *vr5500: | |
261 | { | |
262 | GPR[RD] = do_ror (SD_, GPR[RT], GPR[RS]); | |
263 | } | |
264 | ||
265 | 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR | |
266 | "dror r<RD>, r<RT>, <SHIFT>" | |
267 | *vr5400: | |
268 | *vr5500: | |
269 | { | |
270 | GPR[RD] = do_dror (SD_, GPR[RT], SHIFT); | |
271 | } | |
272 | ||
273 | 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32 | |
274 | "dror32 r<RD>, r<RT>, <SHIFT>" | |
275 | *vr5400: | |
276 | *vr5500: | |
277 | { | |
278 | GPR[RD] = do_dror (SD_, GPR[RT], SHIFT + 32); | |
279 | } | |
280 | ||
281 | 000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV | |
282 | "drorv r<RD>, r<RT>, r<RS>" | |
283 | *vr5400: | |
284 | *vr5500: | |
285 | { | |
286 | GPR[RD] = do_dror (SD_, GPR[RT], GPR[RS]); | |
287 | } | |
288 | ||
289 | 010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1 | |
290 | "luxc1 f<FD>, r<INDEX>(r<BASE>)" | |
291 | *vr5500: | |
292 | { | |
293 | check_fpu (SD_); | |
294 | COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, | |
295 | (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0)); | |
296 | } | |
297 | ||
298 | 010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1 | |
299 | "suxc1 f<FS>, r<INDEX>(r<BASE>)" | |
300 | *vr5500: | |
301 | { | |
302 | check_fpu (SD_); | |
303 | do_store (SD_, AccessLength_DOUBLEWORD, | |
304 | (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0, | |
305 | COP_SD (1, FS)); | |
306 | } | |
307 | ||
308 | 010000,1,19.*,100000:COP0:32::WAIT | |
309 | "wait" | |
310 | *vr5500: | |
311 | ||
312 | 011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR | |
313 | "mfdr r<RT>, r<DR>" | |
314 | *vr5400: | |
315 | *vr5500: | |
c906108c | 316 | |
4c54fc26 CD |
317 | 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR |
318 | "mtdr r<RT>, r<DR>" | |
319 | *vr5400: | |
320 | *vr5500: | |
c906108c | 321 | |
4c54fc26 CD |
322 | 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET |
323 | "dret" | |
324 | *vr5400: | |
325 | *vr5500: |