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