1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde
3 /* compute operations */
4
5 #include <cmath>
6
7 #define CLEAR_ALU_FLAGS() (m_core->astat &= ~(AZ|AN|AV|AC|AS|AI))
8
9 #define SET_FLAG_AZ(r) { m_core->astat |= (((r) == 0) ? AZ : 0); }
10 #define SET_FLAG_AN(r) { m_core->astat |= (((r) & 0x80000000) ? AN : 0); }
11 #define SET_FLAG_AC_ADD(r,a,b) { m_core->astat |= (((uint32_t)r < (uint32_t)a) ? AC : 0); }
12 #define SET_FLAG_AV_ADD(r,a,b) { m_core->astat |= (((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); }
13 #define SET_FLAG_AC_SUB(r,a,b) { m_core->astat |= ((!((uint32_t)a < (uint32_t)b)) ? AC : 0); }
14 #define SET_FLAG_AV_SUB(r,a,b) { m_core->astat |= ((( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); }
15
16 #define IS_FLOAT_ZERO(r) ((((r) & 0x7fffffff) == 0))
17 #define IS_FLOAT_DENORMAL(r) ((((r) & 0x7f800000) == 0) && (((r) & 0x7fffff) != 0))
18 #define IS_FLOAT_NAN(r) ((((r) & 0x7f800000) == 0x7f800000) && (((r) & 0x7fffff) != 0))
19 #define IS_FLOAT_INFINITY(r) (((r) & 0x7fffffff) == 0x7f800000)
20
21 #define CLEAR_MULTIPLIER_FLAGS() (m_core->astat &= ~(MN|MV|MU|MI))
22
23 #define SET_FLAG_MN(r) { m_core->astat |= (((r) & 0x80000000) ? MN : 0); }
24 #define SET_FLAG_MV(r) { m_core->astat |= ((((uint32_t)((r) >> 32) != 0) && ((uint32_t)((r) >> 32) != 0xffffffff)) ? MV : 0); }
25
26 /* TODO: MU needs 80-bit result */
27 #define SET_FLAG_MU(r) { m_core->astat |= ((((uint32_t)((r) >> 32) == 0) && ((uint32_t)(r)) != 0) ? MU : 0); }
28
29
30 #define FLOAT_SIGN 0x80000000
31 #define FLOAT_INFINITY 0x7f800000
32 #define FLOAT_MANTISSA 0x007fffff
33
34 /*****************************************************************************/
35
36 // Mantissa lookup-table for RECIPS opcode
37 static const uint32_t recips_mantissa_lookup[128] =
38 {
39 0x007F8000, 0x007E0000, 0x007C0000, 0x007A0000,
40 0x00780000, 0x00760000, 0x00740000, 0x00720000,
41 0x00700000, 0x006F0000, 0x006D0000, 0x006B0000,
42 0x006A0000, 0x00680000, 0x00660000, 0x00650000,
43 0x00630000, 0x00610000, 0x00600000, 0x005E0000,
44 0x005D0000, 0x005B0000, 0x005A0000, 0x00590000,
45 0x00570000, 0x00560000, 0x00540000, 0x00530000,
46 0x00520000, 0x00500000, 0x004F0000, 0x004E0000,
47 0x004C0000, 0x004B0000, 0x004A0000, 0x00490000,
48 0x00470000, 0x00460000, 0x00450000, 0x00440000,
49 0x00430000, 0x00410000, 0x00400000, 0x003F0000,
50 0x003E0000, 0x003D0000, 0x003C0000, 0x003B0000,
51 0x003A0000, 0x00390000, 0x00380000, 0x00370000,
52 0x00360000, 0x00350000, 0x00340000, 0x00330000,
53 0x00320000, 0x00310000, 0x00300000, 0x002F0000,
54 0x002E0000, 0x002D0000, 0x002C0000, 0x002B0000,
55 0x002A0000, 0x00290000, 0x00280000, 0x00280000,
56 0x00270000, 0x00260000, 0x00250000, 0x00240000,
57 0x00230000, 0x00230000, 0x00220000, 0x00210000,
58 0x00200000, 0x001F0000, 0x001F0000, 0x001E0000,
59 0x001D0000, 0x001C0000, 0x001C0000, 0x001B0000,
60 0x001A0000, 0x00190000, 0x00190000, 0x00180000,
61 0x00170000, 0x00170000, 0x00160000, 0x00150000,
62 0x00140000, 0x00140000, 0x00130000, 0x00120000,
63 0x00120000, 0x00110000, 0x00100000, 0x00100000,
64 0x000F0000, 0x000F0000, 0x000E0000, 0x000D0000,
65 0x000D0000, 0x000C0000, 0x000C0000, 0x000B0000,
66 0x000A0000, 0x000A0000, 0x00090000, 0x00090000,
67 0x00080000, 0x00070000, 0x00070000, 0x00060000,
68 0x00060000, 0x00050000, 0x00050000, 0x00040000,
69 0x00040000, 0x00030000, 0x00030000, 0x00020000,
70 0x00020000, 0x00010000, 0x00010000, 0x00000000,
71 };
72
73 // Mantissa lookup-table for RSQRTS opcode
74 static const uint32_t rsqrts_mantissa_lookup[128] =
75 {
76 0x00350000, 0x00330000, 0x00320000, 0x00300000,
77 0x002F0000, 0x002E0000, 0x002D0000, 0x002B0000,
78 0x002A0000, 0x00290000, 0x00280000, 0x00270000,
79 0x00260000, 0x00250000, 0x00230000, 0x00220000,
80 0x00210000, 0x00200000, 0x001F0000, 0x001E0000,
81 0x001E0000, 0x001D0000, 0x001C0000, 0x001B0000,
82 0x001A0000, 0x00190000, 0x00180000, 0x00170000,
83 0x00160000, 0x00160000, 0x00150000, 0x00140000,
84 0x00130000, 0x00130000, 0x00120000, 0x00110000,
85 0x00100000, 0x00100000, 0x000F0000, 0x000E0000,
86 0x000E0000, 0x000D0000, 0x000C0000, 0x000B0000,
87 0x000B0000, 0x000A0000, 0x000A0000, 0x00090000,
88 0x00080000, 0x00080000, 0x00070000, 0x00070000,
89 0x00060000, 0x00050000, 0x00050000, 0x00040000,
90 0x00040000, 0x00030000, 0x00030000, 0x00020000,
91 0x00020000, 0x00010000, 0x00010000, 0x00000000,
92 0x007F8000, 0x007E0000, 0x007C0000, 0x007A0000,
93 0x00780000, 0x00760000, 0x00740000, 0x00730000,
94 0x00710000, 0x006F0000, 0x006E0000, 0x006C0000,
95 0x006A0000, 0x00690000, 0x00670000, 0x00660000,
96 0x00640000, 0x00630000, 0x00620000, 0x00600000,
97 0x005F0000, 0x005E0000, 0x005C0000, 0x005B0000,
98 0x005A0000, 0x00590000, 0x00570000, 0x00560000,
99 0x00550000, 0x00540000, 0x00530000, 0x00520000,
100 0x00510000, 0x004F0000, 0x004E0000, 0x004D0000,
101 0x004C0000, 0x004B0000, 0x004A0000, 0x00490000,
102 0x00480000, 0x00470000, 0x00460000, 0x00450000,
103 0x00450000, 0x00440000, 0x00430000, 0x00420000,
104 0x00410000, 0x00400000, 0x003F0000, 0x003E0000,
105 0x003E0000, 0x003D0000, 0x003C0000, 0x003B0000,
106 0x003A0000, 0x003A0000, 0x00390000, 0x00380000,
107 0x00370000, 0x00370000, 0x00360000, 0x00350000,
108 };
109
110 /*****************************************************************************/
111 /* Integer ALU operations */
112
113 /* Rn = Rx + Ry */
compute_add(int rn,int rx,int ry)114 void adsp21062_device::compute_add(int rn, int rx, int ry)
115 {
116 uint32_t r = REG(rx) + REG(ry);
117
118 if (m_core->mode1 & MODE1_ALUSAT)
119 fatalerror("SHARC: compute_add: ALU saturation not implemented!\n");
120
121 CLEAR_ALU_FLAGS();
122 SET_FLAG_AN(r);
123 SET_FLAG_AZ(r);
124 SET_FLAG_AV_ADD(r, REG(rx), REG(ry));
125 SET_FLAG_AC_ADD(r, REG(rx), REG(ry));
126 REG(rn) = r;
127
128 m_core->astat &= ~AF;
129 }
130
131 /* Rn = Rx - Ry */
compute_sub(int rn,int rx,int ry)132 void adsp21062_device::compute_sub(int rn, int rx, int ry)
133 {
134 uint32_t r = REG(rx) - REG(ry);
135
136 if (m_core->mode1 & MODE1_ALUSAT)
137 fatalerror("SHARC: compute_sub: ALU saturation not implemented!\n");
138
139 CLEAR_ALU_FLAGS();
140 SET_FLAG_AN(r);
141 SET_FLAG_AZ(r);
142 SET_FLAG_AV_SUB(r, REG(rx), REG(ry));
143 SET_FLAG_AC_SUB(r, REG(rx), REG(ry));
144 REG(rn) = r;
145
146 m_core->astat &= ~AF;
147 }
148
149 /* Rn = Rx + Ry + CI */
compute_add_ci(int rn,int rx,int ry)150 void adsp21062_device::compute_add_ci(int rn, int rx, int ry)
151 {
152 int c = (m_core->astat & AC) ? 1 : 0;
153 uint32_t r = REG(rx) + REG(ry) + c;
154
155 if (m_core->mode1 & MODE1_ALUSAT)
156 fatalerror("SHARC: compute_add_ci: ALU saturation not implemented!\n");
157
158 CLEAR_ALU_FLAGS();
159 SET_FLAG_AN(r);
160 SET_FLAG_AZ(r);
161 SET_FLAG_AV_ADD(r, REG(rx), REG(ry)+c);
162 SET_FLAG_AC_ADD(r, REG(rx), REG(ry)+c);
163 REG(rn) = r;
164
165 m_core->astat &= ~AF;
166 }
167
168 /* Rn = Rx - Ry + CI - 1 */
compute_sub_ci(int rn,int rx,int ry)169 void adsp21062_device::compute_sub_ci(int rn, int rx, int ry)
170 {
171 int c = (m_core->astat & AC) ? 1 : 0;
172 uint32_t r = REG(rx) - REG(ry) + c - 1;
173
174 if (m_core->mode1 & MODE1_ALUSAT)
175 fatalerror("SHARC: compute_sub_ci: ALU saturation not implemented!\n");
176
177 CLEAR_ALU_FLAGS();
178 SET_FLAG_AN(r);
179 SET_FLAG_AZ(r);
180 SET_FLAG_AV_SUB(r, REG(rx), REG(ry)+c-1);
181 SET_FLAG_AC_SUB(r, REG(rx), REG(ry)+c-1);
182 REG(rn) = r;
183
184 m_core->astat &= ~AF;
185 }
186
187 /* Rn = Rx AND Ry */
compute_and(int rn,int rx,int ry)188 void adsp21062_device::compute_and(int rn, int rx, int ry)
189 {
190 uint32_t r = REG(rx) & REG(ry);
191
192 CLEAR_ALU_FLAGS();
193 SET_FLAG_AN(r);
194 SET_FLAG_AZ(r);
195 REG(rn) = r;
196
197 m_core->astat &= ~AF;
198 }
199
200 /* COMP(Rx, Ry) */
compute_comp(int rx,int ry)201 void adsp21062_device::compute_comp(int rx, int ry)
202 {
203 uint32_t comp_accum;
204
205 CLEAR_ALU_FLAGS();
206 if( REG(rx) == REG(ry) )
207 m_core->astat |= AZ;
208 if( (int32_t)REG(rx) < (int32_t)REG(ry) )
209 m_core->astat |= AN;
210
211 // Update ASTAT compare accumulation register
212 comp_accum = (m_core->astat >> 24) & 0xff;
213 comp_accum >>= 1;
214 if ((m_core->astat & (AZ|AN)) == 0)
215 {
216 comp_accum |= 0x80;
217 }
218 m_core->astat &= 0xffffff;
219 m_core->astat |= comp_accum << 24;
220
221 m_core->astat &= ~AF;
222 }
223
224 /* Rn = PASS Rx */
compute_pass(int rn,int rx)225 void adsp21062_device::compute_pass(int rn, int rx)
226 {
227 CLEAR_ALU_FLAGS();
228 /* TODO: floating-point extension field is set to 0 */
229
230 REG(rn) = REG(rx);
231 if (REG(rn) == 0)
232 m_core->astat |= AZ;
233 if (REG(rn) & 0x80000000)
234 m_core->astat |= AN;
235
236 m_core->astat &= ~AF;
237 }
238
239 /* Rn = Rx XOR Ry */
compute_xor(int rn,int rx,int ry)240 void adsp21062_device::compute_xor(int rn, int rx, int ry)
241 {
242 uint32_t r = REG(rx) ^ REG(ry);
243 CLEAR_ALU_FLAGS();
244 SET_FLAG_AN(r);
245 SET_FLAG_AZ(r);
246 REG(rn) = r;
247
248 m_core->astat &= ~AF;
249 }
250
251 /* Rn = Rx OR Ry */
compute_or(int rn,int rx,int ry)252 void adsp21062_device::compute_or(int rn, int rx, int ry)
253 {
254 uint32_t r = REG(rx) | REG(ry);
255 CLEAR_ALU_FLAGS();
256 SET_FLAG_AN(r);
257 SET_FLAG_AZ(r);
258 REG(rn) = r;
259
260 m_core->astat &= ~AF;
261 }
262
263 /* Rn = Rx + 1 */
compute_inc(int rn,int rx)264 void adsp21062_device::compute_inc(int rn, int rx)
265 {
266 uint32_t r = REG(rx) + 1;
267
268 CLEAR_ALU_FLAGS();
269 SET_FLAG_AN(r);
270 SET_FLAG_AZ(r);
271 SET_FLAG_AV_ADD(r, REG(rx), 1);
272 SET_FLAG_AC_ADD(r, REG(rx), 1);
273
274 REG(rn) = r;
275
276 m_core->astat &= ~AF;
277 }
278
279 /* Rn = Rx - 1 */
compute_dec(int rn,int rx)280 void adsp21062_device::compute_dec(int rn, int rx)
281 {
282 uint32_t r = REG(rx) - 1;
283
284 CLEAR_ALU_FLAGS();
285 SET_FLAG_AN(r);
286 SET_FLAG_AZ(r);
287 SET_FLAG_AV_SUB(r, REG(rx), 1);
288 SET_FLAG_AC_SUB(r, REG(rx), 1);
289
290 REG(rn) = r;
291
292 m_core->astat &= ~AF;
293 }
294
295 /* Rn = MIN(Rx, Ry) */
compute_min(int rn,int rx,int ry)296 void adsp21062_device::compute_min(int rn, int rx, int ry)
297 {
298 uint32_t r = std::min((int32_t)REG(rx), (int32_t)REG(ry));
299
300 CLEAR_ALU_FLAGS();
301 SET_FLAG_AN(r);
302 SET_FLAG_AZ(r);
303
304 REG(rn) = r;
305
306 m_core->astat &= ~AF;
307 }
308
309 /* Rn = MAX(Rx, Ry) */
compute_max(int rn,int rx,int ry)310 void adsp21062_device::compute_max(int rn, int rx, int ry)
311 {
312 uint32_t r = std::max((int32_t)REG(rx), (int32_t)REG(ry));
313
314 CLEAR_ALU_FLAGS();
315 SET_FLAG_AN(r);
316 SET_FLAG_AZ(r);
317
318 REG(rn) = r;
319
320 m_core->astat &= ~AF;
321 }
322
323 /* Rn = -Rx */
compute_neg(int rn,int rx)324 void adsp21062_device::compute_neg(int rn, int rx)
325 {
326 uint32_t r = -(int32_t)(REG(rx));
327
328 CLEAR_ALU_FLAGS();
329 SET_FLAG_AN(r);
330 SET_FLAG_AZ(r);
331 SET_FLAG_AV_SUB(r, 0, REG(rx));
332 SET_FLAG_AC_SUB(r, 0, REG(rx));
333
334 REG(rn) = r;
335
336 m_core->astat &= ~AF;
337 }
338
339 /* Rn = NOT Rx */
compute_not(int rn,int rx)340 void adsp21062_device::compute_not(int rn, int rx)
341 {
342 uint32_t r = ~REG(rx);
343
344 CLEAR_ALU_FLAGS();
345 SET_FLAG_AN(r);
346 SET_FLAG_AZ(r);
347
348 REG(rn) = r;
349
350 m_core->astat &= ~AF;
351 }
352
353 /*****************************************************************************/
354 /* Floating-point ALU operations */
355
SCALB(SHARC_REG rx,int ry)356 uint32_t adsp21062_device::SCALB(SHARC_REG rx, int ry)
357 {
358 uint32_t mantissa = rx.r & FLOAT_MANTISSA;
359 uint32_t sign = rx.r & FLOAT_SIGN;
360
361 int exponent = ((rx.r >> 23) & 0xff) - 127;
362 exponent += (int32_t)(REG(ry));
363
364 if (exponent > 127)
365 {
366 // overflow
367 m_core->astat |= AV;
368 return sign | FLOAT_INFINITY;
369 }
370 else if (exponent < -126)
371 {
372 // denormal
373 m_core->astat |= AZ;
374 return sign;
375 }
376 else
377 {
378 return sign | (((exponent + 127) & 0xff) << 23) | mantissa;
379 }
380 }
381
382 /* Fn = FLOAT Rx */
compute_float(int rn,int rx)383 void adsp21062_device::compute_float(int rn, int rx)
384 {
385 // verified
386 FREG(rn) = (float)(int32_t)REG(rx);
387
388 CLEAR_ALU_FLAGS();
389 // AN
390 SET_FLAG_AN(REG(rn));
391 // AZ
392 m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
393 // AUS
394 m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
395 /* TODO: AV flag */
396
397 m_core->astat |= AF;
398 }
399
400 /* Rn = FIX Fx */
compute_fix(int rn,int rx)401 void adsp21062_device::compute_fix(int rn, int rx)
402 {
403 int32_t alu_i;
404 SHARC_REG r_alu;
405
406 r_alu.f = FREG(rx);
407 if (m_core->mode1 & MODE1_TRUNCATE)
408 {
409 alu_i = (int32_t)(r_alu.f);
410 }
411 else
412 {
413 alu_i = (int32_t)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
414 }
415
416 CLEAR_ALU_FLAGS();
417 SET_FLAG_AN(alu_i);
418 // AZ
419 SET_FLAG_AZ(alu_i);
420 // AU
421 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
422 // AI
423 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
424 /* TODO: AV flag */
425
426 REG(rn) = alu_i;
427 m_core->astat |= AF;
428 }
429
430 /* Rn = FIX Fx BY Ry */
compute_fix_scaled(int rn,int rx,int ry)431 void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry)
432 {
433 int32_t alu_i;
434 SHARC_REG r_alu;
435
436 r_alu.r = SCALB(m_core->r[rx], ry);
437 if (m_core->mode1 & MODE1_TRUNCATE)
438 {
439 alu_i = (int32_t)(r_alu.f);
440 }
441 else
442 {
443 alu_i = (int32_t)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
444 }
445
446 CLEAR_ALU_FLAGS();
447 SET_FLAG_AN(alu_i);
448 // AZ
449 SET_FLAG_AZ(alu_i);
450 // AU
451 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
452 // AI
453 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
454 /* TODO: AV flag */
455
456 REG(rn) = alu_i;
457 m_core->astat |= AF;
458 }
459
460 /* Fn = FLOAT Rx BY Ry */
compute_float_scaled(int rn,int rx,int ry)461 void adsp21062_device::compute_float_scaled(int rn, int rx, int ry)
462 {
463 SHARC_REG x;
464 x.f = (float)(int32_t)(REG(rx));
465
466 // verified
467 CLEAR_ALU_FLAGS();
468
469 REG(rn) = SCALB(x, ry);
470
471 // AN
472 SET_FLAG_AN(REG(rn));
473 // AZ
474 m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0;
475 // AU
476 m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0;
477
478 m_core->astat |= AF;
479 }
480
481 /* Rn = LOGB Fx */
compute_logb(int rn,int rx)482 void adsp21062_device::compute_logb(int rn, int rx)
483 {
484 // verified
485 uint32_t r = REG(rx);
486
487 CLEAR_ALU_FLAGS();
488
489 if (IS_FLOAT_INFINITY(REG(rx)))
490 {
491 REG(rn) = FLOAT_INFINITY;
492
493 m_core->astat |= AV;
494 }
495 else if (IS_FLOAT_ZERO(REG(rx)))
496 {
497 REG(rn) = FLOAT_SIGN | FLOAT_INFINITY;
498
499 m_core->astat |= AV;
500 }
501 else if (IS_FLOAT_NAN(REG(rx)))
502 {
503 REG(rn) = 0xffffffff;
504
505 m_core->astat |= AI;
506 m_core->stky |= AIS;
507 }
508 else
509 {
510 int exponent = (r >> 23) & 0xff;
511 exponent -= 127;
512
513 // AN
514 SET_FLAG_AN(exponent);
515 // AZ
516 SET_FLAG_AZ(exponent);
517
518 REG(rn) = exponent;
519 }
520 m_core->astat |= AF;
521 }
522
523 /* Fn = SCALB Fx BY Fy */
compute_scalb(int rn,int rx,int ry)524 void adsp21062_device::compute_scalb(int rn, int rx, int ry)
525 {
526 // verified
527 SHARC_REG r;
528 CLEAR_ALU_FLAGS();
529
530 if (IS_FLOAT_NAN(REG(rx)))
531 {
532 m_core->astat |= AI;
533 m_core->stky |= AIS;
534
535 REG(rn) = 0xffffffff;
536 }
537 else
538 {
539 r.r = SCALB(m_core->r[rx], ry);
540
541 // AN
542 SET_FLAG_AN(r.r);
543 // AZ
544 m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0;
545 // AUS
546 m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
547
548 FREG(rn) = r.f;
549 }
550 m_core->astat |= AF;
551 }
552
553 /* Fn = Fx + Fy */
compute_fadd(int rn,int rx,int ry)554 void adsp21062_device::compute_fadd(int rn, int rx, int ry)
555 {
556 SHARC_REG r;
557 r.f = FREG(rx) + FREG(ry);
558
559 CLEAR_ALU_FLAGS();
560 // AN
561 m_core->astat |= (r.f < 0.0f) ? AN : 0;
562 // AZ
563 m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
564 // AUS
565 m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
566 // AI
567 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
568 /* TODO: AV flag */
569
570 // AIS
571 if (m_core->astat & AI) m_core->stky |= AIS;
572
573 FREG(rn) = r.f;
574 m_core->astat |= AF;
575 }
576
compute_favg(int rn,int rx,int ry)577 void adsp21062_device::compute_favg(int rn, int rx, int ry)
578 {
579 SHARC_REG r;
580 r.f = (FREG(rx) + FREG(ry)) / (float) 2.0f;
581
582 CLEAR_ALU_FLAGS();
583 // AN
584 m_core->astat |= (r.f < 0.0f) ? AN : 0;
585 // AZ
586 m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
587 // AUS
588 m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
589 // AI
590 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
591 /* TODO: AV flag */
592
593 // AIS
594 if (m_core->astat & AI) m_core->stky |= AIS;
595
596 FREG(rn) = r.f;
597 m_core->astat |= AF;
598 }
599
600 /* Fn = Fx - Fy */
compute_fsub(int rn,int rx,int ry)601 void adsp21062_device::compute_fsub(int rn, int rx, int ry)
602 {
603 SHARC_REG r;
604 r.f = FREG(rx) - FREG(ry);
605
606 CLEAR_ALU_FLAGS();
607 // AN
608 m_core->astat |= (r.f < 0.0f) ? AN : 0;
609 // AZ
610 m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
611 // AUS
612 m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
613 // AI
614 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
615 /* TODO: AV flag */
616
617 // AIS
618 if (m_core->astat & AI) m_core->stky |= AIS;
619
620 FREG(rn) = r.f;
621 m_core->astat |= AF;
622 }
623
624 /* Fn = -Fx */
compute_fneg(int rn,int rx)625 void adsp21062_device::compute_fneg(int rn, int rx)
626 {
627 SHARC_REG r;
628 r.f = -FREG(rx);
629
630 CLEAR_ALU_FLAGS();
631 // AZ
632 m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
633 // AN
634 m_core->astat |= (r.f < 0.0f) ? AN : 0;
635 // AI
636 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
637
638 // AIS
639 if (m_core->astat & AI) m_core->stky |= AIS;
640
641 FREG(rn) = r.f;
642 m_core->astat |= AF;
643 }
644
645 /* COMP(Fx, Fy) */
compute_fcomp(int rx,int ry)646 void adsp21062_device::compute_fcomp(int rx, int ry)
647 {
648 uint32_t comp_accum;
649
650 CLEAR_ALU_FLAGS();
651 // AZ
652 if( FREG(rx) == FREG(ry) )
653 m_core->astat |= AZ;
654 // AN
655 if( FREG(rx) < FREG(ry) )
656 m_core->astat |= AN;
657 // AI
658 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
659
660 // AIS
661 if (m_core->astat & AI) m_core->stky |= AIS;
662
663 // Update ASTAT compare accumulation register
664 comp_accum = (m_core->astat >> 24) & 0xff;
665 comp_accum >>= 1;
666 if ((m_core->astat & (AZ|AN)) == 0)
667 {
668 comp_accum |= 0x80;
669 }
670 m_core->astat &= 0xffffff;
671 m_core->astat |= comp_accum << 24;
672 m_core->astat |= AF;
673 }
674
675 /* Fn = ABS(Fx + Fy) */
compute_fabs_plus(int rn,int rx,int ry)676 void adsp21062_device::compute_fabs_plus(int rn, int rx, int ry)
677 {
678 SHARC_REG r;
679 r.f = fabs(FREG(rx) + FREG(ry));
680
681 CLEAR_ALU_FLAGS();
682 // AZ
683 m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0;
684 // AUS
685 m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0;
686 // AI
687 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
688 /* TODO: AV flag */
689
690 // AIS
691 if (m_core->astat & AI) m_core->stky |= AIS;
692
693 FREG(rn) = r.f;
694 m_core->astat |= AF;
695 }
696
697 /* Fn = MAX(Fx, Fy) */
compute_fmax(int rn,int rx,int ry)698 void adsp21062_device::compute_fmax(int rn, int rx, int ry)
699 {
700 SHARC_REG r_alu;
701
702 r_alu.f = std::max(FREG(rx), FREG(ry));
703
704 CLEAR_ALU_FLAGS();
705 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
706 // AZ
707 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
708 // AU
709 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
710 // AI
711 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
712 /* TODO: AV flag */
713
714 FREG(rn) = r_alu.f;
715 m_core->astat |= AF;
716 }
717
718 /* Fn = MIN(Fx, Fy) */
compute_fmin(int rn,int rx,int ry)719 void adsp21062_device::compute_fmin(int rn, int rx, int ry)
720 {
721 SHARC_REG r_alu;
722
723 r_alu.f = std::min(FREG(rx), FREG(ry));
724
725 CLEAR_ALU_FLAGS();
726 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
727 // AZ
728 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
729 // AU
730 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
731 // AI
732 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
733 /* TODO: AV flag */
734
735 FREG(rn) = r_alu.f;
736 m_core->astat |= AF;
737 }
738
739 /* Fn = COPYSIGN(Fx, Fy) */
compute_fcopysign(int rn,int rx,int ry)740 void adsp21062_device::compute_fcopysign(int rn, int rx, int ry)
741 {
742 SHARC_REG r_alu;
743
744 r_alu.r = (REG(rx) & 0x7fffffff) | (REG(ry) & 0x80000000); // TODO DENORM and NAN cases ?
745
746 CLEAR_ALU_FLAGS();
747 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
748 // AZ
749 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
750 // AI
751 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
752
753 FREG(rn) = r_alu.f;
754 m_core->astat |= AF;
755 }
756
757 /* Fn = CLIP Fx BY Fy */
compute_fclip(int rn,int rx,int ry)758 void adsp21062_device::compute_fclip(int rn, int rx, int ry)
759 {
760 SHARC_REG r_alu;
761
762 if (FREG(rx) < fabsf(FREG(ry)))
763 {
764 r_alu.f = FREG(rx);
765 }
766 else
767 {
768 if (FREG(rx) >= 0.0f)
769 {
770 r_alu.f = fabsf(FREG(ry));
771 }
772 else
773 {
774 r_alu.f = -fabsf(FREG(ry));
775 }
776 }
777
778
779 CLEAR_ALU_FLAGS();
780 SET_FLAG_AN(r_alu.r);
781 // AZ
782 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
783 // AU
784 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
785 // AI
786 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
787
788 FREG(rn) = r_alu.f;
789 m_core->astat |= AF;
790 }
791
792 /* Fn = RECIPS Fx */
compute_recips(int rn,int rx)793 void adsp21062_device::compute_recips(int rn, int rx)
794 {
795 // verified
796 uint32_t r;
797
798 CLEAR_ALU_FLAGS();
799
800 if (IS_FLOAT_NAN(REG(rx)))
801 {
802 // NaN
803 r = 0xffffffff;
804
805 // AI
806 m_core->astat |= AI;
807
808 // AIS
809 m_core->stky |= AIS;
810 }
811 else if (IS_FLOAT_ZERO(REG(rx)))
812 {
813 // +- Zero
814 r = (REG(rx) & FLOAT_SIGN) | FLOAT_INFINITY;
815
816 m_core->astat |= AZ;
817 }
818 else
819 {
820 uint32_t mantissa = REG(rx) & 0x7fffff;
821 uint32_t exponent = (REG(rx) >> 23) & 0xff;
822 uint32_t sign = REG(rx) & FLOAT_SIGN;
823
824 uint32_t res_mantissa = recips_mantissa_lookup[mantissa >> 16];
825
826 int res_exponent = -(exponent - 127) - 1;
827 if (res_exponent > 125 || res_exponent < -126)
828 {
829 res_exponent = 0;
830 res_mantissa = 0;
831 }
832 else
833 {
834 res_exponent = (res_exponent + 127) & 0xff;
835 }
836
837 r = sign | (res_exponent << 23) | res_mantissa;
838
839 SET_FLAG_AN(REG(rx));
840 // AZ & AV
841 m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
842 m_core->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0;
843 // AI
844 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
845
846 // AIS
847 if (m_core->astat & AI) m_core->stky |= AIS;
848 }
849
850 // AF
851 m_core->astat |= AF;
852
853 REG(rn) = r;
854 }
855
856 /* Fn = RSQRTS Fx */
compute_rsqrts(int rn,int rx)857 void adsp21062_device::compute_rsqrts(int rn, int rx)
858 {
859 // verified
860 uint32_t r;
861
862 if ((uint32_t)(REG(rx)) > 0x80000000)
863 {
864 // non-zero negative
865 r = 0xffffffff;
866 }
867 else if (IS_FLOAT_NAN(REG(rx)))
868 {
869 // NaN
870 r = 0xffffffff;
871 }
872 else
873 {
874 uint32_t mantissa = REG(rx) & 0xffffff; // mantissa + LSB of biased exponent
875 uint32_t exponent = (REG(rx) >> 23) & 0xff;
876 uint32_t sign = REG(rx) & FLOAT_SIGN;
877
878 uint32_t res_mantissa = rsqrts_mantissa_lookup[mantissa >> 17];
879
880 int res_exponent = -((exponent - 127) / 2) - 1;
881 res_exponent = (res_exponent + 127) & 0xff;
882
883 r = sign | (res_exponent << 23) | res_mantissa;
884 }
885
886 CLEAR_ALU_FLAGS();
887 // AN
888 m_core->astat |= (REG(rx) == 0x80000000) ? AN : 0;
889 // AZ & AV
890 m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0;
891 m_core->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0;
892 // AI
893 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & 0x80000000)) ? AI : 0;
894 // AIS
895 if (m_core->astat & AI) m_core->stky |= AIS;
896 // AF
897 m_core->astat |= AF;
898
899 REG(rn) = r;
900 }
901
902
903 /* Fn = PASS Fx */
compute_fpass(int rn,int rx)904 void adsp21062_device::compute_fpass(int rn, int rx)
905 {
906 SHARC_REG r;
907 r.f = FREG(rx);
908
909 CLEAR_ALU_FLAGS();
910 // AN
911 m_core->astat |= (r.f < 0.0f) ? AN : 0;
912 // AZ
913 m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
914 // AI
915 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
916
917 FREG(rn) = r.f;
918 m_core->astat |= AF;
919 }
920
921 /* Fn = ABS Fx */
compute_fabs(int rn,int rx)922 void adsp21062_device::compute_fabs(int rn, int rx)
923 {
924 SHARC_REG r;
925 r.f = fabs(FREG(rx));
926
927 CLEAR_ALU_FLAGS();
928 // AN
929 m_core->astat |= (r.f < 0.0f) ? AN : 0;
930 // AZ
931 m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0;
932 // AI
933 m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0;
934
935 FREG(rn) = r.f;
936 m_core->astat |= AF;
937 }
938
939 /*****************************************************************************/
940 /* Multiplier opcodes */
941
942 /* Rn = (unsigned)Rx * (unsigned)Ry, integer, no rounding */
compute_mul_uuin(int rn,int rx,int ry)943 void adsp21062_device::compute_mul_uuin(int rn, int rx, int ry)
944 {
945 uint64_t r = (uint64_t)(uint32_t)REG(rx) * (uint64_t)(uint32_t)REG(ry);
946
947 CLEAR_MULTIPLIER_FLAGS();
948 SET_FLAG_MN((uint32_t)r);
949 SET_FLAG_MV(r);
950 SET_FLAG_MU(r);
951
952 REG(rn) = (uint32_t)(r);
953 }
954
955 /* Rn = (signed)Rx * (signed)Ry, integer, no rounding */
compute_mul_ssin(int rn,int rx,int ry)956 void adsp21062_device::compute_mul_ssin(int rn, int rx, int ry)
957 {
958 uint64_t r = (int64_t)(int32_t)REG(rx) * (int64_t)(int32_t)REG(ry);
959
960 CLEAR_MULTIPLIER_FLAGS();
961 SET_FLAG_MN((uint32_t)r);
962 SET_FLAG_MV(r);
963 SET_FLAG_MU(r);
964
965 REG(rn) = (uint32_t)(r);
966 }
967
968 /* MRF + (signed)Rx * (signed)Ry, integer, no rounding */
compute_mrf_plus_mul_ssin(int rx,int ry)969 uint32_t adsp21062_device::compute_mrf_plus_mul_ssin(int rx, int ry)
970 {
971 uint64_t r = m_core->mrf + ((int64_t)(int32_t)REG(rx) * (int64_t)(int32_t)REG(ry));
972
973 CLEAR_MULTIPLIER_FLAGS();
974 SET_FLAG_MN((uint32_t)r);
975 SET_FLAG_MV(r);
976 SET_FLAG_MU(r);
977
978 return (uint32_t)(r);
979 }
980
981 /* MRB + (signed)Rx * (signed)Ry, integer, no rounding */
compute_mrb_plus_mul_ssin(int rx,int ry)982 uint32_t adsp21062_device::compute_mrb_plus_mul_ssin(int rx, int ry)
983 {
984 int64_t r = m_core->mrb + ((int64_t)(int32_t)REG(rx) * (int64_t)(int32_t)REG(ry));
985
986 CLEAR_MULTIPLIER_FLAGS();
987 SET_FLAG_MN((uint32_t)r);
988 SET_FLAG_MV(r);
989 SET_FLAG_MU(r);
990
991 return (uint32_t)(r);
992 }
993
994 /* Fn = Fx * Fy */
compute_fmul(int rn,int rx,int ry)995 void adsp21062_device::compute_fmul(int rn, int rx, int ry)
996 {
997 FREG(rn) = FREG(rx) * FREG(ry);
998
999 CLEAR_MULTIPLIER_FLAGS();
1000 SET_FLAG_MN(REG(rn));
1001 /* TODO: MV flag */
1002 /* TODO: MU flag */
1003 /* TODO: MI flag */
1004 }
1005
1006 /*****************************************************************************/
1007
1008 /* multi function opcodes */
1009
1010 /* integer*/
compute_multi_mr_to_reg(int ai,int rk)1011 void adsp21062_device::compute_multi_mr_to_reg(int ai, int rk)
1012 {
1013 switch(ai)
1014 {
1015 case 0: SET_UREG(rk, (uint32_t)(m_core->mrf)); break;
1016 case 1: SET_UREG(rk, (uint32_t)(m_core->mrf >> 32)); break;
1017 case 2: fatalerror("SHARC: tried to load MR2F\n"); break;
1018 case 4: SET_UREG(rk, (uint32_t)(m_core->mrb)); break;
1019 case 5: SET_UREG(rk, (uint32_t)(m_core->mrb >> 32)); break;
1020 case 6: fatalerror("SHARC: tried to load MR2B\n"); break;
1021 default: fatalerror("SHARC: unknown ai %d in mr_to_reg\n", ai);
1022 }
1023
1024 CLEAR_MULTIPLIER_FLAGS();
1025 }
1026
compute_multi_reg_to_mr(int ai,int rk)1027 void adsp21062_device::compute_multi_reg_to_mr(int ai, int rk)
1028 {
1029 switch(ai)
1030 {
1031 case 0: m_core->mrf &= ~0xffffffff; m_core->mrf |= GET_UREG(rk); break;
1032 case 1: m_core->mrf &= 0xffffffff; m_core->mrf |= (uint64_t)(GET_UREG(rk)) << 32; break;
1033 case 2: fatalerror("SHARC: tried to write MR2F\n"); break;
1034 case 4: m_core->mrb &= ~0xffffffff; m_core->mrb |= GET_UREG(rk); break;
1035 case 5: m_core->mrb &= 0xffffffff; m_core->mrb |= (uint64_t)(GET_UREG(rk)) << 32; break;
1036 case 6: fatalerror("SHARC: tried to write MR2B\n"); break;
1037 default: fatalerror("SHARC: unknown ai %d in reg_to_mr\n", ai);
1038 }
1039
1040 CLEAR_MULTIPLIER_FLAGS();
1041 }
1042
1043 /* Ra = Rx + Ry, Rs = Rx - Ry */
compute_dual_add_sub(int ra,int rs,int rx,int ry)1044 void adsp21062_device::compute_dual_add_sub(int ra, int rs, int rx, int ry)
1045 {
1046 uint32_t r_add = REG(rx) + REG(ry);
1047 uint32_t r_sub = REG(rx) - REG(ry);
1048
1049 CLEAR_ALU_FLAGS();
1050 if (r_add == 0 || r_sub == 0)
1051 {
1052 m_core->astat |= AZ;
1053 }
1054 if (r_add & 0x80000000 || r_sub & 0x80000000)
1055 {
1056 m_core->astat |= AN;
1057 }
1058 if (((~(REG(rx) ^ REG(ry)) & (REG(rx) ^ r_add)) & 0x80000000) ||
1059 (( (REG(rx) ^ REG(ry)) & (REG(rx) ^ r_sub)) & 0x80000000))
1060 {
1061 m_core->astat |= AV;
1062 }
1063 if (((uint32_t)r_add < (uint32_t)REG(rx)) ||
1064 (!((uint32_t)r_sub < (uint32_t)REG(rx))))
1065 {
1066 m_core->astat |= AC;
1067 }
1068
1069 REG(ra) = r_add;
1070 REG(rs) = r_sub;
1071
1072 m_core->astat &= ~AF;
1073 }
1074
1075 /* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa + Rya */
compute_mul_ssfr_add(int rm,int rxm,int rym,int ra,int rxa,int rya)1076 void adsp21062_device::compute_mul_ssfr_add(int rm, int rxm, int rym, int ra, int rxa, int rya)
1077 {
1078 uint32_t r_mul = (uint32_t)(((int64_t)(REG(rxm)) * (int64_t)(REG(rym))) >> 31);
1079 uint32_t r_add = REG(rxa) + REG(rya);
1080
1081 CLEAR_MULTIPLIER_FLAGS();
1082 SET_FLAG_MN(r_mul);
1083 /* TODO: MV flag */
1084 /* TODO: MU flag */
1085 /* TODO: MI flag */
1086
1087 CLEAR_ALU_FLAGS();
1088 SET_FLAG_AN(r_add);
1089 SET_FLAG_AZ(r_add);
1090 SET_FLAG_AV_ADD(r_add, REG(rxa), REG(rya));
1091 SET_FLAG_AC_ADD(r_add, REG(rxa), REG(rya));
1092
1093
1094 REG(rm) = r_mul;
1095 REG(ra) = r_add;
1096
1097 m_core->astat &= ~AF;
1098 }
1099
1100 /* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa - Rya */
compute_mul_ssfr_sub(int rm,int rxm,int rym,int ra,int rxa,int rya)1101 void adsp21062_device::compute_mul_ssfr_sub(int rm, int rxm, int rym, int ra, int rxa, int rya)
1102 {
1103 uint32_t r_mul = (uint32_t)(((int64_t)(REG(rxm)) * (int64_t)(REG(rym))) >> 31);
1104 uint32_t r_sub = REG(rxa) - REG(rya);
1105
1106 CLEAR_MULTIPLIER_FLAGS();
1107 SET_FLAG_MN(r_mul);
1108 /* TODO: MV flag */
1109 /* TODO: MU flag */
1110 /* TODO: MI flag */
1111
1112 CLEAR_ALU_FLAGS();
1113 SET_FLAG_AN(r_sub);
1114 SET_FLAG_AZ(r_sub);
1115 SET_FLAG_AV_SUB(r_sub, REG(rxa), REG(rya));
1116 SET_FLAG_AC_SUB(r_sub, REG(rxa), REG(rya));
1117
1118
1119 REG(rm) = r_mul;
1120 REG(ra) = r_sub;
1121
1122 m_core->astat &= ~AF;
1123 }
1124
1125
1126 /* floating-point */
1127
1128 /* Fa = Fx + Fy, Fs = Fx - Fy */
compute_dual_fadd_fsub(int ra,int rs,int rx,int ry)1129 void adsp21062_device::compute_dual_fadd_fsub(int ra, int rs, int rx, int ry)
1130 {
1131 SHARC_REG r_add, r_sub;
1132 r_add.f = FREG(rx) + FREG(ry);
1133 r_sub.f = FREG(rx) - FREG(ry);
1134
1135 CLEAR_ALU_FLAGS();
1136 // AN
1137 m_core->astat |= ((r_add.f < 0.0f) || (r_sub.f < 0.0f)) ? AN : 0;
1138 // AZ
1139 m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) ||
1140 IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
1141 // AUS
1142 m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
1143 // AI
1144 m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0;
1145 /* TODO: AV flag */
1146
1147 // AIS
1148 if (m_core->astat & AI) m_core->stky |= AIS;
1149
1150 FREG(ra) = r_add.f;
1151 FREG(rs) = r_sub.f;
1152 m_core->astat |= AF;
1153 }
1154
1155 /* Fm = Fxm * Fym, Fa = Fxa + Fya */
compute_fmul_fadd(int fm,int fxm,int fym,int fa,int fxa,int fya)1156 void adsp21062_device::compute_fmul_fadd(int fm, int fxm, int fym, int fa, int fxa, int fya)
1157 {
1158 SHARC_REG r_mul, r_add;
1159 r_mul.f = FREG(fxm) * FREG(fym);
1160 r_add.f = FREG(fxa) + FREG(fya);
1161
1162 CLEAR_MULTIPLIER_FLAGS();
1163 SET_FLAG_MN(r_mul.r);
1164 /* TODO: MV flag */
1165 /* TODO: MU flag */
1166 /* TODO: MI flag */
1167
1168 CLEAR_ALU_FLAGS();
1169 m_core->astat |= (r_add.f < 0.0f) ? AN : 0;
1170 // AZ
1171 m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r)) ? AZ : 0;
1172 // AU
1173 m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r)) ? AUS : 0;
1174 // AI
1175 m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
1176 /* TODO: AV flag */
1177
1178 // AIS
1179 if (m_core->astat & AI) m_core->stky |= AIS;
1180
1181 FREG(fm) = r_mul.f;
1182 FREG(fa) = r_add.f;
1183 m_core->astat |= AF;
1184 }
1185
1186 /* Fm = Fxm * Fym, Fa = Fxa - Fya */
compute_fmul_fsub(int fm,int fxm,int fym,int fa,int fxa,int fya)1187 void adsp21062_device::compute_fmul_fsub(int fm, int fxm, int fym, int fa, int fxa, int fya)
1188 {
1189 SHARC_REG r_mul, r_sub;
1190 r_mul.f = FREG(fxm) * FREG(fym);
1191 r_sub.f = FREG(fxa) - FREG(fya);
1192
1193 CLEAR_MULTIPLIER_FLAGS();
1194 SET_FLAG_MN(r_mul.r);
1195 /* TODO: MV flag */
1196 /* TODO: MU flag */
1197 /* TODO: MI flag */
1198
1199 CLEAR_ALU_FLAGS();
1200 m_core->astat |= (r_sub.f < 0.0f) ? AN : 0;
1201 // AZ
1202 m_core->astat |= (IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
1203 // AU
1204 m_core->stky |= (IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
1205 // AI
1206 m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
1207 /* TODO: AV flag */
1208
1209 // AIS
1210 if (m_core->astat & AI) m_core->stky |= AIS;
1211
1212 FREG(fm) = r_mul.f;
1213 FREG(fa) = r_sub.f;
1214 m_core->astat |= AF;
1215 }
1216
1217 /* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */
compute_fmul_float_scaled(int fm,int fxm,int fym,int fa,int fxa,int fya)1218 void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int fa, int fxa, int fya)
1219 {
1220 SHARC_REG x;
1221 SHARC_REG r_mul, r_alu;
1222 r_mul.f = FREG(fxm) * FREG(fym);
1223
1224 x.f = (float)(int32_t)REG(fxa);
1225
1226 r_alu.r = SCALB(x, fya);
1227
1228 CLEAR_MULTIPLIER_FLAGS();
1229 SET_FLAG_MN(r_mul.r);
1230 /* TODO: MV flag */
1231 /* TODO: MU flag */
1232 /* TODO: MI flag */
1233
1234 CLEAR_ALU_FLAGS();
1235 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
1236 // AZ
1237 m_core->astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
1238 // AU
1239 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1240 /* TODO: set AV if overflowed */
1241
1242 FREG(fm) = r_mul.f;
1243 FREG(fa) = r_alu.f;
1244 m_core->astat |= AF;
1245 }
1246
1247 /* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */
compute_fmul_fix_scaled(int fm,int fxm,int fym,int fa,int fxa,int fya)1248 void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int fa, int fxa, int fya)
1249 {
1250 int32_t alu_i;
1251 SHARC_REG r_mul, r_alu;
1252 r_mul.f = FREG(fxm) * FREG(fym);
1253
1254 r_alu.r = SCALB(m_core->r[fxa], fya);
1255
1256 if (m_core->mode1 & MODE1_TRUNCATE)
1257 {
1258 alu_i = (int32_t)(r_alu.f);
1259 }
1260 else
1261 {
1262 alu_i = (int32_t)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
1263 }
1264
1265 CLEAR_MULTIPLIER_FLAGS();
1266 SET_FLAG_MN(r_mul.r);
1267 /* TODO: MV flag */
1268 /* TODO: MU flag */
1269 /* TODO: MI flag */
1270
1271 CLEAR_ALU_FLAGS();
1272 SET_FLAG_AN(alu_i);
1273 // AZ
1274 SET_FLAG_AZ(alu_i);
1275 // AU
1276 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1277 // AI
1278 m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0;
1279 /* TODO: AV flag */
1280
1281 FREG(fm) = r_mul.f;
1282 REG(fa) = alu_i; // TODO: check this, should be RA?
1283 m_core->astat |= AF;
1284 }
1285
compute_fmul_avg(int fm,int fxm,int fym,int fa,int fxa,int fya)1286 void adsp21062_device::compute_fmul_avg(int fm, int fxm, int fym, int fa, int fxa, int fya)
1287 {
1288 int32_t alu_i;
1289 SHARC_REG r_mul, r_alu;
1290 r_mul.f = FREG(fxm) * FREG(fym);
1291 r_alu.f = (FREG(fxa) + FREG(fya))/((float) 2.0);
1292
1293 // TODO: are flags right for this?
1294 if (m_core->mode1 & MODE1_TRUNCATE)
1295 {
1296 alu_i = (int32_t)(r_alu.f);
1297 }
1298 else
1299 {
1300 alu_i = (int32_t)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
1301 }
1302
1303 CLEAR_MULTIPLIER_FLAGS();
1304 SET_FLAG_MN(r_mul.r);
1305 /* TODO: MV flag */
1306 /* TODO: MU flag */
1307 /* TODO: MI flag */
1308
1309 CLEAR_ALU_FLAGS();
1310 SET_FLAG_AN(alu_i);
1311 // AZ
1312 SET_FLAG_AZ(alu_i);
1313 // AU
1314 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1315 // AI
1316 m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0;
1317 /* TODO: AV flag */
1318
1319 FREG(fm) = r_mul.f;
1320 REG(fa) = alu_i;
1321 m_core->astat |= AF;
1322 }
1323
compute_fmul_abs(int fm,int fxm,int fym,int fa,int fxa,int fya)1324 void adsp21062_device::compute_fmul_abs(int fm, int fxm, int fym, int fa, int fxa, int fya)
1325 {
1326 int32_t alu_i;
1327 SHARC_REG r_mul, r_alu;
1328 r_mul.f = FREG(fxm) * FREG(fym);
1329 r_alu.f = (float) fabs(FREG(fxa));
1330
1331 // TODO: are flags right for this?
1332 if (m_core->mode1 & MODE1_TRUNCATE)
1333 {
1334 alu_i = (int32_t)(r_alu.f);
1335 }
1336 else
1337 {
1338 alu_i = (int32_t)(r_alu.f < 0 ? (r_alu.f - 0.5f) : (r_alu.f + 0.5f));
1339 }
1340
1341 CLEAR_MULTIPLIER_FLAGS();
1342 SET_FLAG_MN(r_mul.r);
1343 /* TODO: MV flag */
1344 /* TODO: MU flag */
1345 /* TODO: MI flag */
1346
1347 CLEAR_ALU_FLAGS();
1348 SET_FLAG_AN(alu_i);
1349 // AZ
1350 SET_FLAG_AZ(alu_i);
1351 // AU
1352 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1353 // AI
1354 m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0;
1355 /* TODO: AV flag */
1356
1357 FREG(fm) = r_mul.f;
1358 REG(fa) = alu_i;
1359 m_core->astat |= AF;
1360 }
1361
1362 /* Fm = Fxm * Fym, Fa = MAX(Fxa, Fya) */
compute_fmul_fmax(int fm,int fxm,int fym,int fa,int fxa,int fya)1363 void adsp21062_device::compute_fmul_fmax(int fm, int fxm, int fym, int fa, int fxa, int fya)
1364 {
1365 SHARC_REG r_mul, r_alu;
1366 r_mul.f = FREG(fxm) * FREG(fym);
1367
1368 r_alu.f = std::max(FREG(fxa), FREG(fya));
1369
1370 CLEAR_MULTIPLIER_FLAGS();
1371 SET_FLAG_MN(r_mul.r);
1372 /* TODO: MV flag */
1373 /* TODO: MU flag */
1374 /* TODO: MI flag */
1375
1376 CLEAR_ALU_FLAGS();
1377 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
1378 // AZ
1379 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
1380 // AU
1381 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1382 // AI
1383 m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
1384 /* TODO: AV flag */
1385
1386 FREG(fm) = r_mul.f;
1387 FREG(fa) = r_alu.f;
1388 m_core->astat |= AF;
1389 }
1390
1391
1392 /* Fm = Fxm * Fym, Fa = MIN(Fxa, Fya) */
compute_fmul_fmin(int fm,int fxm,int fym,int fa,int fxa,int fya)1393 void adsp21062_device::compute_fmul_fmin(int fm, int fxm, int fym, int fa, int fxa, int fya)
1394 {
1395 SHARC_REG r_mul, r_alu;
1396 r_mul.f = FREG(fxm) * FREG(fym);
1397
1398 r_alu.f = std::min(FREG(fxa), FREG(fya));
1399
1400 CLEAR_MULTIPLIER_FLAGS();
1401 SET_FLAG_MN(r_mul.r);
1402 /* TODO: MV flag */
1403 /* TODO: MU flag */
1404 /* TODO: MI flag */
1405
1406 CLEAR_ALU_FLAGS();
1407 m_core->astat |= (r_alu.f < 0.0f) ? AN : 0;
1408 // AZ
1409 m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0;
1410 // AU
1411 m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0;
1412 // AI
1413 m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
1414 /* TODO: AV flag */
1415
1416 FREG(fm) = r_mul.f;
1417 FREG(fa) = r_alu.f;
1418 m_core->astat |= AF;
1419 }
1420
1421
1422
1423 /* Fm = Fxm * Fym, Fa = Fxa + Fya, Fs = Fxa - Fya */
compute_fmul_dual_fadd_fsub(int fm,int fxm,int fym,int fa,int fs,int fxa,int fya)1424 void adsp21062_device::compute_fmul_dual_fadd_fsub(int fm, int fxm, int fym, int fa, int fs, int fxa, int fya)
1425 {
1426 SHARC_REG r_mul, r_add, r_sub;
1427 r_mul.f = FREG(fxm) * FREG(fym);
1428 r_add.f = FREG(fxa) + FREG(fya);
1429 r_sub.f = FREG(fxa) - FREG(fya);
1430
1431 CLEAR_MULTIPLIER_FLAGS();
1432 SET_FLAG_MN(r_mul.r);
1433 /* TODO: MV flag */
1434 /* TODO: MU flag */
1435 /* TODO: MI flag */
1436
1437 CLEAR_ALU_FLAGS();
1438 // AN
1439 m_core->astat |= ((r_add.r < 0.0f) || (r_sub.r < 0.0f)) ? AN : 0;
1440 // AZ
1441 m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) ||
1442 IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0;
1443 // AUS
1444 m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0;
1445 // AI
1446 m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0;
1447 /* TODO: AV flag */
1448
1449 // AIS
1450 if (m_core->astat & AI) m_core->stky |= AIS;
1451
1452 FREG(fm) = r_mul.f;
1453 FREG(fa) = r_add.f;
1454 FREG(fs) = r_sub.f;
1455 m_core->astat |= AF;
1456 }
1457