1 /* 2 * Copyright (C) 2002-2013 The DOSBox Team 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 */ 18 19 /* State Management */ 20 CASE_0F_D(0x77) /* EMMS */ 21 { 22 setFPU(TAG_Empty); 23 break; 24 } 25 26 27 /* Data Movement */ 28 CASE_0F_D(0x6e) /* MOVD Pq,Ed */ 29 { 30 GetRM; 31 MMX_reg* rmrq=lookupRMregMM[rm]; 32 if (rm>=0xc0) { 33 GetEArd; 34 rmrq->ud.d0=*(Bit32u*)eard; 35 rmrq->ud.d1=0; 36 } else { 37 GetEAa; 38 rmrq->ud.d0=LoadMd(eaa); 39 rmrq->ud.d1=0; 40 } 41 break; 42 } 43 CASE_0F_D(0x7e) /* MOVD Ed,Pq */ 44 { 45 GetRM; 46 MMX_reg* rmrq=lookupRMregMM[rm]; 47 if (rm>=0xc0) { 48 GetEArd; 49 *(Bit32u*)eard=rmrq->ud.d0; 50 } else { 51 GetEAa; 52 SaveMd(eaa,rmrq->ud.d0); 53 } 54 break; 55 } 56 57 CASE_0F_D(0x6f) /* MOVQ Pq,Qq */ 58 { 59 GetRM; 60 MMX_reg* dest=lookupRMregMM[rm]; 61 if (rm>=0xc0) { 62 MMX_reg* src=®_mmx[rm&7]; 63 dest->q = src->q; 64 } else { 65 GetEAa; 66 dest->q=LoadMq(eaa); 67 } 68 break; 69 } 70 CASE_0F_D(0x7f) /* MOVQ Qq,Pq */ 71 { 72 GetRM; 73 MMX_reg* dest=lookupRMregMM[rm]; 74 if (rm>=0xc0) { 75 MMX_reg* src=®_mmx[rm&7]; 76 dest->q = src->q; 77 } else { 78 GetEAa; 79 SaveMq(eaa,dest->q); 80 } 81 break; 82 } 83 84 /* Boolean Logic */ 85 CASE_0F_D(0xef) /* PXOR Pq,Qq */ 86 { 87 GetRM; 88 MMX_reg* dest=lookupRMregMM[rm]; 89 if (rm>=0xc0) { 90 MMX_reg* src=®_mmx[rm&7]; 91 dest->q ^= src->q; 92 } else { 93 GetEAa; 94 dest->q ^= LoadMq(eaa); 95 } 96 break; 97 } 98 99 CASE_0F_D(0xeb) /* POR Pq,Qq */ 100 { 101 GetRM; 102 MMX_reg* dest=lookupRMregMM[rm]; 103 if (rm>=0xc0) { 104 MMX_reg* src=®_mmx[rm&7]; 105 dest->q |= src->q; 106 } else { 107 GetEAa; 108 dest->q |= LoadMq(eaa); 109 } 110 break; 111 } 112 CASE_0F_D(0xdb) /* PAND Pq,Qq */ 113 { 114 GetRM; 115 MMX_reg* dest=lookupRMregMM[rm]; 116 if (rm>=0xc0) { 117 MMX_reg* src=®_mmx[rm&7]; 118 dest->q &= src->q; 119 } else { 120 GetEAa; 121 dest->q &= LoadMq(eaa); 122 } 123 break; 124 } 125 CASE_0F_D(0xdf) /* PANDN Pq,Qq */ 126 { 127 GetRM; 128 MMX_reg* dest=lookupRMregMM[rm]; 129 if (rm>=0xc0) { 130 MMX_reg* src=®_mmx[rm&7]; 131 dest->q = ~dest->q & src->q; 132 } else { 133 GetEAa; 134 dest->q = ~dest->q & LoadMq(eaa); 135 } 136 break; 137 } 138 139 /* Shift */ 140 CASE_0F_D(0xf1) /* PSLLW Pq,Qq */ 141 { 142 GetRM; 143 MMX_reg* dest=lookupRMregMM[rm]; 144 MMX_reg src; 145 if (rm>=0xc0) { 146 src.q=reg_mmx[rm&7].q; 147 } else { 148 GetEAa; 149 src.q=LoadMq(eaa); 150 } 151 if (src.q > 15) dest->q = 0; 152 else { 153 dest->uw.w0 <<= src.ub.b0; 154 dest->uw.w1 <<= src.ub.b0; 155 dest->uw.w2 <<= src.ub.b0; 156 dest->uw.w3 <<= src.ub.b0; 157 } 158 break; 159 } 160 CASE_0F_D(0xd1) /* PSRLW Pq,Qq */ 161 { 162 GetRM; 163 MMX_reg* dest=lookupRMregMM[rm]; 164 MMX_reg src; 165 if (rm>=0xc0) { 166 src.q=reg_mmx[rm&7].q; 167 } else { 168 GetEAa; 169 src.q=LoadMq(eaa); 170 } 171 if (src.q > 15) dest->q = 0; 172 else { 173 dest->uw.w0 >>= src.ub.b0; 174 dest->uw.w1 >>= src.ub.b0; 175 dest->uw.w2 >>= src.ub.b0; 176 dest->uw.w3 >>= src.ub.b0; 177 } 178 break; 179 } 180 CASE_0F_D(0xe1) /* PSRAW Pq,Qq */ 181 { 182 GetRM; 183 MMX_reg* dest=lookupRMregMM[rm]; 184 MMX_reg src; 185 MMX_reg tmp; 186 tmp.q = dest->q; 187 if (rm>=0xc0) { 188 src.q=reg_mmx[rm&7].q; 189 } else { 190 GetEAa; 191 src.q=LoadMq(eaa); 192 } 193 if (!src.q) break; 194 if (src.q > 15) { 195 dest->uw.w0 = (tmp.uw.w0&0x8000)?0xffff:0; 196 dest->uw.w1 = (tmp.uw.w1&0x8000)?0xffff:0; 197 dest->uw.w2 = (tmp.uw.w2&0x8000)?0xffff:0; 198 dest->uw.w3 = (tmp.uw.w3&0x8000)?0xffff:0; 199 } else { 200 dest->uw.w0 >>= src.ub.b0; 201 dest->uw.w1 >>= src.ub.b0; 202 dest->uw.w2 >>= src.ub.b0; 203 dest->uw.w3 >>= src.ub.b0; 204 if (tmp.uw.w0&0x8000) dest->uw.w0 |= (0xffff << (16 - src.ub.b0)); 205 if (tmp.uw.w1&0x8000) dest->uw.w1 |= (0xffff << (16 - src.ub.b0)); 206 if (tmp.uw.w2&0x8000) dest->uw.w2 |= (0xffff << (16 - src.ub.b0)); 207 if (tmp.uw.w3&0x8000) dest->uw.w3 |= (0xffff << (16 - src.ub.b0)); 208 } 209 break; 210 } 211 CASE_0F_D(0x71) /* PSLLW/PSRLW/PSRAW Pq,Ib */ 212 { 213 GetRM; 214 Bit8u op=(rm>>3)&7; 215 Bit8u shift=Fetchb(); 216 MMX_reg* dest=®_mmx[rm&7]; 217 switch (op) { 218 case 0x06: /*PSLLW*/ 219 if (shift > 15) dest->q = 0; 220 else { 221 dest->uw.w0 <<= shift; 222 dest->uw.w1 <<= shift; 223 dest->uw.w2 <<= shift; 224 dest->uw.w3 <<= shift; 225 } 226 break; 227 case 0x02: /*PSRLW*/ 228 if (shift > 15) dest->q = 0; 229 else { 230 dest->uw.w0 >>= shift; 231 dest->uw.w1 >>= shift; 232 dest->uw.w2 >>= shift; 233 dest->uw.w3 >>= shift; 234 } 235 break; 236 case 0x04: /*PSRAW*/ 237 MMX_reg tmp; 238 if (!shift) break; 239 tmp.q = dest->q; 240 if (shift > 15) { 241 dest->uw.w0 = (tmp.uw.w0&0x8000)?0xffff:0; 242 dest->uw.w1 = (tmp.uw.w1&0x8000)?0xffff:0; 243 dest->uw.w2 = (tmp.uw.w2&0x8000)?0xffff:0; 244 dest->uw.w3 = (tmp.uw.w3&0x8000)?0xffff:0; 245 } else { 246 dest->uw.w0 >>= shift; 247 dest->uw.w1 >>= shift; 248 dest->uw.w2 >>= shift; 249 dest->uw.w3 >>= shift; 250 if (tmp.uw.w0&0x8000) dest->uw.w0 |= (0xffff << (16 - shift)); 251 if (tmp.uw.w1&0x8000) dest->uw.w1 |= (0xffff << (16 - shift)); 252 if (tmp.uw.w2&0x8000) dest->uw.w2 |= (0xffff << (16 - shift)); 253 if (tmp.uw.w3&0x8000) dest->uw.w3 |= (0xffff << (16 - shift)); 254 } 255 break; 256 } 257 break; 258 } 259 CASE_0F_D(0xf2) /* PSLLD Pq,Qq */ 260 { 261 GetRM; 262 MMX_reg* dest=lookupRMregMM[rm]; 263 MMX_reg src; 264 if (rm>=0xc0) { 265 src.q=reg_mmx[rm&7].q; 266 } else { 267 GetEAa; 268 src.q=LoadMq(eaa); 269 } 270 if (src.q > 31) dest->q = 0; 271 else { 272 dest->ud.d0 <<= src.ub.b0; 273 dest->ud.d1 <<= src.ub.b0; 274 } 275 break; 276 } 277 CASE_0F_D(0xd2) /* PSRLD Pq,Qq */ 278 { 279 GetRM; 280 MMX_reg* dest=lookupRMregMM[rm]; 281 MMX_reg src; 282 if (rm>=0xc0) { 283 src.q=reg_mmx[rm&7].q; 284 } else { 285 GetEAa; 286 src.q=LoadMq(eaa); 287 } 288 if (src.q > 31) dest->q = 0; 289 else { 290 dest->ud.d0 >>= src.ub.b0; 291 dest->ud.d1 >>= src.ub.b0; 292 } 293 break; 294 } 295 CASE_0F_D(0xe2) /* PSRAD Pq,Qq */ 296 { 297 GetRM; 298 MMX_reg* dest=lookupRMregMM[rm]; 299 MMX_reg src; 300 MMX_reg tmp; 301 tmp.q = dest->q; 302 if (rm>=0xc0) { 303 src.q=reg_mmx[rm&7].q; 304 } else { 305 GetEAa; 306 src.q=LoadMq(eaa); 307 } 308 if (!src.q) break; 309 if (src.q > 31) { 310 dest->ud.d0 = (tmp.ud.d0&0x80000000)?0xffffffff:0; 311 dest->ud.d1 = (tmp.ud.d1&0x80000000)?0xffffffff:0; 312 } else { 313 dest->ud.d0 >>= src.ub.b0; 314 dest->ud.d1 >>= src.ub.b0; 315 if (tmp.ud.d0&0x80000000) dest->ud.d0 |= (0xffffffff << (32 - src.ub.b0)); 316 if (tmp.ud.d1&0x80000000) dest->ud.d1 |= (0xffffffff << (32 - src.ub.b0)); 317 } 318 break; 319 } 320 CASE_0F_D(0x72) /* PSLLD/PSRLD/PSRAD Pq,Ib */ 321 { 322 GetRM; 323 Bit8u op=(rm>>3)&7; 324 Bit8u shift=Fetchb(); 325 MMX_reg* dest=®_mmx[rm&7]; 326 switch (op) { 327 case 0x06: /*PSLLD*/ 328 if (shift > 31) dest->q = 0; 329 else { 330 dest->ud.d0 <<= shift; 331 dest->ud.d1 <<= shift; 332 } 333 break; 334 case 0x02: /*PSRLD*/ 335 if (shift > 31) dest->q = 0; 336 else { 337 dest->ud.d0 >>= shift; 338 dest->ud.d1 >>= shift; 339 } 340 break; 341 case 0x04: /*PSRAD*/ 342 MMX_reg tmp; 343 if (!shift) break; 344 tmp.q = dest->q; 345 if (shift > 31) { 346 dest->ud.d0 = (tmp.ud.d0&0x80000000)?0xffffffff:0; 347 dest->ud.d1 = (tmp.ud.d1&0x80000000)?0xffffffff:0; 348 } else { 349 dest->ud.d0 >>= shift; 350 dest->ud.d1 >>= shift; 351 if (tmp.ud.d0&0x80000000) dest->ud.d0 |= (0xffffffff << (32 - shift)); 352 if (tmp.ud.d1&0x80000000) dest->ud.d1 |= (0xffffffff << (32 - shift)); 353 } 354 break; 355 } 356 break; 357 } 358 359 CASE_0F_D(0xf3) /* PSLLQ Pq,Qq */ 360 { 361 GetRM; 362 MMX_reg* dest=lookupRMregMM[rm]; 363 MMX_reg src; 364 if (rm>=0xc0) { 365 src.q=reg_mmx[rm&7].q; 366 } else { 367 GetEAa; 368 src.q=LoadMq(eaa); 369 } 370 if (src.q > 63) dest->q = 0; 371 else dest->q <<= src.ub.b0; 372 break; 373 } 374 CASE_0F_D(0xd3) /* PSRLQ Pq,Qq */ 375 { 376 GetRM; 377 MMX_reg* dest=lookupRMregMM[rm]; 378 MMX_reg src; 379 if (rm>=0xc0) { 380 src.q=reg_mmx[rm&7].q; 381 } else { 382 GetEAa; 383 src.q=LoadMq(eaa); 384 } 385 if (src.q > 63) dest->q = 0; 386 else dest->q >>= src.ub.b0; 387 break; 388 } 389 CASE_0F_D(0x73) /* PSLLQ/PSRLQ Pq,Ib */ 390 { 391 GetRM; 392 Bit8u shift=Fetchb(); 393 MMX_reg* dest=®_mmx[rm&7]; 394 if (shift > 63) dest->q = 0; 395 else { 396 Bit8u op=rm&0x20; 397 if (op) { 398 dest->q <<= shift; 399 } else { 400 dest->q >>= shift; 401 } 402 } 403 break; 404 } 405 406 /* Math */ 407 CASE_0F_D(0xFC) /* PADDB Pq,Qq */ 408 { 409 GetRM; 410 MMX_reg* dest=lookupRMregMM[rm]; 411 MMX_reg src; 412 if (rm>=0xc0) { 413 src.q=reg_mmx[rm&7].q; 414 } else { 415 GetEAa; 416 src.q = LoadMq(eaa); 417 } 418 dest->ub.b0 += src.ub.b0; 419 dest->ub.b1 += src.ub.b1; 420 dest->ub.b2 += src.ub.b2; 421 dest->ub.b3 += src.ub.b3; 422 dest->ub.b4 += src.ub.b4; 423 dest->ub.b5 += src.ub.b5; 424 dest->ub.b6 += src.ub.b6; 425 dest->ub.b7 += src.ub.b7; 426 break; 427 } 428 CASE_0F_D(0xFD) /* PADDW Pq,Qq */ 429 { 430 GetRM; 431 MMX_reg* dest=lookupRMregMM[rm]; 432 MMX_reg src; 433 if (rm>=0xc0) { 434 src.q=reg_mmx[rm&7].q; 435 } else { 436 GetEAa; 437 src.q = LoadMq(eaa); 438 } 439 dest->uw.w0 += src.uw.w0; 440 dest->uw.w1 += src.uw.w1; 441 dest->uw.w2 += src.uw.w2; 442 dest->uw.w3 += src.uw.w3; 443 break; 444 } 445 CASE_0F_D(0xFE) /* PADDD Pq,Qq */ 446 { 447 GetRM; 448 MMX_reg* dest=lookupRMregMM[rm]; 449 MMX_reg src; 450 if (rm>=0xc0) { 451 src.q=reg_mmx[rm&7].q; 452 } else { 453 GetEAa; 454 src.q = LoadMq(eaa); 455 } 456 dest->ud.d0 += src.ud.d0; 457 dest->ud.d1 += src.ud.d1; 458 break; 459 } 460 CASE_0F_D(0xEC) /* PADDSB Pq,Qq */ 461 { 462 GetRM; 463 MMX_reg* dest=lookupRMregMM[rm]; 464 MMX_reg src; 465 if (rm>=0xc0) { 466 src.q = reg_mmx[rm&7].q; 467 } else { 468 GetEAa; 469 src.q = LoadMq(eaa); 470 } 471 dest->sb.b0 = SaturateWordSToByteS((Bit16s)dest->sb.b0+(Bit16s)src.sb.b0); 472 dest->sb.b1 = SaturateWordSToByteS((Bit16s)dest->sb.b1+(Bit16s)src.sb.b1); 473 dest->sb.b2 = SaturateWordSToByteS((Bit16s)dest->sb.b2+(Bit16s)src.sb.b2); 474 dest->sb.b3 = SaturateWordSToByteS((Bit16s)dest->sb.b3+(Bit16s)src.sb.b3); 475 dest->sb.b4 = SaturateWordSToByteS((Bit16s)dest->sb.b4+(Bit16s)src.sb.b4); 476 dest->sb.b5 = SaturateWordSToByteS((Bit16s)dest->sb.b5+(Bit16s)src.sb.b5); 477 dest->sb.b6 = SaturateWordSToByteS((Bit16s)dest->sb.b6+(Bit16s)src.sb.b6); 478 dest->sb.b7 = SaturateWordSToByteS((Bit16s)dest->sb.b7+(Bit16s)src.sb.b7); 479 break; 480 } 481 CASE_0F_D(0xED) /* PADDSW Pq,Qq */ 482 { 483 GetRM; 484 MMX_reg* dest=lookupRMregMM[rm]; 485 MMX_reg src; 486 if (rm>=0xc0) { 487 src.q = reg_mmx[rm&7].q; 488 } else { 489 GetEAa; 490 src.q = LoadMq(eaa); 491 } 492 dest->sw.w0 = SaturateDwordSToWordS((Bit32s)dest->sw.w0+(Bit32s)src.sw.w0); 493 dest->sw.w1 = SaturateDwordSToWordS((Bit32s)dest->sw.w1+(Bit32s)src.sw.w1); 494 dest->sw.w2 = SaturateDwordSToWordS((Bit32s)dest->sw.w2+(Bit32s)src.sw.w2); 495 dest->sw.w3 = SaturateDwordSToWordS((Bit32s)dest->sw.w3+(Bit32s)src.sw.w3); 496 break; 497 } 498 CASE_0F_D(0xDC) /* PADDUSB Pq,Qq */ 499 { 500 GetRM; 501 MMX_reg* dest=lookupRMregMM[rm]; 502 MMX_reg src; 503 if (rm>=0xc0) { 504 src.q = reg_mmx[rm&7].q; 505 } else { 506 GetEAa; 507 src.q = LoadMq(eaa); 508 } 509 dest->ub.b0 = SaturateWordSToByteU((Bit16s)dest->ub.b0+(Bit16s)src.ub.b0); 510 dest->ub.b1 = SaturateWordSToByteU((Bit16s)dest->ub.b1+(Bit16s)src.ub.b1); 511 dest->ub.b2 = SaturateWordSToByteU((Bit16s)dest->ub.b2+(Bit16s)src.ub.b2); 512 dest->ub.b3 = SaturateWordSToByteU((Bit16s)dest->ub.b3+(Bit16s)src.ub.b3); 513 dest->ub.b4 = SaturateWordSToByteU((Bit16s)dest->ub.b4+(Bit16s)src.ub.b4); 514 dest->ub.b5 = SaturateWordSToByteU((Bit16s)dest->ub.b5+(Bit16s)src.ub.b5); 515 dest->ub.b6 = SaturateWordSToByteU((Bit16s)dest->ub.b6+(Bit16s)src.ub.b6); 516 dest->ub.b7 = SaturateWordSToByteU((Bit16s)dest->ub.b7+(Bit16s)src.ub.b7); 517 break; 518 } 519 CASE_0F_D(0xDD) /* PADDUSW Pq,Qq */ 520 { 521 GetRM; 522 MMX_reg* dest=lookupRMregMM[rm]; 523 MMX_reg src; 524 if (rm>=0xc0) { 525 src.q = reg_mmx[rm&7].q; 526 } else { 527 GetEAa; 528 src.q = LoadMq(eaa); 529 } 530 dest->uw.w0 = SaturateDwordSToWordU((Bit32s)dest->uw.w0+(Bit32s)src.uw.w0); 531 dest->uw.w1 = SaturateDwordSToWordU((Bit32s)dest->uw.w1+(Bit32s)src.uw.w1); 532 dest->uw.w2 = SaturateDwordSToWordU((Bit32s)dest->uw.w2+(Bit32s)src.uw.w2); 533 dest->uw.w3 = SaturateDwordSToWordU((Bit32s)dest->uw.w3+(Bit32s)src.uw.w3); 534 break; 535 } 536 CASE_0F_D(0xF8) /* PSUBB Pq,Qq */ 537 { 538 GetRM; 539 MMX_reg* dest=lookupRMregMM[rm]; 540 MMX_reg src; 541 if (rm>=0xc0) { 542 src.q=reg_mmx[rm&7].q; 543 } else { 544 GetEAa; 545 src.q = LoadMq(eaa); 546 } 547 dest->ub.b0 -= src.ub.b0; 548 dest->ub.b1 -= src.ub.b1; 549 dest->ub.b2 -= src.ub.b2; 550 dest->ub.b3 -= src.ub.b3; 551 dest->ub.b4 -= src.ub.b4; 552 dest->ub.b5 -= src.ub.b5; 553 dest->ub.b6 -= src.ub.b6; 554 dest->ub.b7 -= src.ub.b7; 555 break; 556 } 557 CASE_0F_D(0xF9) /* PSUBW Pq,Qq */ 558 { 559 GetRM; 560 MMX_reg* dest=lookupRMregMM[rm]; 561 MMX_reg src; 562 if (rm>=0xc0) { 563 src.q=reg_mmx[rm&7].q; 564 } else { 565 GetEAa; 566 src.q = LoadMq(eaa); 567 } 568 dest->uw.w0 -= src.uw.w0; 569 dest->uw.w1 -= src.uw.w1; 570 dest->uw.w2 -= src.uw.w2; 571 dest->uw.w3 -= src.uw.w3; 572 break; 573 } 574 CASE_0F_D(0xFA) /* PSUBD Pq,Qq */ 575 { 576 GetRM; 577 MMX_reg* dest=lookupRMregMM[rm]; 578 MMX_reg src; 579 if (rm>=0xc0) { 580 src.q=reg_mmx[rm&7].q; 581 } else { 582 GetEAa; 583 src.q = LoadMq(eaa); 584 } 585 dest->ud.d0 -= src.ud.d0; 586 dest->ud.d1 -= src.ud.d1; 587 break; 588 } 589 CASE_0F_D(0xE8) /* PSUBSB Pq,Qq */ 590 { 591 GetRM; 592 MMX_reg* dest=lookupRMregMM[rm]; 593 MMX_reg src; 594 if (rm>=0xc0) { 595 src.q = reg_mmx[rm&7].q; 596 } else { 597 GetEAa; 598 src.q = LoadMq(eaa); 599 } 600 dest->sb.b0 = SaturateWordSToByteS((Bit16s)dest->sb.b0-(Bit16s)src.sb.b0); 601 dest->sb.b1 = SaturateWordSToByteS((Bit16s)dest->sb.b1-(Bit16s)src.sb.b1); 602 dest->sb.b2 = SaturateWordSToByteS((Bit16s)dest->sb.b2-(Bit16s)src.sb.b2); 603 dest->sb.b3 = SaturateWordSToByteS((Bit16s)dest->sb.b3-(Bit16s)src.sb.b3); 604 dest->sb.b4 = SaturateWordSToByteS((Bit16s)dest->sb.b4-(Bit16s)src.sb.b4); 605 dest->sb.b5 = SaturateWordSToByteS((Bit16s)dest->sb.b5-(Bit16s)src.sb.b5); 606 dest->sb.b6 = SaturateWordSToByteS((Bit16s)dest->sb.b6-(Bit16s)src.sb.b6); 607 dest->sb.b7 = SaturateWordSToByteS((Bit16s)dest->sb.b7-(Bit16s)src.sb.b7); 608 break; 609 } 610 CASE_0F_D(0xE9) /* PSUBSW Pq,Qq */ 611 { 612 GetRM; 613 MMX_reg* dest=lookupRMregMM[rm]; 614 MMX_reg src; 615 if (rm>=0xc0) { 616 src.q = reg_mmx[rm&7].q; 617 } else { 618 GetEAa; 619 src.q = LoadMq(eaa); 620 } 621 dest->sw.w0 = SaturateDwordSToWordS((Bit32s)dest->sw.w0-(Bit32s)src.sw.w0); 622 dest->sw.w1 = SaturateDwordSToWordS((Bit32s)dest->sw.w1-(Bit32s)src.sw.w1); 623 dest->sw.w2 = SaturateDwordSToWordS((Bit32s)dest->sw.w2-(Bit32s)src.sw.w2); 624 dest->sw.w3 = SaturateDwordSToWordS((Bit32s)dest->sw.w3-(Bit32s)src.sw.w3); 625 break; 626 } 627 CASE_0F_D(0xD8) /* PSUBUSB Pq,Qq */ 628 { 629 GetRM; 630 MMX_reg* dest=lookupRMregMM[rm]; 631 MMX_reg src; 632 MMX_reg result; 633 if (rm>=0xc0) { 634 src.q = reg_mmx[rm&7].q; 635 } else { 636 GetEAa; 637 src.q = LoadMq(eaa); 638 } 639 result.q = 0; 640 if (dest->ub.b0>src.ub.b0) result.ub.b0 = dest->ub.b0 - src.ub.b0; 641 if (dest->ub.b1>src.ub.b1) result.ub.b1 = dest->ub.b1 - src.ub.b1; 642 if (dest->ub.b2>src.ub.b2) result.ub.b2 = dest->ub.b2 - src.ub.b2; 643 if (dest->ub.b3>src.ub.b3) result.ub.b3 = dest->ub.b3 - src.ub.b3; 644 if (dest->ub.b4>src.ub.b4) result.ub.b4 = dest->ub.b4 - src.ub.b4; 645 if (dest->ub.b5>src.ub.b5) result.ub.b5 = dest->ub.b5 - src.ub.b5; 646 if (dest->ub.b6>src.ub.b6) result.ub.b6 = dest->ub.b6 - src.ub.b6; 647 if (dest->ub.b7>src.ub.b7) result.ub.b7 = dest->ub.b7 - src.ub.b7; 648 dest->q = result.q; 649 break; 650 } 651 652 CASE_0F_D(0xD9) /* PSUBUSW Pq,Qq */ 653 { 654 GetRM; 655 MMX_reg* dest=lookupRMregMM[rm]; 656 MMX_reg src; 657 MMX_reg result; 658 if (rm>=0xc0) { 659 src.q = reg_mmx[rm&7].q; 660 } else { 661 GetEAa; 662 src.q = LoadMq(eaa); 663 } 664 result.q = 0; 665 if (dest->uw.w0>src.uw.w0) result.uw.w0 = dest->uw.w0 - src.uw.w0; 666 if (dest->uw.w1>src.uw.w1) result.uw.w1 = dest->uw.w1 - src.uw.w1; 667 if (dest->uw.w2>src.uw.w2) result.uw.w2 = dest->uw.w2 - src.uw.w2; 668 if (dest->uw.w3>src.uw.w3) result.uw.w3 = dest->uw.w3 - src.uw.w3; 669 dest->q = result.q; 670 break; 671 } 672 CASE_0F_D(0xE5) /* PMULHW Pq,Qq */ 673 { 674 GetRM; 675 MMX_reg* dest=lookupRMregMM[rm]; 676 MMX_reg src; 677 if (rm>=0xc0) { 678 src.q = reg_mmx[rm&7].q; 679 } else { 680 GetEAa; 681 src.q = LoadMq(eaa); 682 } 683 Bit32s product0 = (Bit32s)dest->sw.w0 * (Bit32s)src.sw.w0; 684 Bit32s product1 = (Bit32s)dest->sw.w1 * (Bit32s)src.sw.w1; 685 Bit32s product2 = (Bit32s)dest->sw.w2 * (Bit32s)src.sw.w2; 686 Bit32s product3 = (Bit32s)dest->sw.w3 * (Bit32s)src.sw.w3; 687 dest->uw.w0 = (Bit16u)(product0 >> 16); 688 dest->uw.w1 = (Bit16u)(product1 >> 16); 689 dest->uw.w2 = (Bit16u)(product2 >> 16); 690 dest->uw.w3 = (Bit16u)(product3 >> 16); 691 break; 692 } 693 CASE_0F_D(0xD5) /* PMULLW Pq,Qq */ 694 { 695 GetRM; 696 MMX_reg* dest=lookupRMregMM[rm]; 697 MMX_reg src; 698 if (rm>=0xc0) { 699 src.q = reg_mmx[rm&7].q; 700 } else { 701 GetEAa; 702 src.q = LoadMq(eaa); 703 } 704 Bit32u product0 = (Bit32u)dest->uw.w0 * (Bit32u)src.uw.w0; 705 Bit32u product1 = (Bit32u)dest->uw.w1 * (Bit32u)src.uw.w1; 706 Bit32u product2 = (Bit32u)dest->uw.w2 * (Bit32u)src.uw.w2; 707 Bit32u product3 = (Bit32u)dest->uw.w3 * (Bit32u)src.uw.w3; 708 dest->uw.w0 = (product0 & 0xffff); 709 dest->uw.w1 = (product1 & 0xffff); 710 dest->uw.w2 = (product2 & 0xffff); 711 dest->uw.w3 = (product3 & 0xffff); 712 break; 713 } 714 CASE_0F_D(0xF5) /* PMADDWD Pq,Qq */ 715 { 716 GetRM; 717 MMX_reg* dest=lookupRMregMM[rm]; 718 MMX_reg src; 719 if (rm>=0xc0) { 720 src.q = reg_mmx[rm&7].q; 721 } else { 722 GetEAa; 723 src.q = LoadMq(eaa); 724 } 725 if (dest->ud.d0 == 0x80008000 && src.ud.d0 == 0x80008000) 726 dest->ud.d0 = 0x80000000; 727 else { 728 Bit32s product0 = (Bit32s)dest->sw.w0 * (Bit32s)src.sw.w0; 729 Bit32s product1 = (Bit32s)dest->sw.w1 * (Bit32s)src.sw.w1; 730 dest->ud.d0 = product0 + product1; 731 } 732 if (dest->ud.d1 == 0x80008000 && src.ud.d1 == 0x80008000) 733 dest->ud.d1 = 0x80000000; 734 else { 735 Bit32s product2 = (Bit32s)dest->sw.w2 * (Bit32s)src.sw.w2; 736 Bit32s product3 = (Bit32s)dest->sw.w3 * (Bit32s)src.sw.w3; 737 dest->sd.d1 = product2 + product3; 738 } 739 break; 740 } 741 742 /* Comparison */ 743 CASE_0F_D(0x74) /* PCMPEQB Pq,Qq */ 744 { 745 GetRM; 746 MMX_reg* dest=lookupRMregMM[rm]; 747 MMX_reg src; 748 if (rm>=0xc0) { 749 src.q=reg_mmx[rm&7].q; 750 } else { 751 GetEAa; 752 src.q = LoadMq(eaa); 753 } 754 dest->ub.b0 = dest->ub.b0==src.ub.b0?0xff:0; 755 dest->ub.b1 = dest->ub.b1==src.ub.b1?0xff:0; 756 dest->ub.b2 = dest->ub.b2==src.ub.b2?0xff:0; 757 dest->ub.b3 = dest->ub.b3==src.ub.b3?0xff:0; 758 dest->ub.b4 = dest->ub.b4==src.ub.b4?0xff:0; 759 dest->ub.b5 = dest->ub.b5==src.ub.b5?0xff:0; 760 dest->ub.b6 = dest->ub.b6==src.ub.b6?0xff:0; 761 dest->ub.b7 = dest->ub.b7==src.ub.b7?0xff:0; 762 break; 763 } 764 CASE_0F_D(0x75) /* PCMPEQW Pq,Qq */ 765 { 766 GetRM; 767 MMX_reg* dest=lookupRMregMM[rm]; 768 MMX_reg src; 769 if (rm>=0xc0) { 770 src.q=reg_mmx[rm&7].q; 771 } else { 772 GetEAa; 773 src.q = LoadMq(eaa); 774 } 775 dest->uw.w0 = dest->uw.w0==src.uw.w0?0xffff:0; 776 dest->uw.w1 = dest->uw.w1==src.uw.w1?0xffff:0; 777 dest->uw.w2 = dest->uw.w2==src.uw.w2?0xffff:0; 778 dest->uw.w3 = dest->uw.w3==src.uw.w3?0xffff:0; 779 break; 780 } 781 CASE_0F_D(0x76) /* PCMPEQD Pq,Qq */ 782 { 783 GetRM; 784 MMX_reg* dest=lookupRMregMM[rm]; 785 MMX_reg src; 786 if (rm>=0xc0) { 787 src.q=reg_mmx[rm&7].q; 788 } else { 789 GetEAa; 790 src.q = LoadMq(eaa); 791 } 792 dest->ud.d0 = dest->ud.d0==src.ud.d0?0xffffffff:0; 793 dest->ud.d1 = dest->ud.d1==src.ud.d1?0xffffffff:0; 794 break; 795 } 796 CASE_0F_D(0x64) /* PCMPGTB Pq,Qq */ 797 { 798 GetRM; 799 MMX_reg* dest=lookupRMregMM[rm]; 800 MMX_reg src; 801 if (rm>=0xc0) { 802 src.q=reg_mmx[rm&7].q; 803 } else { 804 GetEAa; 805 src.q = LoadMq(eaa); 806 } 807 dest->ub.b0 = dest->sb.b0>src.sb.b0?0xff:0; 808 dest->ub.b1 = dest->sb.b1>src.sb.b1?0xff:0; 809 dest->ub.b2 = dest->sb.b2>src.sb.b2?0xff:0; 810 dest->ub.b3 = dest->sb.b3>src.sb.b3?0xff:0; 811 dest->ub.b4 = dest->sb.b4>src.sb.b4?0xff:0; 812 dest->ub.b5 = dest->sb.b5>src.sb.b5?0xff:0; 813 dest->ub.b6 = dest->sb.b6>src.sb.b6?0xff:0; 814 dest->ub.b7 = dest->sb.b7>src.sb.b7?0xff:0; 815 break; 816 } 817 CASE_0F_D(0x65) /* PCMPGTW Pq,Qq */ 818 { 819 GetRM; 820 MMX_reg* dest=lookupRMregMM[rm]; 821 MMX_reg src; 822 if (rm>=0xc0) { 823 src.q=reg_mmx[rm&7].q; 824 } else { 825 GetEAa; 826 src.q = LoadMq(eaa); 827 } 828 dest->uw.w0 = dest->sw.w0>src.sw.w0?0xffff:0; 829 dest->uw.w1 = dest->sw.w1>src.sw.w1?0xffff:0; 830 dest->uw.w2 = dest->sw.w2>src.sw.w2?0xffff:0; 831 dest->uw.w3 = dest->sw.w3>src.sw.w3?0xffff:0; 832 break; 833 } 834 CASE_0F_D(0x66) /* PCMPGTD Pq,Qq */ 835 { 836 GetRM; 837 MMX_reg* dest=lookupRMregMM[rm]; 838 MMX_reg src; 839 if (rm>=0xc0) { 840 src.q=reg_mmx[rm&7].q; 841 } else { 842 GetEAa; 843 src.q = LoadMq(eaa); 844 } 845 dest->ud.d0 = dest->sd.d0>src.sd.d0?0xffffffff:0; 846 dest->ud.d1 = dest->sd.d1>src.sd.d1?0xffffffff:0; 847 break; 848 } 849 850 /* Data Packing */ 851 CASE_0F_D(0x63) /* PACKSSWB Pq,Qq */ 852 { 853 GetRM; 854 MMX_reg* dest=lookupRMregMM[rm]; 855 MMX_reg src; 856 if (rm>=0xc0) { 857 src.q=reg_mmx[rm&7].q; 858 } else { 859 GetEAa; 860 src.q = LoadMq(eaa); 861 } 862 dest->sb.b0 = SaturateWordSToByteS(dest->sw.w0); 863 dest->sb.b1 = SaturateWordSToByteS(dest->sw.w1); 864 dest->sb.b2 = SaturateWordSToByteS(dest->sw.w2); 865 dest->sb.b3 = SaturateWordSToByteS(dest->sw.w3); 866 dest->sb.b4 = SaturateWordSToByteS(src.sw.w0); 867 dest->sb.b5 = SaturateWordSToByteS(src.sw.w1); 868 dest->sb.b6 = SaturateWordSToByteS(src.sw.w2); 869 dest->sb.b7 = SaturateWordSToByteS(src.sw.w3); 870 break; 871 } 872 CASE_0F_D(0x6B) /* PACKSSDW Pq,Qq */ 873 { 874 GetRM; 875 MMX_reg* dest=lookupRMregMM[rm]; 876 MMX_reg src; 877 if (rm>=0xc0) { 878 src.q=reg_mmx[rm&7].q; 879 } else { 880 GetEAa; 881 src.q = LoadMq(eaa); 882 } 883 dest->sw.w0 = SaturateDwordSToWordS(dest->sd.d0); 884 dest->sw.w1 = SaturateDwordSToWordS(dest->sd.d1); 885 dest->sw.w2 = SaturateDwordSToWordS(src.sd.d0); 886 dest->sw.w3 = SaturateDwordSToWordS(src.sd.d1); 887 break; 888 } 889 CASE_0F_D(0x67) /* PACKUSWB Pq,Qq */ 890 { 891 GetRM; 892 MMX_reg* dest=lookupRMregMM[rm]; 893 MMX_reg src; 894 if (rm>=0xc0) { 895 src.q=reg_mmx[rm&7].q; 896 } else { 897 GetEAa; 898 src.q = LoadMq(eaa); 899 } 900 dest->ub.b0 = SaturateWordSToByteU(dest->sw.w0); 901 dest->ub.b1 = SaturateWordSToByteU(dest->sw.w1); 902 dest->ub.b2 = SaturateWordSToByteU(dest->sw.w2); 903 dest->ub.b3 = SaturateWordSToByteU(dest->sw.w3); 904 dest->ub.b4 = SaturateWordSToByteU(src.sw.w0); 905 dest->ub.b5 = SaturateWordSToByteU(src.sw.w1); 906 dest->ub.b6 = SaturateWordSToByteU(src.sw.w2); 907 dest->ub.b7 = SaturateWordSToByteU(src.sw.w3); 908 break; 909 } 910 CASE_0F_D(0x68) /* PUNPCKHBW Pq,Qq */ 911 { 912 GetRM; 913 MMX_reg* dest=lookupRMregMM[rm]; 914 MMX_reg src; 915 if (rm>=0xc0) { 916 src.q=reg_mmx[rm&7].q; 917 } else { 918 GetEAa; 919 src.q = LoadMq(eaa); 920 } 921 dest->ub.b0 = dest->ub.b4; 922 dest->ub.b1 = src.ub.b4; 923 dest->ub.b2 = dest->ub.b5; 924 dest->ub.b3 = src.ub.b5; 925 dest->ub.b4 = dest->ub.b6; 926 dest->ub.b5 = src.ub.b6; 927 dest->ub.b6 = dest->ub.b7; 928 dest->ub.b7 = src.ub.b7; 929 break; 930 } 931 CASE_0F_D(0x69) /* PUNPCKHWD Pq,Qq */ 932 { 933 GetRM; 934 MMX_reg* dest=lookupRMregMM[rm]; 935 MMX_reg src; 936 if (rm>=0xc0) { 937 src.q=reg_mmx[rm&7].q; 938 } else { 939 GetEAa; 940 src.q = LoadMq(eaa); 941 } 942 dest->uw.w0 = dest->uw.w2; 943 dest->uw.w1 = src.uw.w2; 944 dest->uw.w2 = dest->uw.w3; 945 dest->uw.w3 = src.uw.w3; 946 break; 947 } 948 CASE_0F_D(0x6A) /* PUNPCKHDQ Pq,Qq */ 949 { 950 GetRM; 951 MMX_reg* dest=lookupRMregMM[rm]; 952 MMX_reg src; 953 if (rm>=0xc0) { 954 src.q=reg_mmx[rm&7].q; 955 } else { 956 GetEAa; 957 src.q = LoadMq(eaa); 958 } 959 dest->ud.d0 = dest->ud.d1; 960 dest->ud.d1 = src.ud.d1; 961 break; 962 } 963 CASE_0F_D(0x60) /* PUNPCKLBW Pq,Qq */ 964 { 965 GetRM; 966 MMX_reg* dest=lookupRMregMM[rm]; 967 MMX_reg src; 968 if (rm>=0xc0) { 969 src.q=reg_mmx[rm&7].q; 970 } else { 971 GetEAa; 972 src.q = LoadMq(eaa); 973 } 974 dest->ub.b7 = src.ub.b3; 975 dest->ub.b6 = dest->ub.b3; 976 dest->ub.b5 = src.ub.b2; 977 dest->ub.b4 = dest->ub.b2; 978 dest->ub.b3 = src.ub.b1; 979 dest->ub.b2 = dest->ub.b1; 980 dest->ub.b1 = src.ub.b0; 981 dest->ub.b0 = dest->ub.b0; 982 break; 983 } 984 CASE_0F_D(0x61) /* PUNPCKLWD Pq,Qq */ 985 { 986 GetRM; 987 MMX_reg* dest=lookupRMregMM[rm]; 988 MMX_reg src; 989 if (rm>=0xc0) { 990 src.q=reg_mmx[rm&7].q; 991 } else { 992 GetEAa; 993 src.q = LoadMq(eaa); 994 } 995 dest->uw.w3 = src.uw.w1; 996 dest->uw.w2 = dest->uw.w1; 997 dest->uw.w1 = src.uw.w0; 998 dest->uw.w0 = dest->uw.w0; 999 break; 1000 } 1001 CASE_0F_D(0x62) /* PUNPCKLDQ Pq,Qq */ 1002 { 1003 GetRM; 1004 MMX_reg* dest=lookupRMregMM[rm]; 1005 MMX_reg src; 1006 if (rm>=0xc0) { 1007 src.q=reg_mmx[rm&7].q; 1008 } else { 1009 GetEAa; 1010 src.q = LoadMq(eaa); 1011 } 1012 dest->ud.d1 = src.ud.d0; 1013 break; 1014 } 1015