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); | |
76 | product = (unsigned_p ? x * y : EXTEND32 (x) * EXTEND32 (y)); | |
77 | result = (subtract_p ? lhs - product : lhs + product); | |
78 | if (saturate_p) | |
79 | { | |
80 | /* Saturate the result to 32 bits. An unsigned, unsaturated | |
81 | result is zero-extended to 64 bits, but unsigned overflow | |
82 | causes all 64 bits to be set. */ | |
83 | if (!unsigned_p && (unsigned64) EXTEND32 (result) != result) | |
84 | result = ((signed64) result < 0 ? -0x7fffffff - 1 : 0x7fffffff); | |
85 | else if (unsigned_p && (result >> 32) != 0) | |
86 | result = (unsigned64) 0 - 1; | |
87 | } | |
88 | TRACE_ALU_RESULT (result); | |
89 | ||
90 | if (double_p) | |
91 | LO = result; | |
92 | else | |
93 | { | |
94 | LO = EXTEND32 (result); | |
95 | HI = EXTEND32 (VH4_8 (result)); | |
96 | } | |
97 | if (rd != 0) | |
98 | GPR[rd] = store_hi_p ? HI : LO; | |
c906108c SS |
99 | } |
100 | ||
4c54fc26 CD |
101 | // 32-bit rotate right of X by Y bits. |
102 | :function:::unsigned64:do_ror:unsigned32 x,unsigned32 y | |
103 | *vr5400: | |
104 | *vr5500: | |
c906108c | 105 | { |
4c54fc26 CD |
106 | unsigned64 result; |
107 | ||
108 | y &= 31; | |
109 | TRACE_ALU_INPUT2 (x, y); | |
110 | result = EXTEND32 (ROTR32 (x, y)); | |
111 | TRACE_ALU_RESULT (result); | |
c906108c SS |
112 | return result; |
113 | } | |
114 | ||
4c54fc26 CD |
115 | // Likewise 64-bit |
116 | :function:::unsigned64:do_dror:unsigned64 x,unsigned64 y | |
117 | *vr5400: | |
118 | *vr5500: | |
c906108c | 119 | { |
4c54fc26 CD |
120 | unsigned64 result; |
121 | ||
122 | y &= 63; | |
123 | TRACE_ALU_INPUT2 (x, y); | |
124 | result = ROTR64 (x, y); | |
125 | TRACE_ALU_RESULT (result); | |
c906108c SS |
126 | return result; |
127 | } | |
128 | ||
4c54fc26 CD |
129 | |
130 | // VR4100 instructions. | |
131 | ||
132 | 000000,5.RS,5.RT,00000,00000,101000::32::MADD16 | |
133 | "madd16 r<RS>, r<RT>" | |
c906108c SS |
134 | *vr4100: |
135 | { | |
4c54fc26 CD |
136 | do_vr_mul_op (SD_, 0, RS, RT, |
137 | 1 /* accumulate */, | |
138 | 0 /* store in LO */, | |
139 | 0 /* signed arithmetic */, | |
140 | 0 /* don't saturate */, | |
141 | 0 /* don't subtract */, | |
142 | 1 /* short */, | |
143 | 0 /* single */); | |
c906108c SS |
144 | } |
145 | ||
4c54fc26 CD |
146 | 000000,5.RS,5.RT,00000,00000,101001::64::DMADD16 |
147 | "dmadd16 r<RS>, r<RT>" | |
c906108c SS |
148 | *vr4100: |
149 | { | |
4c54fc26 CD |
150 | do_vr_mul_op (SD_, 0, RS, RT, |
151 | 1 /* accumulate */, | |
152 | 0 /* store in LO */, | |
153 | 0 /* signed arithmetic */, | |
154 | 0 /* don't saturate */, | |
155 | 0 /* don't subtract */, | |
156 | 1 /* short */, | |
157 | 1 /* double */); | |
c906108c SS |
158 | } |
159 | ||
160 | ||
161 | ||
4c54fc26 CD |
162 | // VR4120 and VR4130 instructions. |
163 | ||
164 | 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101001::64::DMACC | |
165 | "dmacc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>" | |
166 | *vr4120: | |
c906108c | 167 | { |
4c54fc26 CD |
168 | do_vr_mul_op (SD_, RD, RS, RT, |
169 | 1 /* accumulate */, | |
170 | MFHI, UNS, SAT, | |
171 | 0 /* don't subtract */, | |
172 | SAT /* short */, | |
173 | 1 /* double */); | |
c906108c SS |
174 | } |
175 | ||
4c54fc26 CD |
176 | 000000,5.RS,5.RT,5.RD,1.SAT,1.MFHI,00,1.UNS,101000::32::MACC_4120 |
177 | "macc%s<MFHI>%s<UNS>%s<SAT> r<RD>, r<RS>, r<RT>" | |
178 | *vr4120: | |
179 | { | |
180 | do_vr_mul_op (SD_, RD, RS, RT, | |
181 | 1 /* accumulate */, | |
182 | MFHI, UNS, SAT, | |
183 | 0 /* don't subtract */, | |
184 | SAT /* short */, | |
185 | 0 /* single */); | |
186 | } | |
c906108c | 187 | |
4c54fc26 CD |
188 | |
189 | // VR5400 and VR5500 instructions. | |
190 | ||
191 | 000000,5.RS,5.RT,5.RD,0,1.MFHI,001,01100,1.UNS::32::MUL | |
192 | "mul%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>" | |
193 | *vr5400: | |
194 | *vr5500: | |
c906108c | 195 | { |
4c54fc26 CD |
196 | do_vr_mul_op (SD_, RD, RS, RT, |
197 | 0 /* don't accumulate */, | |
198 | MFHI, UNS, | |
199 | 0 /* don't saturate */, | |
200 | 0 /* don't subtract */, | |
201 | 0 /* not short */, | |
202 | 0 /* single */); | |
c906108c SS |
203 | } |
204 | ||
4c54fc26 CD |
205 | 000000,5.RS,5.RT,5.RD,0,1.MFHI,011,01100,1.UNS::32::MULS |
206 | "muls%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>" | |
207 | *vr5400: | |
208 | *vr5500: | |
209 | { | |
210 | do_vr_mul_op (SD_, RD, RS, RT, | |
211 | 0 /* don't accumulate */, | |
212 | MFHI, UNS, | |
213 | 0 /* don't saturate */, | |
214 | 1 /* subtract */, | |
215 | 0 /* not short */, | |
216 | 0 /* single */); | |
217 | } | |
218 | ||
219 | 000000,5.RS,5.RT,5.RD,0,1.MFHI,101,01100,1.UNS::32::MACC_5xxx | |
220 | "macc%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>" | |
221 | *vr5400: | |
222 | *vr5500: | |
223 | { | |
224 | do_vr_mul_op (SD_, RD, RS, RT, | |
225 | 1 /* accumulate */, | |
226 | MFHI, UNS, | |
227 | 0 /* don't saturate */, | |
228 | 0 /* don't subtract */, | |
229 | 0 /* not short */, | |
230 | 0 /* single */); | |
231 | } | |
232 | ||
233 | 000000,5.RS,5.RT,5.RD,0,1.MFHI,111,01100,1.UNS::32::MSAC | |
234 | "msac%s<MFHI>%s<UNS> r<RD>, r<RS>, r<RT>" | |
235 | *vr5400: | |
236 | *vr5500: | |
237 | { | |
238 | do_vr_mul_op (SD_, RD, RS, RT, | |
239 | 1 /* accumulate */, | |
240 | MFHI, UNS, | |
241 | 0 /* don't saturate */, | |
242 | 1 /* subtract */, | |
243 | 0 /* not short */, | |
244 | 0 /* single */); | |
245 | } | |
246 | ||
247 | 000000,00001,5.RT,5.RD,5.SHIFT,000010::32::ROR | |
248 | "ror r<RD>, r<RT>, <SHIFT>" | |
249 | *vr5400: | |
250 | *vr5500: | |
251 | { | |
252 | GPR[RD] = do_ror (SD_, GPR[RT], SHIFT); | |
253 | } | |
254 | ||
255 | 000000,5.RS,5.RT,5.RD,00001,000110::32::RORV | |
256 | "rorv r<RD>, r<RT>, r<RS>" | |
257 | *vr5400: | |
258 | *vr5500: | |
259 | { | |
260 | GPR[RD] = do_ror (SD_, GPR[RT], GPR[RS]); | |
261 | } | |
262 | ||
263 | 000000,00001,5.RT,5.RD,5.SHIFT,111010::64::DROR | |
264 | "dror r<RD>, r<RT>, <SHIFT>" | |
265 | *vr5400: | |
266 | *vr5500: | |
267 | { | |
268 | GPR[RD] = do_dror (SD_, GPR[RT], SHIFT); | |
269 | } | |
270 | ||
271 | 000000,00001,5.RT,5.RD,5.SHIFT,111110::64::DROR32 | |
272 | "dror32 r<RD>, r<RT>, <SHIFT>" | |
273 | *vr5400: | |
274 | *vr5500: | |
275 | { | |
276 | GPR[RD] = do_dror (SD_, GPR[RT], SHIFT + 32); | |
277 | } | |
278 | ||
279 | 000000,5.RS,5.RT,5.RD,00001,010110::64::DRORV | |
280 | "drorv r<RD>, r<RT>, r<RS>" | |
281 | *vr5400: | |
282 | *vr5500: | |
283 | { | |
284 | GPR[RD] = do_dror (SD_, GPR[RT], GPR[RS]); | |
285 | } | |
286 | ||
287 | 010011,5.BASE,5.INDEX,5.0,5.FD,000101:COP1X:64::LUXC1 | |
288 | "luxc1 f<FD>, r<INDEX>(r<BASE>)" | |
289 | *vr5500: | |
290 | { | |
291 | check_fpu (SD_); | |
292 | COP_LD (1, FD, do_load (SD_, AccessLength_DOUBLEWORD, | |
293 | (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0)); | |
294 | } | |
295 | ||
296 | 010011,5.BASE,5.INDEX,5.FS,00000,001101:COP1X:64::SUXC1 | |
297 | "suxc1 f<FS>, r<INDEX>(r<BASE>)" | |
298 | *vr5500: | |
299 | { | |
300 | check_fpu (SD_); | |
301 | do_store (SD_, AccessLength_DOUBLEWORD, | |
302 | (GPR[BASE] + GPR[INDEX]) & ~MASK64 (2, 0), 0, | |
303 | COP_SD (1, FS)); | |
304 | } | |
305 | ||
306 | 010000,1,19.*,100000:COP0:32::WAIT | |
307 | "wait" | |
308 | *vr5500: | |
309 | ||
310 | 011100,00000,5.RT,5.DR,00000,111101:SPECIAL:64::MFDR | |
311 | "mfdr r<RT>, r<DR>" | |
312 | *vr5400: | |
313 | *vr5500: | |
c906108c | 314 | |
4c54fc26 CD |
315 | 011100,00100,5.RT,5.DR,00000,111101:SPECIAL:64::MTDR |
316 | "mtdr r<RT>, r<DR>" | |
317 | *vr5400: | |
318 | *vr5500: | |
c906108c | 319 | |
4c54fc26 CD |
320 | 011100,00000,00000,00000,00000,111110:SPECIAL:64::DRET |
321 | "dret" | |
322 | *vr5400: | |
323 | *vr5500: |