1 1.1 christos /* Simulation code for the MIPS MDMX ASE. 2 1.11 christos Copyright (C) 2002-2024 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.10 christos /* This must come before any other includes. */ 22 1.10 christos #include "defs.h" 23 1.10 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.10 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.10 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.10 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.10 christos typedef uint64_t unsigned48; 58 1.1 christos #define MASK48 (UNSIGNED64 (0xffffffffffff)) 59 1.1 christos 60 1.10 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.10 christos #define OB_MAX ((uint8_t)0xFF) 75 1.10 christos #define QH_MIN ((int16_t)0x8000) 76 1.10 christos #define QH_MAX ((int16_t)0x7FFF) 77 1.1 christos 78 1.10 christos #define OB_CLAMP(x) ((uint8_t)((x) > OB_MAX ? OB_MAX : (x))) 79 1.10 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.10 christos ((int16_t)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF)) 88 1.1 christos #define OB_ELEM(v,fmtsel) \ 89 1.10 christos ((uint8_t)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF)) 90 1.1 christos 91 1.1 christos 92 1.10 christos typedef int16_t (*QH_FUNC)(int16_t, int16_t); 93 1.10 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.10 christos static int16_t 98 1.10 christos AndQH(int16_t ts, int16_t tt) 99 1.1 christos { 100 1.10 christos return (int16_t)((uint16_t)ts & (uint16_t)tt); 101 1.1 christos } 102 1.1 christos 103 1.10 christos static uint8_t 104 1.10 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.10 christos static int16_t 110 1.10 christos NorQH(int16_t ts, int16_t tt) 111 1.1 christos { 112 1.10 christos return (int16_t)(((uint16_t)ts | (uint16_t)tt) ^ 0xFFFF); 113 1.1 christos } 114 1.1 christos 115 1.10 christos static uint8_t 116 1.10 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.10 christos static int16_t 122 1.10 christos OrQH(int16_t ts, int16_t tt) 123 1.1 christos { 124 1.10 christos return (int16_t)((uint16_t)ts | (uint16_t)tt); 125 1.1 christos } 126 1.1 christos 127 1.10 christos static uint8_t 128 1.10 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.10 christos static int16_t 134 1.10 christos XorQH(int16_t ts, int16_t tt) 135 1.1 christos { 136 1.10 christos return (int16_t)((uint16_t)ts ^ (uint16_t)tt); 137 1.1 christos } 138 1.1 christos 139 1.10 christos static uint8_t 140 1.10 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.10 christos static int16_t 146 1.10 christos SLLQH(int16_t ts, int16_t tt) 147 1.1 christos { 148 1.10 christos uint32_t s = (uint32_t)tt & 0xF; 149 1.10 christos return (int16_t)(((uint32_t)ts << s) & 0xFFFF); 150 1.1 christos } 151 1.1 christos 152 1.10 christos static uint8_t 153 1.10 christos SLLOB(uint8_t ts, uint8_t tt) 154 1.1 christos { 155 1.10 christos uint32_t s = tt & 0x7; 156 1.1 christos return (ts << s) & 0xFF; 157 1.1 christos } 158 1.1 christos 159 1.10 christos static int16_t 160 1.10 christos SRLQH(int16_t ts, int16_t tt) 161 1.1 christos { 162 1.10 christos uint32_t s = (uint32_t)tt & 0xF; 163 1.10 christos return (int16_t)((uint16_t)ts >> s); 164 1.1 christos } 165 1.1 christos 166 1.10 christos static uint8_t 167 1.10 christos SRLOB(uint8_t ts, uint8_t tt) 168 1.1 christos { 169 1.10 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.10 christos static int16_t 177 1.10 christos AddQH(int16_t ts, int16_t tt) 178 1.1 christos { 179 1.10 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.10 christos static uint8_t 184 1.10 christos AddOB(uint8_t ts, uint8_t tt) 185 1.1 christos { 186 1.10 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.10 christos static int16_t 191 1.10 christos SubQH(int16_t ts, int16_t tt) 192 1.1 christos { 193 1.10 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.10 christos static uint8_t 198 1.10 christos SubOB(uint8_t ts, uint8_t tt) 199 1.1 christos { 200 1.10 christos int32_t t; 201 1.10 christos t = (int32_t)ts - (int32_t)tt; 202 1.1 christos if (t < 0) 203 1.1 christos t = 0; 204 1.10 christos return (uint8_t)t; 205 1.1 christos } 206 1.1 christos 207 1.10 christos static int16_t 208 1.10 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.10 christos static uint8_t 214 1.10 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.10 christos static int16_t 220 1.10 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.10 christos static uint8_t 226 1.10 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.10 christos static int16_t 232 1.10 christos MulQH(int16_t ts, int16_t tt) 233 1.1 christos { 234 1.10 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.10 christos static uint8_t 239 1.10 christos MulOB(uint8_t ts, uint8_t tt) 240 1.1 christos { 241 1.10 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.10 christos static int16_t 248 1.10 christos MsgnQH(int16_t ts, int16_t tt) 249 1.1 christos { 250 1.10 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.10 christos static int16_t 261 1.10 christos SRAQH(int16_t ts, int16_t tt) 262 1.1 christos { 263 1.10 christos uint32_t s = (uint32_t)tt & 0xF; 264 1.10 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.10 christos static uint8_t 271 1.10 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.10 christos static uint8_t 277 1.10 christos AvgOB(uint8_t ts, uint8_t tt) 278 1.1 christos { 279 1.10 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.10 christos static uint64_t 301 1.10 christos qh_vector_op(uint64_t v1, uint64_t v2, QH_FUNC func) 302 1.1 christos { 303 1.10 christos uint64_t result = 0; 304 1.1 christos int i; 305 1.10 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.10 christos h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16; 310 1.10 christos h2 = (int16_t)(v2 & 0xFFFF); v2 >>= 16; 311 1.1 christos h = (*func)(h1, h2); 312 1.10 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.10 christos static uint64_t 318 1.10 christos qh_map_op(uint64_t v1, int16_t h2, QH_FUNC func) 319 1.1 christos { 320 1.10 christos uint64_t result = 0; 321 1.1 christos int i; 322 1.10 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.10 christos h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16; 327 1.1 christos h = (*func)(h1, h2); 328 1.10 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.10 christos static uint64_t 337 1.10 christos ob_vector_op(uint64_t v1, uint64_t v2, OB_FUNC func) 338 1.1 christos { 339 1.10 christos uint64_t result = 0; 340 1.1 christos int i; 341 1.10 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.10 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.10 christos static uint64_t 354 1.10 christos ob_map_op(uint64_t v1, uint8_t b2, OB_FUNC func) 355 1.1 christos { 356 1.10 christos uint64_t result = 0; 357 1.1 christos int i; 358 1.10 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.10 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.10 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.10 christos uint64_t op1, 376 1.1 christos int vt, 377 1.10 christos MX_fmtsel fmtsel) 378 1.1 christos { 379 1.10 christos uint64_t op2; 380 1.10 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.10 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.10 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.10 christos h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16; 434 1.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 christos uint64_t v1, 496 1.1 christos int vt, 497 1.1 christos MX_fmtsel fmtsel) 498 1.1 christos { 499 1.10 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.10 christos static uint64_t 542 1.10 christos qh_vector_pick(sim_cpu *cpu, uint64_t v1, uint64_t v2, int tf) 543 1.1 christos { 544 1.10 christos uint64_t result = 0; 545 1.1 christos int i, s; 546 1.10 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.10 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.10 christos static uint64_t 560 1.10 christos qh_map_pick(sim_cpu *cpu, uint64_t v1, int16_t h2, int tf) 561 1.1 christos { 562 1.10 christos uint64_t result = 0; 563 1.1 christos int i, s; 564 1.10 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.10 christos h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (uint16_t)h2; 570 1.1 christos v1 >>= 16; 571 1.10 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.10 christos static uint64_t 578 1.10 christos ob_vector_pick(sim_cpu *cpu, uint64_t v1, uint64_t v2, int tf) 579 1.1 christos { 580 1.10 christos uint64_t result = 0; 581 1.1 christos int i, s; 582 1.10 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.10 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.10 christos static uint64_t 596 1.10 christos ob_map_pick(sim_cpu *cpu, uint64_t v1, uint8_t b2, int tf) 597 1.1 christos { 598 1.10 christos uint64_t result = 0; 599 1.1 christos int i, s; 600 1.10 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.10 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.10 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.10 christos uint64_t v1, 619 1.1 christos int vt, 620 1.1 christos MX_fmtsel fmtsel) 621 1.1 christos { 622 1.10 christos uint64_t result = 0; 623 1.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 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.10 christos AccAbsDiffOB(signed24 *a, uint8_t ts, uint8_t tt) 769 1.1 christos { 770 1.10 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.10 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.10 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.10 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.10 christos h1 = (int16_t)(v1 & 0xFFFF); v1 >>= 16; 799 1.10 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.10 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.10 christos int16_t h1; 809 1.1 christos 810 1.1 christos for (i = 0; i < 4; i++) 811 1.1 christos { 812 1.10 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.10 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.10 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.10 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.10 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.10 christos uint64_t op1, 851 1.1 christos int vt, 852 1.10 christos MX_fmtsel fmtsel) 853 1.1 christos { 854 1.10 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.10 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.10 christos int fmt) 901 1.1 christos { 902 1.10 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.10 christos uint64_t vs, 938 1.10 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.10 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.10 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.10 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.10 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.10 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.10 christos static int16_t 1007 1.10 christos RNASQH(signed48 a, int16_t s) 1008 1.1 christos { 1009 1.1 christos signed48 t; 1010 1.10 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.10 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.10 christos static int16_t 1040 1.10 christos RNAUQH(signed48 a, int16_t s) 1041 1.1 christos { 1042 1.1 christos unsigned48 t; 1043 1.10 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.10 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.10 christos static int16_t 1062 1.10 christos RNESQH(signed48 a, int16_t s) 1063 1.1 christos { 1064 1.1 christos signed48 t; 1065 1.10 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.10 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.10 christos static int16_t 1095 1.10 christos RNEUQH(signed48 a, int16_t s) 1096 1.1 christos { 1097 1.1 christos unsigned48 t; 1098 1.10 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.10 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.10 christos static int16_t 1122 1.10 christos RZSQH(signed48 a, int16_t s) 1123 1.1 christos { 1124 1.1 christos signed48 t; 1125 1.10 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.10 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.10 christos static int16_t 1148 1.10 christos RZUQH(signed48 a, int16_t s) 1149 1.1 christos { 1150 1.1 christos unsigned48 t; 1151 1.10 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.10 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.10 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.10 christos static uint8_t 1174 1.10 christos RNAUOB(signed24 a, uint8_t s) 1175 1.1 christos { 1176 1.10 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.10 christos static uint8_t 1194 1.10 christos RNEUOB(signed24 a, uint8_t s) 1195 1.1 christos { 1196 1.10 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.10 christos static uint8_t 1219 1.10 christos RZUOB(signed24 a, uint8_t s) 1220 1.1 christos { 1221 1.10 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.10 christos static uint64_t 1245 1.10 christos qh_vector_round(sim_cpu *cpu, address_word cia, uint64_t v2, QH_ROUND round) 1246 1.1 christos { 1247 1.10 christos uint64_t result = 0; 1248 1.1 christos int i, s; 1249 1.10 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.10 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.10 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.10 christos static uint64_t 1270 1.10 christos qh_map_round(sim_cpu *cpu, address_word cia, int16_t h2, QH_ROUND round) 1271 1.1 christos { 1272 1.10 christos uint64_t result = 0; 1273 1.1 christos int i, s; 1274 1.10 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.10 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.10 christos static uint64_t 1293 1.10 christos ob_vector_round(sim_cpu *cpu, address_word cia, uint64_t v2, OB_ROUND round) 1294 1.1 christos { 1295 1.10 christos uint64_t result = 0; 1296 1.1 christos int i, s; 1297 1.10 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.10 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.10 christos static uint64_t 1311 1.10 christos ob_map_round(sim_cpu *cpu, address_word cia, uint8_t b2, OB_ROUND round) 1312 1.1 christos { 1313 1.10 christos uint64_t result = 0; 1314 1.1 christos int i, s; 1315 1.10 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.10 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.10 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.10 christos MX_fmtsel fmtsel) 1334 1.1 christos { 1335 1.10 christos uint64_t op2; 1336 1.10 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.10 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.10 christos uint64_t op1, 1417 1.10 christos uint64_t op2) 1418 1.1 christos { 1419 1.10 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.10 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.10 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.10 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