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