sim: unify reserved instruction bits settings
[deliverable/binutils-gdb.git] / sim / mips / mdmx.c
CommitLineData
f4f1b9f1 1/* Simulation code for the MIPS MDMX ASE.
3666a048 2 Copyright (C) 2002-2021 Free Software Foundation, Inc.
dd69d292
CD
3 Contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
4 Corporation (SiByte).
f4f1b9f1
CD
5
6This file is part of GDB, the GNU debugger.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
4744ac1b
JB
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
f4f1b9f1
CD
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
4744ac1b
JB
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
f4f1b9f1 20
6df01ab8
MF
21/* This must come before any other includes. */
22#include "defs.h"
23
f4f1b9f1
CD
24#include <stdio.h>
25
26#include "sim-main.h"
27
28/* Within mdmx.c we refer to the sim_cpu directly. */
29#define CPU cpu
30#define SD (CPU_STATE(CPU))
a2f8b4f3
CD
31
32/* XXX FIXME: temporary hack while the impact of making unpredictable()
33 a "normal" (non-igen) function is evaluated. */
34#undef Unpredictable
35#define Unpredictable() unpredictable_action (cpu, cia)
f4f1b9f1
CD
36
37/* MDMX Representations
38
39 An 8-bit packed byte element (OB) is always unsigned.
40 The 24-bit accumulators are signed and are represented as 32-bit
41 signed values, which are reduced to 24-bit signed values prior to
42 Round and Clamp operations.
43
44 A 16-bit packed halfword element (QH) is always signed.
45 The 48-bit accumulators are signed and are represented as 64-bit
46 signed values, which are reduced to 48-bit signed values prior to
47 Round and Clamp operations.
48
49 The code below assumes a 2's-complement representation of signed
50 quantities. Care is required to clear extended sign bits when
51 repacking fields.
52
53 The code (and the code for arithmetic shifts in mips.igen) also makes
54 the (not guaranteed portable) assumption that right shifts of signed
55 quantities in C do sign extension. */
56
57typedef unsigned64 unsigned48;
58#define MASK48 (UNSIGNED64 (0xffffffffffff))
59
60typedef unsigned32 unsigned24;
61#define MASK24 (UNSIGNED32 (0xffffff))
62
63typedef enum {
64 mdmx_ob, /* OB (octal byte) */
65 mdmx_qh /* QH (quad half-word) */
66} MX_fmt;
67
68typedef enum {
69 sel_elem, /* element select */
70 sel_vect, /* vector select */
71 sel_imm /* immediate select */
72} VT_select;
73
74#define OB_MAX ((unsigned8)0xFF)
75#define QH_MIN ((signed16)0x8000)
76#define QH_MAX ((signed16)0x7FFF)
77
78#define OB_CLAMP(x) ((unsigned8)((x) > OB_MAX ? OB_MAX : (x)))
79#define QH_CLAMP(x) ((signed16)((x) < QH_MIN ? QH_MIN : \
80 ((x) > QH_MAX ? QH_MAX : (x))))
81
82#define MX_FMT(fmtsel) (((fmtsel) & 0x1) == 0 ? mdmx_ob : mdmx_qh)
83#define MX_VT(fmtsel) (((fmtsel) & 0x10) == 0 ? sel_elem : \
84 (((fmtsel) & 0x18) == 0x10 ? sel_vect : sel_imm))
85
86#define QH_ELEM(v,fmtsel) \
87 ((signed16)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF))
88#define OB_ELEM(v,fmtsel) \
89 ((unsigned8)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF))
90
91
92typedef signed16 (*QH_FUNC)(signed16, signed16);
93typedef unsigned8 (*OB_FUNC)(unsigned8, unsigned8);
94
95/* vectorized logical operators */
96
97static signed16
98AndQH(signed16 ts, signed16 tt)
99{
100 return (signed16)((unsigned16)ts & (unsigned16)tt);
101}
102
103static unsigned8
104AndOB(unsigned8 ts, unsigned8 tt)
105{
106 return ts & tt;
107}
108
109static signed16
110NorQH(signed16 ts, signed16 tt)
111{
112 return (signed16)(((unsigned16)ts | (unsigned16)tt) ^ 0xFFFF);
113}
114
115static unsigned8
116NorOB(unsigned8 ts, unsigned8 tt)
117{
118 return (ts | tt) ^ 0xFF;
119}
120
121static signed16
122OrQH(signed16 ts, signed16 tt)
123{
124 return (signed16)((unsigned16)ts | (unsigned16)tt);
125}
126
127static unsigned8
128OrOB(unsigned8 ts, unsigned8 tt)
129{
130 return ts | tt;
131}
132
133static signed16
134XorQH(signed16 ts, signed16 tt)
135{
136 return (signed16)((unsigned16)ts ^ (unsigned16)tt);
137}
138
139static unsigned8
140XorOB(unsigned8 ts, unsigned8 tt)
141{
142 return ts ^ tt;
143}
144
145static signed16
146SLLQH(signed16 ts, signed16 tt)
147{
148 unsigned32 s = (unsigned32)tt & 0xF;
149 return (signed16)(((unsigned32)ts << s) & 0xFFFF);
150}
151
152static unsigned8
153SLLOB(unsigned8 ts, unsigned8 tt)
154{
155 unsigned32 s = tt & 0x7;
156 return (ts << s) & 0xFF;
157}
158
159static signed16
160SRLQH(signed16 ts, signed16 tt)
161{
162 unsigned32 s = (unsigned32)tt & 0xF;
163 return (signed16)((unsigned16)ts >> s);
164}
165
166static unsigned8
167SRLOB(unsigned8 ts, unsigned8 tt)
168{
169 unsigned32 s = tt & 0x7;
170 return ts >> s;
171}
172
173
174/* Vectorized arithmetic operators. */
175
176static signed16
177AddQH(signed16 ts, signed16 tt)
178{
179 signed32 t = (signed32)ts + (signed32)tt;
180 return QH_CLAMP(t);
181}
182
183static unsigned8
184AddOB(unsigned8 ts, unsigned8 tt)
185{
186 unsigned32 t = (unsigned32)ts + (unsigned32)tt;
187 return OB_CLAMP(t);
188}
189
190static signed16
191SubQH(signed16 ts, signed16 tt)
192{
193 signed32 t = (signed32)ts - (signed32)tt;
194 return QH_CLAMP(t);
195}
196
197static unsigned8
198SubOB(unsigned8 ts, unsigned8 tt)
199{
200 signed32 t;
201 t = (signed32)ts - (signed32)tt;
202 if (t < 0)
203 t = 0;
204 return (unsigned8)t;
205}
206
207static signed16
208MinQH(signed16 ts, signed16 tt)
209{
210 return (ts < tt ? ts : tt);
211}
212
213static unsigned8
214MinOB(unsigned8 ts, unsigned8 tt)
215{
216 return (ts < tt ? ts : tt);
217}
218
219static signed16
220MaxQH(signed16 ts, signed16 tt)
221{
222 return (ts > tt ? ts : tt);
223}
224
225static unsigned8
226MaxOB(unsigned8 ts, unsigned8 tt)
227{
228 return (ts > tt ? ts : tt);
229}
230
231static signed16
232MulQH(signed16 ts, signed16 tt)
233{
234 signed32 t = (signed32)ts * (signed32)tt;
235 return QH_CLAMP(t);
236}
237
238static unsigned8
239MulOB(unsigned8 ts, unsigned8 tt)
240{
241 unsigned32 t = (unsigned32)ts * (unsigned32)tt;
242 return OB_CLAMP(t);
243}
244
245/* "msgn" and "sra" are defined only for QH format. */
246
247static signed16
248MsgnQH(signed16 ts, signed16 tt)
249{
250 signed16 t;
251 if (ts < 0)
252 t = (tt == QH_MIN ? QH_MAX : -tt);
253 else if (ts == 0)
254 t = 0;
255 else
256 t = tt;
257 return t;
258}
259
f4f1b9f1
CD
260static signed16
261SRAQH(signed16 ts, signed16 tt)
262{
263 unsigned32 s = (unsigned32)tt & 0xF;
264 return (signed16)((signed32)ts >> s);
265}
266
267
7cbea089
CD
268/* "pabsdiff" and "pavg" are defined only for OB format. */
269
270static unsigned8
271AbsDiffOB(unsigned8 ts, unsigned8 tt)
272{
273 return (ts >= tt ? ts - tt : tt - ts);
274}
275
276static unsigned8
277AvgOB(unsigned8 ts, unsigned8 tt)
278{
279 return ((unsigned32)ts + (unsigned32)tt + 1) >> 1;
280}
281
282
f4f1b9f1
CD
283/* Dispatch tables for operations that update a CPR. */
284
285static const QH_FUNC qh_func[] = {
286 AndQH, NorQH, OrQH, XorQH, SLLQH, SRLQH,
287 AddQH, SubQH, MinQH, MaxQH,
288 MulQH, MsgnQH, SRAQH, NULL, NULL
289};
290
291static const OB_FUNC ob_func[] = {
292 AndOB, NorOB, OrOB, XorOB, SLLOB, SRLOB,
293 AddOB, SubOB, MinOB, MaxOB,
7cbea089 294 MulOB, NULL, NULL, AbsDiffOB, AvgOB
f4f1b9f1
CD
295};
296
297/* Auxiliary functions for CPR updates. */
298
299/* Vector mapping for QH format. */
300static unsigned64
301qh_vector_op(unsigned64 v1, unsigned64 v2, QH_FUNC func)
302{
303 unsigned64 result = 0;
304 int i;
305 signed16 h, h1, h2;
306
307 for (i = 0; i < 64; i += 16)
308 {
309 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
310 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
311 h = (*func)(h1, h2);
312 result |= ((unsigned64)((unsigned16)h) << i);
313 }
314 return result;
315}
316
317static unsigned64
318qh_map_op(unsigned64 v1, signed16 h2, QH_FUNC func)
319{
320 unsigned64 result = 0;
321 int i;
322 signed16 h, h1;
323
324 for (i = 0; i < 64; i += 16)
325 {
326 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
327 h = (*func)(h1, h2);
328 result |= ((unsigned64)((unsigned16)h) << i);
329 }
330 return result;
331}
332
333
334/* Vector operations for OB format. */
335
336static unsigned64
337ob_vector_op(unsigned64 v1, unsigned64 v2, OB_FUNC func)
338{
339 unsigned64 result = 0;
340 int i;
341 unsigned8 b, b1, b2;
342
343 for (i = 0; i < 64; i += 8)
344 {
345 b1 = v1 & 0xFF; v1 >>= 8;
346 b2 = v2 & 0xFF; v2 >>= 8;
347 b = (*func)(b1, b2);
348 result |= ((unsigned64)b << i);
349 }
350 return result;
351}
352
353static unsigned64
354ob_map_op(unsigned64 v1, unsigned8 b2, OB_FUNC func)
355{
356 unsigned64 result = 0;
357 int i;
358 unsigned8 b, b1;
359
360 for (i = 0; i < 64; i += 8)
361 {
362 b1 = v1 & 0xFF; v1 >>= 8;
363 b = (*func)(b1, b2);
364 result |= ((unsigned64)b << i);
365 }
366 return result;
367}
368
369
370/* Primary entry for operations that update CPRs. */
371unsigned64
372mdmx_cpr_op(sim_cpu *cpu,
373 address_word cia,
374 int op,
375 unsigned64 op1,
376 int vt,
377 MX_fmtsel fmtsel)
378{
379 unsigned64 op2;
380 unsigned64 result = 0;
381
382 switch (MX_FMT (fmtsel))
383 {
384 case mdmx_qh:
385 switch (MX_VT (fmtsel))
386 {
387 case sel_elem:
388 op2 = ValueFPR(vt, fmt_mdmx);
389 result = qh_map_op(op1, QH_ELEM(op2, fmtsel), qh_func[op]);
390 break;
391 case sel_vect:
392 result = qh_vector_op(op1, ValueFPR(vt, fmt_mdmx), qh_func[op]);
393 break;
394 case sel_imm:
395 result = qh_map_op(op1, vt, qh_func[op]);
396 break;
397 }
398 break;
399 case mdmx_ob:
400 switch (MX_VT (fmtsel))
401 {
402 case sel_elem:
403 op2 = ValueFPR(vt, fmt_mdmx);
404 result = ob_map_op(op1, OB_ELEM(op2, fmtsel), ob_func[op]);
405 break;
406 case sel_vect:
407 result = ob_vector_op(op1, ValueFPR(vt, fmt_mdmx), ob_func[op]);
408 break;
409 case sel_imm:
410 result = ob_map_op(op1, vt, ob_func[op]);
411 break;
412 }
413 break;
414 default:
415 Unpredictable ();
416 }
417
418 return result;
419}
420
421
422/* Operations that update CCs */
423
424static void
425qh_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
426{
427 int i;
428 signed16 h1, h2;
429 int boolean;
430
431 for (i = 0; i < 4; i++)
432 {
433 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
434 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
435 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
436 ((cond & MX_C_LT) && (h1 < h2));
437 SETFCC(i, boolean);
438 }
439}
440
441static void
442qh_map_test(sim_cpu *cpu, unsigned64 v1, signed16 h2, int cond)
443{
444 int i;
445 signed16 h1;
446 int boolean;
447
448 for (i = 0; i < 4; i++)
449 {
450 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
451 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
452 ((cond & MX_C_LT) && (h1 < h2));
453 SETFCC(i, boolean);
454 }
455}
456
457static void
458ob_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
459{
460 int i;
461 unsigned8 b1, b2;
462 int boolean;
463
464 for (i = 0; i < 8; i++)
465 {
466 b1 = v1 & 0xFF; v1 >>= 8;
467 b2 = v2 & 0xFF; v2 >>= 8;
468 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
469 ((cond & MX_C_LT) && (b1 < b2));
470 SETFCC(i, boolean);
471 }
472}
473
474static void
475ob_map_test(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int cond)
476{
477 int i;
478 unsigned8 b1;
479 int boolean;
480
481 for (i = 0; i < 8; i++)
482 {
483 b1 = (unsigned8)(v1 & 0xFF); v1 >>= 8;
484 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
485 ((cond & MX_C_LT) && (b1 < b2));
486 SETFCC(i, boolean);
487 }
488}
489
490
491void
492mdmx_cc_op(sim_cpu *cpu,
493 address_word cia,
494 int cond,
495 unsigned64 v1,
496 int vt,
497 MX_fmtsel fmtsel)
498{
499 unsigned64 op2;
500
501 switch (MX_FMT (fmtsel))
502 {
503 case mdmx_qh:
504 switch (MX_VT (fmtsel))
505 {
506 case sel_elem:
507 op2 = ValueFPR(vt, fmt_mdmx);
508 qh_map_test(cpu, v1, QH_ELEM(op2, fmtsel), cond);
509 break;
510 case sel_vect:
511 qh_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
512 break;
513 case sel_imm:
514 qh_map_test(cpu, v1, vt, cond);
515 break;
516 }
517 break;
518 case mdmx_ob:
519 switch (MX_VT (fmtsel))
520 {
521 case sel_elem:
522 op2 = ValueFPR(vt, fmt_mdmx);
523 ob_map_test(cpu, v1, OB_ELEM(op2, fmtsel), cond);
524 break;
525 case sel_vect:
526 ob_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
527 break;
528 case sel_imm:
529 ob_map_test(cpu, v1, vt, cond);
530 break;
531 }
532 break;
533 default:
534 Unpredictable ();
535 }
536}
537
538
539/* Pick operations. */
540
541static unsigned64
542qh_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
543{
544 unsigned64 result = 0;
545 int i, s;
546 unsigned16 h;
547
548 s = 0;
549 for (i = 0; i < 4; i++)
550 {
551 h = ((GETFCC(i) == tf) ? (v1 & 0xFFFF) : (v2 & 0xFFFF));
552 v1 >>= 16; v2 >>= 16;
553 result |= ((unsigned64)h << s);
554 s += 16;
555 }
556 return result;
557}
558
559static unsigned64
560qh_map_pick(sim_cpu *cpu, unsigned64 v1, signed16 h2, int tf)
561{
562 unsigned64 result = 0;
563 int i, s;
564 unsigned16 h;
565
566 s = 0;
567 for (i = 0; i < 4; i++)
568 {
569 h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (unsigned16)h2;
570 v1 >>= 16;
571 result |= ((unsigned64)h << s);
572 s += 16;
573 }
574 return result;
575}
576
577static unsigned64
578ob_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
579{
580 unsigned64 result = 0;
581 int i, s;
582 unsigned8 b;
583
584 s = 0;
585 for (i = 0; i < 8; i++)
586 {
587 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : (v2 & 0xFF);
588 v1 >>= 8; v2 >>= 8;
589 result |= ((unsigned64)b << s);
590 s += 8;
591 }
592 return result;
593}
594
595static unsigned64
596ob_map_pick(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int tf)
597{
598 unsigned64 result = 0;
599 int i, s;
600 unsigned8 b;
601
602 s = 0;
603 for (i = 0; i < 8; i++)
604 {
605 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : b2;
606 v1 >>= 8;
607 result |= ((unsigned64)b << s);
608 s += 8;
609 }
610 return result;
611}
612
613
614unsigned64
615mdmx_pick_op(sim_cpu *cpu,
616 address_word cia,
617 int tf,
618 unsigned64 v1,
619 int vt,
620 MX_fmtsel fmtsel)
621{
622 unsigned64 result = 0;
623 unsigned64 op2;
624
625 switch (MX_FMT (fmtsel))
626 {
627 case mdmx_qh:
628 switch (MX_VT (fmtsel))
629 {
630 case sel_elem:
631 op2 = ValueFPR(vt, fmt_mdmx);
632 result = qh_map_pick(cpu, v1, QH_ELEM(op2, fmtsel), tf);
633 break;
634 case sel_vect:
635 result = qh_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
636 break;
637 case sel_imm:
638 result = qh_map_pick(cpu, v1, vt, tf);
639 break;
640 }
641 break;
642 case mdmx_ob:
643 switch (MX_VT (fmtsel))
644 {
645 case sel_elem:
646 op2 = ValueFPR(vt, fmt_mdmx);
647 result = ob_map_pick(cpu, v1, OB_ELEM(op2, fmtsel), tf);
648 break;
649 case sel_vect:
650 result = ob_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
651 break;
652 case sel_imm:
653 result = ob_map_pick(cpu, v1, vt, tf);
654 break;
655 }
656 break;
657 default:
658 Unpredictable ();
659 }
660 return result;
661}
662
663
664/* Accumulators. */
665
666typedef void (*QH_ACC)(signed48 *a, signed16 ts, signed16 tt);
667
668static void
669AccAddAQH(signed48 *a, signed16 ts, signed16 tt)
670{
671 *a += (signed48)ts + (signed48)tt;
672}
673
674static void
675AccAddLQH(signed48 *a, signed16 ts, signed16 tt)
676{
677 *a = (signed48)ts + (signed48)tt;
678}
679
680static void
681AccMulAQH(signed48 *a, signed16 ts, signed16 tt)
682{
683 *a += (signed48)ts * (signed48)tt;
684}
685
686static void
687AccMulLQH(signed48 *a, signed16 ts, signed16 tt)
688{
689 *a = (signed48)ts * (signed48)tt;
690}
691
692static void
693SubMulAQH(signed48 *a, signed16 ts, signed16 tt)
694{
695 *a -= (signed48)ts * (signed48)tt;
696}
697
698static void
699SubMulLQH(signed48 *a, signed16 ts, signed16 tt)
700{
701 *a = -((signed48)ts * (signed48)tt);
702}
703
704static void
705AccSubAQH(signed48 *a, signed16 ts, signed16 tt)
706{
707 *a += (signed48)ts - (signed48)tt;
708}
709
710static void
711AccSubLQH(signed48 *a, signed16 ts, signed16 tt)
712{
713 *a = (signed48)ts - (signed48)tt;
714}
715
716
717typedef void (*OB_ACC)(signed24 *acc, unsigned8 ts, unsigned8 tt);
718
719static void
720AccAddAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
721{
722 *a += (signed24)ts + (signed24)tt;
723}
724
725static void
726AccAddLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
727{
728 *a = (signed24)ts + (signed24)tt;
729}
730
731static void
732AccMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
733{
734 *a += (signed24)ts * (signed24)tt;
735}
736
737static void
738AccMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
739{
740 *a = (signed24)ts * (signed24)tt;
741}
742
743static void
744SubMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
745{
746 *a -= (signed24)ts * (signed24)tt;
747}
748
749static void
750SubMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
751{
752 *a = -((signed24)ts * (signed24)tt);
753}
754
755static void
756AccSubAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
757{
758 *a += (signed24)ts - (signed24)tt;
759}
760
761static void
762AccSubLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
763{
764 *a = (signed24)ts - (signed24)tt;
765}
766
7cbea089
CD
767static void
768AccAbsDiffOB(signed24 *a, unsigned8 ts, unsigned8 tt)
769{
770 unsigned8 t = (ts >= tt ? ts - tt : tt - ts);
771 *a += (signed24)t;
772}
773
f4f1b9f1
CD
774
775/* Dispatch tables for operations that update a CPR. */
776
777static const QH_ACC qh_acc[] = {
4df817de 778 AccAddAQH, AccAddLQH, AccMulAQH, AccMulLQH,
7cbea089
CD
779 SubMulAQH, SubMulLQH, AccSubAQH, AccSubLQH,
780 NULL
f4f1b9f1
CD
781};
782
783static const OB_ACC ob_acc[] = {
784 AccAddAOB, AccAddLOB, AccMulAOB, AccMulLOB,
7cbea089
CD
785 SubMulAOB, SubMulLOB, AccSubAOB, AccSubLOB,
786 AccAbsDiffOB
f4f1b9f1
CD
787};
788
789
790static void
791qh_vector_acc(signed48 a[], unsigned64 v1, unsigned64 v2, QH_ACC acc)
792{
793 int i;
794 signed16 h1, h2;
795
796 for (i = 0; i < 4; i++)
797 {
798 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
799 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
800 (*acc)(&a[i], h1, h2);
801 }
802}
803
804static void
805qh_map_acc(signed48 a[], unsigned64 v1, signed16 h2, QH_ACC acc)
806{
807 int i;
808 signed16 h1;
809
810 for (i = 0; i < 4; i++)
811 {
812 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
813 (*acc)(&a[i], h1, h2);
814 }
815}
816
817static void
818ob_vector_acc(signed24 a[], unsigned64 v1, unsigned64 v2, OB_ACC acc)
819{
820 int i;
821 unsigned8 b1, b2;
822
823 for (i = 0; i < 8; i++)
824 {
825 b1 = v1 & 0xFF; v1 >>= 8;
826 b2 = v2 & 0xFF; v2 >>= 8;
827 (*acc)(&a[i], b1, b2);
828 }
829}
830
831static void
832ob_map_acc(signed24 a[], unsigned64 v1, unsigned8 b2, OB_ACC acc)
833{
834 int i;
835 unsigned8 b1;
836
837 for (i = 0; i < 8; i++)
838 {
839 b1 = v1 & 0xFF; v1 >>= 8;
840 (*acc)(&a[i], b1, b2);
841 }
842}
843
844
845/* Primary entry for operations that accumulate */
846void
847mdmx_acc_op(sim_cpu *cpu,
848 address_word cia,
849 int op,
850 unsigned64 op1,
851 int vt,
852 MX_fmtsel fmtsel)
853{
854 unsigned64 op2;
855
856 switch (MX_FMT (fmtsel))
857 {
858 case mdmx_qh:
859 switch (MX_VT (fmtsel))
860 {
861 case sel_elem:
862 op2 = ValueFPR(vt, fmt_mdmx);
863 qh_map_acc(ACC.qh, op1, QH_ELEM(op2, fmtsel), qh_acc[op]);
864 break;
865 case sel_vect:
866 qh_vector_acc(ACC.qh, op1, ValueFPR(vt, fmt_mdmx), qh_acc[op]);
867 break;
868 case sel_imm:
869 qh_map_acc(ACC.qh, op1, vt, qh_acc[op]);
870 break;
871 }
872 break;
873 case mdmx_ob:
874 switch (MX_VT (fmtsel))
875 {
876 case sel_elem:
877 op2 = ValueFPR(vt, fmt_mdmx);
878 ob_map_acc(ACC.ob, op1, OB_ELEM(op2, fmtsel), ob_acc[op]);
879 break;
880 case sel_vect:
881 ob_vector_acc(ACC.ob, op1, ValueFPR(vt, fmt_mdmx), ob_acc[op]);
882 break;
883 case sel_imm:
a2f8b4f3 884 ob_map_acc(ACC.ob, op1, vt, ob_acc[op]);
f4f1b9f1
CD
885 break;
886 }
887 break;
888 default:
889 Unpredictable ();
890 }
891}
892
893
894/* Reading and writing accumulator (no conversion). */
895
896unsigned64
897mdmx_rac_op(sim_cpu *cpu,
898 address_word cia,
899 int op,
900 int fmt)
901{
902 unsigned64 result;
903 unsigned int shift;
904 int i;
905
906 shift = op; /* L = 00, M = 01, H = 10. */
907 result = 0;
908
909 switch (fmt)
910 {
911 case MX_FMT_QH:
912 shift <<= 4; /* 16 bits per element. */
913 for (i = 3; i >= 0; --i)
914 {
915 result <<= 16;
916 result |= ((ACC.qh[i] >> shift) & 0xFFFF);
917 }
918 break;
919 case MX_FMT_OB:
920 shift <<= 3; /* 8 bits per element. */
921 for (i = 7; i >= 0; --i)
922 {
923 result <<= 8;
924 result |= ((ACC.ob[i] >> shift) & 0xFF);
925 }
926 break;
927 default:
928 Unpredictable ();
929 }
930 return result;
931}
932
933void
934mdmx_wacl(sim_cpu *cpu,
935 address_word cia,
936 int fmt,
937 unsigned64 vs,
938 unsigned64 vt)
939{
940 int i;
941
942 switch (fmt)
943 {
944 case MX_FMT_QH:
945 for (i = 0; i < 4; i++)
946 {
947 signed32 s = (signed16)(vs & 0xFFFF);
948 ACC.qh[i] = ((signed48)s << 16) | (vt & 0xFFFF);
949 vs >>= 16; vt >>= 16;
950 }
951 break;
952 case MX_FMT_OB:
953 for (i = 0; i < 8; i++)
954 {
955 signed16 s = (signed8)(vs & 0xFF);
956 ACC.ob[i] = ((signed24)s << 8) | (vt & 0xFF);
957 vs >>= 8; vt >>= 8;
958 }
959 break;
960 default:
961 Unpredictable ();
962 }
963}
964
965void
966mdmx_wach(sim_cpu *cpu,
967 address_word cia,
968 int fmt,
969 unsigned64 vs)
970{
971 int i;
972
973 switch (fmt)
974 {
975 case MX_FMT_QH:
976 for (i = 0; i < 4; i++)
977 {
978 signed32 s = (signed16)(vs & 0xFFFF);
979 ACC.qh[i] &= ~((signed48)0xFFFF << 32);
980 ACC.qh[i] |= ((signed48)s << 32);
981 vs >>= 16;
982 }
983 break;
984 case MX_FMT_OB:
985 for (i = 0; i < 8; i++)
986 {
987 ACC.ob[i] &= ~((signed24)0xFF << 16);
988 ACC.ob[i] |= ((signed24)(vs & 0xFF) << 16);
989 vs >>= 8;
990 }
991 break;
992 default:
993 Unpredictable ();
994 }
995}
996
997
998/* Reading and writing accumulator (rounding conversions).
999 Enumerating function guarantees s >= 0 for QH ops. */
1000
1001typedef signed16 (*QH_ROUND)(signed48 a, signed16 s);
1002
1003#define QH_BIT(n) ((unsigned48)1 << (n))
1004#define QH_ONES(n) (((unsigned48)1 << (n))-1)
1005
1006static signed16
1007RNASQH(signed48 a, signed16 s)
1008{
1009 signed48 t;
1010 signed16 result = 0;
1011
1012 if (s > 48)
1013 result = 0;
1014 else
1015 {
1016 t = (a >> s);
1017 if ((a & QH_BIT(47)) == 0)
1018 {
1019 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1020 t++;
1021 if (t > QH_MAX)
1022 t = QH_MAX;
1023 }
1024 else
1025 {
1026 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1027 {
1028 if (s > 1 && ((unsigned48)a & QH_ONES(s-1)) != 0)
1029 t++;
1030 }
1031 if (t < QH_MIN)
1032 t = QH_MIN;
1033 }
1034 result = (signed16)t;
1035 }
1036 return result;
1037}
1038
1039static signed16
1040RNAUQH(signed48 a, signed16 s)
1041{
1042 unsigned48 t;
1043 signed16 result;
1044
1045 if (s > 48)
1046 result = 0;
1047 else if (s == 48)
1048 result = ((unsigned48)a & MASK48) >> 47;
1049 else
1050 {
1051 t = ((unsigned48)a & MASK48) >> s;
1052 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1053 t++;
1054 if (t > 0xFFFF)
1055 t = 0xFFFF;
1056 result = (signed16)t;
1057 }
1058 return result;
1059}
1060
1061static signed16
1062RNESQH(signed48 a, signed16 s)
1063{
1064 signed48 t;
1065 signed16 result = 0;
1066
1067 if (s > 47)
1068 result = 0;
1069 else
1070 {
1071 t = (a >> s);
1072 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1073 {
1074 if (s == 1 || (a & QH_ONES(s-1)) == 0)
1075 t += t & 1;
1076 else
1077 t += 1;
1078 }
1079 if ((a & QH_BIT(47)) == 0)
1080 {
1081 if (t > QH_MAX)
1082 t = QH_MAX;
1083 }
1084 else
1085 {
1086 if (t < QH_MIN)
1087 t = QH_MIN;
1088 }
1089 result = (signed16)t;
1090 }
1091 return result;
1092}
1093
1094static signed16
1095RNEUQH(signed48 a, signed16 s)
1096{
1097 unsigned48 t;
1098 signed16 result;
1099
1100 if (s > 48)
1101 result = 0;
1102 else if (s == 48)
1103 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1104 else
1105 {
1106 t = ((unsigned48)a & MASK48) >> s;
1107 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1108 {
1109 if (s > 1 && (a & QH_ONES(s-1)) != 0)
1110 t++;
1111 else
1112 t += t & 1;
1113 }
1114 if (t > 0xFFFF)
1115 t = 0xFFFF;
1116 result = (signed16)t;
1117 }
1118 return result;
1119}
1120
1121static signed16
1122RZSQH(signed48 a, signed16 s)
1123{
1124 signed48 t;
1125 signed16 result = 0;
1126
1127 if (s > 47)
1128 result = 0;
1129 else
1130 {
1131 t = (a >> s);
1132 if ((a & QH_BIT(47)) == 0)
1133 {
1134 if (t > QH_MAX)
1135 t = QH_MAX;
1136 }
1137 else
1138 {
1139 if (t < QH_MIN)
1140 t = QH_MIN;
1141 }
1142 result = (signed16)t;
1143 }
1144 return result;
1145}
1146
1147static signed16
1148RZUQH(signed48 a, signed16 s)
1149{
1150 unsigned48 t;
1151 signed16 result = 0;
1152
1153 if (s > 48)
1154 result = 0;
1155 else if (s == 48)
1156 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1157 else
1158 {
1159 t = ((unsigned48)a & MASK48) >> s;
1160 if (t > 0xFFFF)
1161 t = 0xFFFF;
1162 result = (signed16)t;
1163 }
1164 return result;
1165}
1166
1167
1168typedef unsigned8 (*OB_ROUND)(signed24 a, unsigned8 s);
1169
1170#define OB_BIT(n) ((unsigned24)1 << (n))
1171#define OB_ONES(n) (((unsigned24)1 << (n))-1)
1172
1173static unsigned8
1174RNAUOB(signed24 a, unsigned8 s)
1175{
1176 unsigned8 result;
1177 unsigned24 t;
1178
1179 if (s > 24)
1180 result = 0;
1181 else if (s == 24)
1182 result = ((unsigned24)a & MASK24) >> 23;
1183 else
1184 {
1185 t = ((unsigned24)a & MASK24) >> s;
1186 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1187 t ++;
1188 result = OB_CLAMP(t);
1189 }
1190 return result;
1191}
1192
1193static unsigned8
1194RNEUOB(signed24 a, unsigned8 s)
1195{
1196 unsigned8 result;
1197 unsigned24 t;
1198
1199 if (s > 24)
1200 result = 0;
1201 else if (s == 24)
1202 result = (((unsigned24)a & MASK24) > OB_BIT(23) ? 1 : 0);
1203 else
1204 {
1205 t = ((unsigned24)a & MASK24) >> s;
1206 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1207 {
1208 if (s > 1 && (a & OB_ONES(s-1)) != 0)
1209 t++;
1210 else
1211 t += t & 1;
1212 }
1213 result = OB_CLAMP(t);
1214 }
1215 return result;
1216}
1217
1218static unsigned8
1219RZUOB(signed24 a, unsigned8 s)
1220{
1221 unsigned8 result;
1222 unsigned24 t;
1223
1224 if (s >= 24)
1225 result = 0;
1226 else
1227 {
1228 t = ((unsigned24)a & MASK24) >> s;
1229 result = OB_CLAMP(t);
1230 }
1231 return result;
1232}
1233
1234
1235static const QH_ROUND qh_round[] = {
1236 RNASQH, RNAUQH, RNESQH, RNEUQH, RZSQH, RZUQH
1237};
1238
1239static const OB_ROUND ob_round[] = {
1240 NULL, RNAUOB, NULL, RNEUOB, NULL, RZUOB
1241};
1242
1243
1244static unsigned64
1245qh_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, QH_ROUND round)
1246{
1247 unsigned64 result = 0;
1248 int i, s;
1249 signed16 h, h2;
1250
1251 s = 0;
1252 for (i = 0; i < 4; i++)
1253 {
1254 h2 = (signed16)(v2 & 0xFFFF);
1255 if (h2 >= 0)
1256 h = (*round)(ACC.qh[i], h2);
1257 else
1258 {
1259 UnpredictableResult ();
1260 h = 0xdead;
1261 }
1262 v2 >>= 16;
1263 result |= ((unsigned64)((unsigned16)h) << s);
1264 s += 16;
1265 }
1266 return result;
1267}
1268
1269static unsigned64
1270qh_map_round(sim_cpu *cpu, address_word cia, signed16 h2, QH_ROUND round)
1271{
1272 unsigned64 result = 0;
1273 int i, s;
1274 signed16 h;
1275
1276 s = 0;
1277 for (i = 0; i < 4; i++)
1278 {
1279 if (h2 >= 0)
1280 h = (*round)(ACC.qh[i], h2);
1281 else
1282 {
1283 UnpredictableResult ();
1284 h = 0xdead;
1285 }
1286 result |= ((unsigned64)((unsigned16)h) << s);
1287 s += 16;
1288 }
1289 return result;
1290}
1291
1292static unsigned64
1293ob_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, OB_ROUND round)
1294{
1295 unsigned64 result = 0;
1296 int i, s;
1297 unsigned8 b, b2;
1298
1299 s = 0;
1300 for (i = 0; i < 8; i++)
1301 {
1302 b2 = v2 & 0xFF; v2 >>= 8;
1303 b = (*round)(ACC.ob[i], b2);
1304 result |= ((unsigned64)b << s);
1305 s += 8;
1306 }
1307 return result;
1308}
1309
1310static unsigned64
1311ob_map_round(sim_cpu *cpu, address_word cia, unsigned8 b2, OB_ROUND round)
1312{
1313 unsigned64 result = 0;
1314 int i, s;
1315 unsigned8 b;
1316
1317 s = 0;
1318 for (i = 0; i < 8; i++)
1319 {
1320 b = (*round)(ACC.ob[i], b2);
1321 result |= ((unsigned64)b << s);
1322 s += 8;
1323 }
1324 return result;
1325}
1326
1327
1328unsigned64
1329mdmx_round_op(sim_cpu *cpu,
1330 address_word cia,
1331 int rm,
1332 int vt,
1333 MX_fmtsel fmtsel)
1334{
1335 unsigned64 op2;
1336 unsigned64 result = 0;
1337
1338 switch (MX_FMT (fmtsel))
1339 {
1340 case mdmx_qh:
1341 switch (MX_VT (fmtsel))
1342 {
1343 case sel_elem:
1344 op2 = ValueFPR(vt, fmt_mdmx);
1345 result = qh_map_round(cpu, cia, QH_ELEM(op2, fmtsel), qh_round[rm]);
1346 break;
1347 case sel_vect:
1348 op2 = ValueFPR(vt, fmt_mdmx);
1349 result = qh_vector_round(cpu, cia, op2, qh_round[rm]);
1350 break;
1351 case sel_imm:
1352 result = qh_map_round(cpu, cia, vt, qh_round[rm]);
1353 break;
1354 }
1355 break;
1356 case mdmx_ob:
1357 switch (MX_VT (fmtsel))
1358 {
1359 case sel_elem:
1360 op2 = ValueFPR(vt, fmt_mdmx);
1361 result = ob_map_round(cpu, cia, OB_ELEM(op2, fmtsel), ob_round[rm]);
1362 break;
1363 case sel_vect:
1364 op2 = ValueFPR(vt, fmt_mdmx);
1365 result = ob_vector_round(cpu, cia, op2, ob_round[rm]);
1366 break;
1367 case sel_imm:
1368 result = ob_map_round(cpu, cia, vt, ob_round[rm]);
1369 break;
1370 }
1371 break;
1372 default:
1373 Unpredictable ();
1374 }
1375
1376 return result;
1377}
1378
1379
1380/* Shuffle operation. */
1381
1382typedef struct {
1383 enum {vs, ss, vt} source;
1384 unsigned int index;
1385} sh_map;
1386
1387static const sh_map ob_shuffle[][8] = {
1388 /* MDMX 2.0 encodings (3-4, 6-7). */
1389 /* vr5400 encoding (5), otherwise. */
1390 { }, /* RSVD */
1391 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* RSVD */
1392 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* RSVD */
1393 {{vs,0}, {ss,0}, {vs,1}, {ss,1}, {vs,2}, {ss,2}, {vs,3}, {ss,3}}, /* upsl */
1394 {{vt,1}, {vt,3}, {vt,5}, {vt,7}, {vs,1}, {vs,3}, {vs,5}, {vs,7}}, /* pach */
1395 {{vt,0}, {vt,2}, {vt,4}, {vt,6}, {vs,0}, {vs,2}, {vs,4}, {vs,6}}, /* pacl */
1396 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* mixh */
1397 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}} /* mixl */
1398};
1399
1400static const sh_map qh_shuffle[][4] = {
1401 {{vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* mixh */
1402 {{vt,0}, {vs,0}, {vt,1}, {vs,1}}, /* mixl */
1403 {{vt,1}, {vt,3}, {vs,1}, {vs,3}}, /* pach */
1404 { }, /* RSVD */
1405 {{vt,1}, {vs,0}, {vt,3}, {vs,2}}, /* bfla */
1406 { }, /* RSVD */
1407 {{vt,2}, {vt,3}, {vs,2}, {vs,3}}, /* repa */
1408 {{vt,0}, {vt,1}, {vs,0}, {vs,1}} /* repb */
1409};
1410
1411
1412unsigned64
1413mdmx_shuffle(sim_cpu *cpu,
1414 address_word cia,
1415 int shop,
1416 unsigned64 op1,
1417 unsigned64 op2)
1418{
1419 unsigned64 result = 0;
1420 int i, s;
1421 int op;
1422
1423 if ((shop & 0x3) == 0x1) /* QH format. */
1424 {
1425 op = shop >> 2;
1426 s = 0;
1427 for (i = 0; i < 4; i++)
1428 {
1429 unsigned64 v;
1430
1431 switch (qh_shuffle[op][i].source)
1432 {
1433 case vs:
1434 v = op1;
1435 break;
1436 case vt:
1437 v = op2;
1438 break;
1439 default:
1440 Unpredictable ();
1441 v = 0;
1442 }
1443 result |= (((v >> 16*qh_shuffle[op][i].index) & 0xFFFF) << s);
1444 s += 16;
1445 }
1446 }
1447 else if ((shop & 0x1) == 0x0) /* OB format. */
1448 {
1449 op = shop >> 1;
1450 s = 0;
1451 for (i = 0; i < 8; i++)
1452 {
1453 unsigned8 b;
1454 unsigned int ishift = 8*ob_shuffle[op][i].index;
1455
1456 switch (ob_shuffle[op][i].source)
1457 {
1458 case vs:
1459 b = (op1 >> ishift) & 0xFF;
1460 break;
1461 case ss:
1462 b = ((op1 >> ishift) & 0x80) ? 0xFF : 0;
1463 break;
1464 case vt:
1465 b = (op2 >> ishift) & 0xFF;
1466 break;
1467 default:
1468 Unpredictable ();
1469 b = 0;
1470 }
1471 result |= ((unsigned64)b << s);
1472 s += 8;
1473 }
1474 }
1475 else
1476 Unpredictable ();
1477
1478 return result;
1479}
This page took 1.049687 seconds and 4 git commands to generate.