DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/cpu/core_normal/prefix_0f_mmx.h
00001 /*
00002  *  Copyright (C) 2002-2013  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 /* State Management */
00020         CASE_0F_D(0x77)                                                                                         /* EMMS */
00021         {
00022                 setFPU(TAG_Empty);
00023                 break;
00024         }
00025 
00026 
00027 /* Data Movement */
00028         CASE_0F_D(0x6e)                                                                                         /* MOVD Pq,Ed */
00029         {
00030                 GetRM;
00031                 MMX_reg* rmrq=lookupRMregMM[rm];
00032                 if (rm>=0xc0) {
00033                         GetEArd;
00034                         rmrq->ud.d0=*(Bit32u*)eard;
00035                         rmrq->ud.d1=0;
00036                 } else {
00037                         GetEAa;
00038                         rmrq->ud.d0=LoadMd(eaa);
00039                         rmrq->ud.d1=0;
00040                 }
00041                 break;
00042         }
00043         CASE_0F_D(0x7e)                                                                                         /* MOVD Ed,Pq */
00044         {
00045                 GetRM;
00046                 MMX_reg* rmrq=lookupRMregMM[rm];
00047                 if (rm>=0xc0) {
00048                         GetEArd;
00049                         *(Bit32u*)eard=rmrq->ud.d0;
00050                 } else {
00051                         GetEAa;
00052                         SaveMd(eaa,rmrq->ud.d0);
00053                 }
00054                 break;
00055         }
00056 
00057         CASE_0F_D(0x6f)                                                                                         /* MOVQ Pq,Qq */
00058         {
00059                 GetRM;
00060                 MMX_reg* dest=lookupRMregMM[rm];
00061                 if (rm>=0xc0) {
00062                         MMX_reg* src=&reg_mmx[rm&7];
00063                         dest->q = src->q;
00064                 } else {
00065                         GetEAa;
00066                         dest->q=LoadMq(eaa);
00067                 }
00068                 break;
00069         }
00070         CASE_0F_D(0x7f)                                                                                         /* MOVQ Qq,Pq */
00071         {
00072                 GetRM;
00073                 MMX_reg* dest=lookupRMregMM[rm];
00074                 if (rm>=0xc0) {
00075                         MMX_reg* src=&reg_mmx[rm&7];
00076                         dest->q = src->q;
00077                 } else {
00078                         GetEAa;
00079                         SaveMq(eaa,dest->q);
00080                 }
00081                 break;
00082         }
00083 
00084 /* Boolean Logic */
00085         CASE_0F_D(0xef)                                                                                         /* PXOR Pq,Qq */
00086         {
00087                 GetRM;
00088                 MMX_reg* dest=lookupRMregMM[rm];
00089                 if (rm>=0xc0) {
00090                         MMX_reg* src=&reg_mmx[rm&7];
00091                         dest->q ^= src->q;
00092                 } else {
00093                         GetEAa;
00094                         dest->q ^= LoadMq(eaa);
00095                 }
00096                 break;
00097         }
00098 
00099         CASE_0F_D(0xeb)                                                                                         /* POR Pq,Qq */
00100         {
00101                 GetRM;
00102                 MMX_reg* dest=lookupRMregMM[rm];
00103                 if (rm>=0xc0) {
00104                         MMX_reg* src=&reg_mmx[rm&7];
00105                         dest->q |= src->q;
00106                 } else {
00107                         GetEAa;
00108                         dest->q |= LoadMq(eaa);
00109                 }
00110                 break;
00111         }
00112         CASE_0F_D(0xdb)                                                                                         /* PAND Pq,Qq */
00113         {
00114                 GetRM;
00115                 MMX_reg* dest=lookupRMregMM[rm];
00116                 if (rm>=0xc0) {
00117                         MMX_reg* src=&reg_mmx[rm&7];
00118                         dest->q &= src->q;
00119                 } else {
00120                         GetEAa;
00121                         dest->q &= LoadMq(eaa);
00122                 }
00123                 break;
00124         }
00125         CASE_0F_D(0xdf)                                                                                         /* PANDN Pq,Qq */
00126         {
00127                 GetRM;
00128                 MMX_reg* dest=lookupRMregMM[rm];
00129                 if (rm>=0xc0) {
00130                         MMX_reg* src=&reg_mmx[rm&7];
00131                         dest->q = ~dest->q & src->q;
00132                 } else {
00133                         GetEAa;
00134                         dest->q = ~dest->q & LoadMq(eaa);
00135                 }
00136                 break;
00137         }
00138 
00139 /* Shift */
00140         CASE_0F_D(0xf1)                                                                                         /* PSLLW Pq,Qq */
00141         {
00142                 GetRM;
00143                 MMX_reg* dest=lookupRMregMM[rm];
00144                 MMX_reg src;
00145                 if (rm>=0xc0) {
00146                         src.q=reg_mmx[rm&7].q;
00147                 } else {
00148                         GetEAa;
00149                         src.q=LoadMq(eaa);
00150                 }
00151                 if (src.q > 15) dest->q = 0;
00152                 else {
00153                         dest->uw.w0 <<= src.ub.b0;
00154                         dest->uw.w1 <<= src.ub.b0;
00155                         dest->uw.w2 <<= src.ub.b0;
00156                         dest->uw.w3 <<= src.ub.b0;
00157                 }
00158                 break;
00159         }
00160         CASE_0F_D(0xd1)                                                                                         /* PSRLW Pq,Qq */
00161         {
00162                 GetRM;
00163                 MMX_reg* dest=lookupRMregMM[rm];
00164                 MMX_reg src;
00165                 if (rm>=0xc0) {
00166                         src.q=reg_mmx[rm&7].q;
00167                 } else {
00168                         GetEAa;
00169                         src.q=LoadMq(eaa);
00170                 }
00171                 if (src.q > 15) dest->q = 0;
00172                 else {
00173                         dest->uw.w0 >>= src.ub.b0;
00174                         dest->uw.w1 >>= src.ub.b0;
00175                         dest->uw.w2 >>= src.ub.b0;
00176                         dest->uw.w3 >>= src.ub.b0;
00177                 }
00178                 break;
00179         }
00180         CASE_0F_D(0xe1)                                                                                         /* PSRAW Pq,Qq */
00181         {
00182                 GetRM;
00183                 MMX_reg* dest=lookupRMregMM[rm];
00184                 MMX_reg src;
00185                 MMX_reg tmp;
00186                 tmp.q = dest->q;
00187                 if (rm>=0xc0) {
00188                         src.q=reg_mmx[rm&7].q;
00189                 } else {
00190                         GetEAa;
00191                         src.q=LoadMq(eaa);
00192                 }
00193                 if (!src.q) break;
00194                 if (src.q > 15) {
00195                         dest->uw.w0 = (tmp.uw.w0&0x8000)?0xffff:0;
00196                         dest->uw.w1 = (tmp.uw.w1&0x8000)?0xffff:0;
00197                         dest->uw.w2 = (tmp.uw.w2&0x8000)?0xffff:0;
00198                         dest->uw.w3 = (tmp.uw.w3&0x8000)?0xffff:0;
00199                 } else {
00200                         dest->uw.w0 >>= src.ub.b0;
00201                         dest->uw.w1 >>= src.ub.b0;
00202                         dest->uw.w2 >>= src.ub.b0;
00203                         dest->uw.w3 >>= src.ub.b0;
00204                         if (tmp.uw.w0&0x8000) dest->uw.w0 |= (0xffff << (16 - src.ub.b0));
00205                         if (tmp.uw.w1&0x8000) dest->uw.w1 |= (0xffff << (16 - src.ub.b0));
00206                         if (tmp.uw.w2&0x8000) dest->uw.w2 |= (0xffff << (16 - src.ub.b0));
00207                         if (tmp.uw.w3&0x8000) dest->uw.w3 |= (0xffff << (16 - src.ub.b0));
00208                 }
00209                 break;
00210         }
00211         CASE_0F_D(0x71)                                                                                         /* PSLLW/PSRLW/PSRAW Pq,Ib */
00212         {
00213                 GetRM;
00214                 Bit8u op=(rm>>3)&7;
00215                 Bit8u shift=Fetchb();
00216                 MMX_reg* dest=&reg_mmx[rm&7];
00217                 switch (op) {
00218                         case 0x06:      /*PSLLW*/
00219                                 if (shift > 15) dest->q = 0;
00220                                 else {
00221                                         dest->uw.w0 <<= shift;
00222                                         dest->uw.w1 <<= shift;
00223                                         dest->uw.w2 <<= shift;
00224                                         dest->uw.w3 <<= shift;
00225                                 }
00226                                 break;
00227                         case 0x02:  /*PSRLW*/
00228                                 if (shift > 15) dest->q = 0;
00229                                 else {
00230                                         dest->uw.w0 >>= shift;
00231                                         dest->uw.w1 >>= shift;
00232                                         dest->uw.w2 >>= shift;
00233                                         dest->uw.w3 >>= shift;
00234                                 }
00235                                 break;
00236                         case 0x04:  /*PSRAW*/
00237                                 MMX_reg tmp;
00238                                 if (!shift) break;
00239                                 tmp.q = dest->q;
00240                                 if (shift > 15) {
00241                                         dest->uw.w0 = (tmp.uw.w0&0x8000)?0xffff:0;
00242                                         dest->uw.w1 = (tmp.uw.w1&0x8000)?0xffff:0;
00243                                         dest->uw.w2 = (tmp.uw.w2&0x8000)?0xffff:0;
00244                                         dest->uw.w3 = (tmp.uw.w3&0x8000)?0xffff:0;
00245                                 } else {
00246                                         dest->uw.w0 >>= shift;
00247                                         dest->uw.w1 >>= shift;
00248                                         dest->uw.w2 >>= shift;
00249                                         dest->uw.w3 >>= shift;
00250                                         if (tmp.uw.w0&0x8000) dest->uw.w0 |= (0xffff << (16 - shift));
00251                                         if (tmp.uw.w1&0x8000) dest->uw.w1 |= (0xffff << (16 - shift));
00252                                         if (tmp.uw.w2&0x8000) dest->uw.w2 |= (0xffff << (16 - shift));
00253                                         if (tmp.uw.w3&0x8000) dest->uw.w3 |= (0xffff << (16 - shift));
00254                                 }
00255                                 break;
00256                 }
00257                 break;
00258         }
00259         CASE_0F_D(0xf2)                                                                                         /* PSLLD Pq,Qq */
00260         {
00261                 GetRM;
00262                 MMX_reg* dest=lookupRMregMM[rm];
00263                 MMX_reg src;
00264                 if (rm>=0xc0) {
00265                         src.q=reg_mmx[rm&7].q;
00266                 } else {
00267                         GetEAa;
00268                         src.q=LoadMq(eaa);
00269                 }
00270                 if (src.q > 31) dest->q = 0;
00271                 else {
00272                         dest->ud.d0 <<= src.ub.b0;
00273                         dest->ud.d1 <<= src.ub.b0;
00274                 }
00275                 break;
00276         }
00277         CASE_0F_D(0xd2)                                                                                         /* PSRLD Pq,Qq */
00278         {
00279                 GetRM;
00280                 MMX_reg* dest=lookupRMregMM[rm];
00281                 MMX_reg src;
00282                 if (rm>=0xc0) {
00283                         src.q=reg_mmx[rm&7].q;
00284                 } else {
00285                         GetEAa;
00286                         src.q=LoadMq(eaa);
00287                 }
00288                 if (src.q > 31) dest->q = 0;
00289                 else {
00290                         dest->ud.d0 >>= src.ub.b0;
00291                         dest->ud.d1 >>= src.ub.b0;
00292                 }
00293                 break;
00294         }
00295         CASE_0F_D(0xe2)                                                                                         /* PSRAD Pq,Qq */
00296         {
00297                 GetRM;
00298                 MMX_reg* dest=lookupRMregMM[rm];
00299                 MMX_reg src;
00300                 MMX_reg tmp;
00301                 tmp.q = dest->q;
00302                 if (rm>=0xc0) {
00303                         src.q=reg_mmx[rm&7].q;
00304                 } else {
00305                         GetEAa;
00306                         src.q=LoadMq(eaa);
00307                 }
00308                 if (!src.q) break;
00309                 if (src.q > 31) {
00310                         dest->ud.d0 = (tmp.ud.d0&0x80000000)?0xffffffff:0;
00311                         dest->ud.d1 = (tmp.ud.d1&0x80000000)?0xffffffff:0;
00312                 } else {
00313                         dest->ud.d0 >>= src.ub.b0;
00314                         dest->ud.d1 >>= src.ub.b0;
00315                         if (tmp.ud.d0&0x80000000) dest->ud.d0 |= (0xffffffff << (32 - src.ub.b0));
00316                         if (tmp.ud.d1&0x80000000) dest->ud.d1 |= (0xffffffff << (32 - src.ub.b0));
00317                 }
00318                 break;
00319         }
00320         CASE_0F_D(0x72)                                                                                         /* PSLLD/PSRLD/PSRAD Pq,Ib */
00321         {
00322                 GetRM;
00323                 Bit8u op=(rm>>3)&7;
00324                 Bit8u shift=Fetchb();
00325                 MMX_reg* dest=&reg_mmx[rm&7];
00326                 switch (op) {
00327                         case 0x06:      /*PSLLD*/
00328                                 if (shift > 31) dest->q = 0;
00329                                 else {
00330                                         dest->ud.d0 <<= shift;
00331                                         dest->ud.d1 <<= shift;
00332                                 }
00333                                 break;
00334                         case 0x02:  /*PSRLD*/
00335                                 if (shift > 31) dest->q = 0;
00336                                 else {
00337                                         dest->ud.d0 >>= shift;
00338                                         dest->ud.d1 >>= shift;
00339                                 }
00340                                 break;
00341                         case 0x04:  /*PSRAD*/
00342                                 MMX_reg tmp;
00343                                 if (!shift) break;
00344                                 tmp.q = dest->q;
00345                                 if (shift > 31) { 
00346                                         dest->ud.d0 = (tmp.ud.d0&0x80000000)?0xffffffff:0;
00347                                         dest->ud.d1 = (tmp.ud.d1&0x80000000)?0xffffffff:0;
00348                                 } else {
00349                                         dest->ud.d0 >>= shift;
00350                                         dest->ud.d1 >>= shift;
00351                                         if (tmp.ud.d0&0x80000000) dest->ud.d0 |= (0xffffffff << (32 - shift));
00352                                         if (tmp.ud.d1&0x80000000) dest->ud.d1 |= (0xffffffff << (32 - shift));
00353                                 }
00354                                 break;
00355                 }
00356                 break;
00357         }
00358 
00359         CASE_0F_D(0xf3)                                                                                         /* PSLLQ Pq,Qq */
00360         {
00361                 GetRM;
00362                 MMX_reg* dest=lookupRMregMM[rm];
00363                 MMX_reg src;
00364                 if (rm>=0xc0) {
00365                         src.q=reg_mmx[rm&7].q;
00366                 } else {
00367                         GetEAa;
00368                         src.q=LoadMq(eaa);
00369                 }
00370                 if (src.q > 63) dest->q = 0;
00371                 else dest->q <<= src.ub.b0;
00372                 break;
00373         }
00374         CASE_0F_D(0xd3)                                                                                         /* PSRLQ Pq,Qq */
00375         {
00376                 GetRM;
00377                 MMX_reg* dest=lookupRMregMM[rm];
00378                 MMX_reg src;
00379                 if (rm>=0xc0) {
00380                         src.q=reg_mmx[rm&7].q;
00381                 } else {
00382                         GetEAa;
00383                         src.q=LoadMq(eaa);
00384                 }
00385                 if (src.q > 63) dest->q = 0;
00386                 else dest->q >>= src.ub.b0;
00387                 break;
00388         }
00389         CASE_0F_D(0x73)                                                                                         /* PSLLQ/PSRLQ Pq,Ib */
00390         {
00391                 GetRM;
00392                 Bit8u shift=Fetchb();
00393                 MMX_reg* dest=&reg_mmx[rm&7];
00394                 if (shift > 63) dest->q = 0;
00395                 else {
00396                         Bit8u op=rm&0x20;
00397                         if (op) {
00398                                 dest->q <<= shift;
00399                         } else {
00400                                 dest->q >>= shift;
00401                         }
00402                 }
00403                 break;
00404         }
00405 
00406 /* Math */
00407         CASE_0F_D(0xFC)                                                                                         /* PADDB Pq,Qq */
00408         {
00409                 GetRM;
00410                 MMX_reg* dest=lookupRMregMM[rm];
00411                 MMX_reg src;
00412                 if (rm>=0xc0) {
00413                         src.q=reg_mmx[rm&7].q;
00414                 } else {
00415                         GetEAa;
00416                         src.q = LoadMq(eaa);
00417                 }
00418                 dest->ub.b0 += src.ub.b0;
00419                 dest->ub.b1 += src.ub.b1;
00420                 dest->ub.b2 += src.ub.b2;
00421                 dest->ub.b3 += src.ub.b3;
00422                 dest->ub.b4 += src.ub.b4;
00423                 dest->ub.b5 += src.ub.b5;
00424                 dest->ub.b6 += src.ub.b6;
00425                 dest->ub.b7 += src.ub.b7;
00426                 break;
00427         }
00428         CASE_0F_D(0xFD)                                                                                         /* PADDW Pq,Qq */
00429         {
00430                 GetRM;
00431                 MMX_reg* dest=lookupRMregMM[rm];
00432                 MMX_reg src;
00433                 if (rm>=0xc0) {
00434                         src.q=reg_mmx[rm&7].q;
00435                 } else {
00436                         GetEAa;
00437                         src.q = LoadMq(eaa);
00438                 }
00439                 dest->uw.w0 += src.uw.w0;
00440                 dest->uw.w1 += src.uw.w1;
00441                 dest->uw.w2 += src.uw.w2;
00442                 dest->uw.w3 += src.uw.w3;
00443                 break;
00444         }
00445         CASE_0F_D(0xFE)                                                                                         /* PADDD Pq,Qq */
00446         {
00447                 GetRM;
00448                 MMX_reg* dest=lookupRMregMM[rm];
00449                 MMX_reg src;
00450                 if (rm>=0xc0) {
00451                         src.q=reg_mmx[rm&7].q;
00452                 } else {
00453                         GetEAa;
00454                         src.q = LoadMq(eaa);
00455                 }
00456                 dest->ud.d0 += src.ud.d0;
00457                 dest->ud.d1 += src.ud.d1;
00458                 break;
00459         }
00460         CASE_0F_D(0xEC)                                                                                         /* PADDSB Pq,Qq */
00461         {
00462                 GetRM;
00463                 MMX_reg* dest=lookupRMregMM[rm];
00464                 MMX_reg src;
00465                 if (rm>=0xc0) {
00466                         src.q = reg_mmx[rm&7].q;
00467                 } else {
00468                         GetEAa;
00469                         src.q = LoadMq(eaa);
00470                 }
00471                 dest->sb.b0 = SaturateWordSToByteS((Bit16s)dest->sb.b0+(Bit16s)src.sb.b0);
00472                 dest->sb.b1 = SaturateWordSToByteS((Bit16s)dest->sb.b1+(Bit16s)src.sb.b1);
00473                 dest->sb.b2 = SaturateWordSToByteS((Bit16s)dest->sb.b2+(Bit16s)src.sb.b2);
00474                 dest->sb.b3 = SaturateWordSToByteS((Bit16s)dest->sb.b3+(Bit16s)src.sb.b3);
00475                 dest->sb.b4 = SaturateWordSToByteS((Bit16s)dest->sb.b4+(Bit16s)src.sb.b4);
00476                 dest->sb.b5 = SaturateWordSToByteS((Bit16s)dest->sb.b5+(Bit16s)src.sb.b5);
00477                 dest->sb.b6 = SaturateWordSToByteS((Bit16s)dest->sb.b6+(Bit16s)src.sb.b6);
00478                 dest->sb.b7 = SaturateWordSToByteS((Bit16s)dest->sb.b7+(Bit16s)src.sb.b7);
00479                 break;
00480         }
00481         CASE_0F_D(0xED)                                                                                         /* PADDSW Pq,Qq */
00482         {
00483                 GetRM;
00484                 MMX_reg* dest=lookupRMregMM[rm];
00485                 MMX_reg src;
00486                 if (rm>=0xc0) {
00487                         src.q = reg_mmx[rm&7].q;
00488                 } else {
00489                         GetEAa;
00490                         src.q = LoadMq(eaa);
00491                 }
00492                 dest->sw.w0 = SaturateDwordSToWordS((Bit32s)dest->sw.w0+(Bit32s)src.sw.w0);
00493                 dest->sw.w1 = SaturateDwordSToWordS((Bit32s)dest->sw.w1+(Bit32s)src.sw.w1);
00494                 dest->sw.w2 = SaturateDwordSToWordS((Bit32s)dest->sw.w2+(Bit32s)src.sw.w2);
00495                 dest->sw.w3 = SaturateDwordSToWordS((Bit32s)dest->sw.w3+(Bit32s)src.sw.w3);
00496                 break;
00497         }
00498         CASE_0F_D(0xDC)                                                                                         /* PADDUSB Pq,Qq */
00499         {
00500                 GetRM;
00501                 MMX_reg* dest=lookupRMregMM[rm];
00502                 MMX_reg src;
00503                 if (rm>=0xc0) {
00504                         src.q = reg_mmx[rm&7].q;
00505                 } else {
00506                         GetEAa;
00507                         src.q = LoadMq(eaa);
00508                 }
00509                 dest->ub.b0 = SaturateWordSToByteU((Bit16s)dest->ub.b0+(Bit16s)src.ub.b0);
00510                 dest->ub.b1 = SaturateWordSToByteU((Bit16s)dest->ub.b1+(Bit16s)src.ub.b1);
00511                 dest->ub.b2 = SaturateWordSToByteU((Bit16s)dest->ub.b2+(Bit16s)src.ub.b2);
00512                 dest->ub.b3 = SaturateWordSToByteU((Bit16s)dest->ub.b3+(Bit16s)src.ub.b3);
00513                 dest->ub.b4 = SaturateWordSToByteU((Bit16s)dest->ub.b4+(Bit16s)src.ub.b4);
00514                 dest->ub.b5 = SaturateWordSToByteU((Bit16s)dest->ub.b5+(Bit16s)src.ub.b5);
00515                 dest->ub.b6 = SaturateWordSToByteU((Bit16s)dest->ub.b6+(Bit16s)src.ub.b6);
00516                 dest->ub.b7 = SaturateWordSToByteU((Bit16s)dest->ub.b7+(Bit16s)src.ub.b7);
00517                 break;
00518         }
00519         CASE_0F_D(0xDD)                                                                                         /* PADDUSW Pq,Qq */
00520         {
00521                 GetRM;
00522                 MMX_reg* dest=lookupRMregMM[rm];
00523                 MMX_reg src;
00524                 if (rm>=0xc0) {
00525                         src.q = reg_mmx[rm&7].q;
00526                 } else {
00527                         GetEAa;
00528                         src.q = LoadMq(eaa);
00529                 }
00530                 dest->uw.w0 = SaturateDwordSToWordU((Bit32s)dest->uw.w0+(Bit32s)src.uw.w0);
00531                 dest->uw.w1 = SaturateDwordSToWordU((Bit32s)dest->uw.w1+(Bit32s)src.uw.w1);
00532                 dest->uw.w2 = SaturateDwordSToWordU((Bit32s)dest->uw.w2+(Bit32s)src.uw.w2);
00533                 dest->uw.w3 = SaturateDwordSToWordU((Bit32s)dest->uw.w3+(Bit32s)src.uw.w3);
00534                 break;
00535         }
00536         CASE_0F_D(0xF8)                                                                                         /* PSUBB Pq,Qq */
00537         {
00538                 GetRM;
00539                 MMX_reg* dest=lookupRMregMM[rm];
00540                 MMX_reg src;
00541                 if (rm>=0xc0) {
00542                         src.q=reg_mmx[rm&7].q;
00543                 } else {
00544                         GetEAa;
00545                         src.q = LoadMq(eaa);
00546                 }
00547                 dest->ub.b0 -= src.ub.b0;
00548                 dest->ub.b1 -= src.ub.b1;
00549                 dest->ub.b2 -= src.ub.b2;
00550                 dest->ub.b3 -= src.ub.b3;
00551                 dest->ub.b4 -= src.ub.b4;
00552                 dest->ub.b5 -= src.ub.b5;
00553                 dest->ub.b6 -= src.ub.b6;
00554                 dest->ub.b7 -= src.ub.b7;
00555                 break;
00556         }
00557         CASE_0F_D(0xF9)                                                                                         /* PSUBW Pq,Qq */
00558         {
00559                 GetRM;
00560                 MMX_reg* dest=lookupRMregMM[rm];
00561                 MMX_reg src;
00562                 if (rm>=0xc0) {
00563                         src.q=reg_mmx[rm&7].q;
00564                 } else {
00565                         GetEAa;
00566                         src.q = LoadMq(eaa);
00567                 }
00568                 dest->uw.w0 -= src.uw.w0;
00569                 dest->uw.w1 -= src.uw.w1;
00570                 dest->uw.w2 -= src.uw.w2;
00571                 dest->uw.w3 -= src.uw.w3;
00572                 break;
00573         }
00574         CASE_0F_D(0xFA)                                                                                         /* PSUBD Pq,Qq */
00575         {
00576                 GetRM;
00577                 MMX_reg* dest=lookupRMregMM[rm];
00578                 MMX_reg src;
00579                 if (rm>=0xc0) {
00580                         src.q=reg_mmx[rm&7].q;
00581                 } else {
00582                         GetEAa;
00583                         src.q = LoadMq(eaa);
00584                 }
00585                 dest->ud.d0 -= src.ud.d0;
00586                 dest->ud.d1 -= src.ud.d1;
00587                 break;
00588         }
00589         CASE_0F_D(0xE8)                                                                                         /* PSUBSB Pq,Qq */
00590         {
00591                 GetRM;
00592                 MMX_reg* dest=lookupRMregMM[rm];
00593                 MMX_reg src;
00594                 if (rm>=0xc0) {
00595                         src.q = reg_mmx[rm&7].q;
00596                 } else {
00597                         GetEAa;
00598                         src.q = LoadMq(eaa);
00599                 }
00600                 dest->sb.b0 = SaturateWordSToByteS((Bit16s)dest->sb.b0-(Bit16s)src.sb.b0);
00601                 dest->sb.b1 = SaturateWordSToByteS((Bit16s)dest->sb.b1-(Bit16s)src.sb.b1);
00602                 dest->sb.b2 = SaturateWordSToByteS((Bit16s)dest->sb.b2-(Bit16s)src.sb.b2);
00603                 dest->sb.b3 = SaturateWordSToByteS((Bit16s)dest->sb.b3-(Bit16s)src.sb.b3);
00604                 dest->sb.b4 = SaturateWordSToByteS((Bit16s)dest->sb.b4-(Bit16s)src.sb.b4);
00605                 dest->sb.b5 = SaturateWordSToByteS((Bit16s)dest->sb.b5-(Bit16s)src.sb.b5);
00606                 dest->sb.b6 = SaturateWordSToByteS((Bit16s)dest->sb.b6-(Bit16s)src.sb.b6);
00607                 dest->sb.b7 = SaturateWordSToByteS((Bit16s)dest->sb.b7-(Bit16s)src.sb.b7);
00608                 break;
00609         }
00610         CASE_0F_D(0xE9)                                                                                         /* PSUBSW Pq,Qq */
00611         {
00612                 GetRM;
00613                 MMX_reg* dest=lookupRMregMM[rm];
00614                 MMX_reg src;
00615                 if (rm>=0xc0) {
00616                         src.q = reg_mmx[rm&7].q;
00617                 } else {
00618                         GetEAa;
00619                         src.q = LoadMq(eaa);
00620                 }
00621                 dest->sw.w0 = SaturateDwordSToWordS((Bit32s)dest->sw.w0-(Bit32s)src.sw.w0);
00622                 dest->sw.w1 = SaturateDwordSToWordS((Bit32s)dest->sw.w1-(Bit32s)src.sw.w1);
00623                 dest->sw.w2 = SaturateDwordSToWordS((Bit32s)dest->sw.w2-(Bit32s)src.sw.w2);
00624                 dest->sw.w3 = SaturateDwordSToWordS((Bit32s)dest->sw.w3-(Bit32s)src.sw.w3);
00625                 break;
00626         }
00627         CASE_0F_D(0xD8)                                                                                         /* PSUBUSB Pq,Qq */
00628         {
00629                 GetRM;
00630                 MMX_reg* dest=lookupRMregMM[rm];
00631                 MMX_reg src;
00632                 MMX_reg result;
00633                 if (rm>=0xc0) {
00634                         src.q = reg_mmx[rm&7].q;
00635                 } else {
00636                         GetEAa;
00637                         src.q = LoadMq(eaa);
00638                 }
00639                 result.q = 0;
00640                 if (dest->ub.b0>src.ub.b0) result.ub.b0 = dest->ub.b0 - src.ub.b0;
00641                 if (dest->ub.b1>src.ub.b1) result.ub.b1 = dest->ub.b1 - src.ub.b1;
00642                 if (dest->ub.b2>src.ub.b2) result.ub.b2 = dest->ub.b2 - src.ub.b2;
00643                 if (dest->ub.b3>src.ub.b3) result.ub.b3 = dest->ub.b3 - src.ub.b3;
00644                 if (dest->ub.b4>src.ub.b4) result.ub.b4 = dest->ub.b4 - src.ub.b4;
00645                 if (dest->ub.b5>src.ub.b5) result.ub.b5 = dest->ub.b5 - src.ub.b5;
00646                 if (dest->ub.b6>src.ub.b6) result.ub.b6 = dest->ub.b6 - src.ub.b6;
00647                 if (dest->ub.b7>src.ub.b7) result.ub.b7 = dest->ub.b7 - src.ub.b7;
00648                 dest->q = result.q;
00649                 break;
00650         }
00651 
00652         CASE_0F_D(0xD9)                                                                                         /* PSUBUSW Pq,Qq */
00653         {
00654                 GetRM;
00655                 MMX_reg* dest=lookupRMregMM[rm];
00656                 MMX_reg src;
00657                 MMX_reg result;
00658                 if (rm>=0xc0) {
00659                         src.q = reg_mmx[rm&7].q;
00660                 } else {
00661                         GetEAa;
00662                         src.q = LoadMq(eaa);
00663                 }
00664                 result.q = 0;
00665                 if (dest->uw.w0>src.uw.w0) result.uw.w0 = dest->uw.w0 - src.uw.w0;
00666                 if (dest->uw.w1>src.uw.w1) result.uw.w1 = dest->uw.w1 - src.uw.w1;
00667                 if (dest->uw.w2>src.uw.w2) result.uw.w2 = dest->uw.w2 - src.uw.w2;
00668                 if (dest->uw.w3>src.uw.w3) result.uw.w3 = dest->uw.w3 - src.uw.w3;
00669                 dest->q = result.q;
00670                 break;
00671         }
00672         CASE_0F_D(0xE5)                                                                                         /* PMULHW Pq,Qq */
00673         {
00674                 GetRM;
00675                 MMX_reg* dest=lookupRMregMM[rm];
00676                 MMX_reg src;
00677                 if (rm>=0xc0) {
00678                         src.q = reg_mmx[rm&7].q;
00679                 } else {
00680                         GetEAa;
00681                         src.q = LoadMq(eaa);
00682                 }
00683                 Bit32s product0 = (Bit32s)dest->sw.w0 * (Bit32s)src.sw.w0;
00684                 Bit32s product1 = (Bit32s)dest->sw.w1 * (Bit32s)src.sw.w1;
00685                 Bit32s product2 = (Bit32s)dest->sw.w2 * (Bit32s)src.sw.w2;
00686                 Bit32s product3 = (Bit32s)dest->sw.w3 * (Bit32s)src.sw.w3;
00687                 dest->uw.w0 = (Bit16u)(product0 >> 16);
00688                 dest->uw.w1 = (Bit16u)(product1 >> 16);
00689                 dest->uw.w2 = (Bit16u)(product2 >> 16);
00690                 dest->uw.w3 = (Bit16u)(product3 >> 16);
00691                 break;
00692         }
00693         CASE_0F_D(0xD5)                                                                                         /* PMULLW Pq,Qq */
00694         {
00695                 GetRM;
00696                 MMX_reg* dest=lookupRMregMM[rm];
00697                 MMX_reg src;
00698                 if (rm>=0xc0) {
00699                         src.q = reg_mmx[rm&7].q;
00700                 } else {
00701                         GetEAa;
00702                         src.q = LoadMq(eaa);
00703                 }
00704                 Bit32u product0 = (Bit32u)dest->uw.w0 * (Bit32u)src.uw.w0;
00705                 Bit32u product1 = (Bit32u)dest->uw.w1 * (Bit32u)src.uw.w1;
00706                 Bit32u product2 = (Bit32u)dest->uw.w2 * (Bit32u)src.uw.w2;
00707                 Bit32u product3 = (Bit32u)dest->uw.w3 * (Bit32u)src.uw.w3;
00708                 dest->uw.w0 = (product0 & 0xffff);
00709                 dest->uw.w1 = (product1 & 0xffff);
00710                 dest->uw.w2 = (product2 & 0xffff);
00711                 dest->uw.w3 = (product3 & 0xffff);
00712                 break;
00713         }
00714         CASE_0F_D(0xF5)                                                                                         /* PMADDWD Pq,Qq */
00715         {
00716                 GetRM;
00717                 MMX_reg* dest=lookupRMregMM[rm];
00718                 MMX_reg src;
00719                 if (rm>=0xc0) {
00720                         src.q = reg_mmx[rm&7].q;
00721                 } else {
00722                         GetEAa;
00723                         src.q = LoadMq(eaa);
00724                 }
00725                 if (dest->ud.d0 == 0x80008000 && src.ud.d0 == 0x80008000)
00726                         dest->ud.d0 = 0x80000000;
00727                 else {
00728                         Bit32s product0 = (Bit32s)dest->sw.w0 * (Bit32s)src.sw.w0;
00729                         Bit32s product1 = (Bit32s)dest->sw.w1 * (Bit32s)src.sw.w1;
00730                         dest->ud.d0 = (uint32_t)(product0 + product1);
00731                 }
00732                 if (dest->ud.d1 == 0x80008000 && src.ud.d1 == 0x80008000)
00733                         dest->ud.d1 = 0x80000000;
00734                 else {
00735                         Bit32s product2 = (Bit32s)dest->sw.w2 * (Bit32s)src.sw.w2;
00736                         Bit32s product3 = (Bit32s)dest->sw.w3 * (Bit32s)src.sw.w3;
00737                         dest->sd.d1 = (int32_t)(product2 + product3);
00738                 }
00739                 break;
00740         }
00741 
00742 /* Comparison */
00743         CASE_0F_D(0x74)                                                                                         /* PCMPEQB Pq,Qq */
00744         {
00745                 GetRM;
00746                 MMX_reg* dest=lookupRMregMM[rm];
00747                 MMX_reg src;
00748                 if (rm>=0xc0) {
00749                         src.q=reg_mmx[rm&7].q;
00750                 } else {
00751                         GetEAa;
00752                         src.q = LoadMq(eaa);
00753                 }
00754                 dest->ub.b0 = dest->ub.b0==src.ub.b0?0xff:0;
00755                 dest->ub.b1 = dest->ub.b1==src.ub.b1?0xff:0;
00756                 dest->ub.b2 = dest->ub.b2==src.ub.b2?0xff:0;
00757                 dest->ub.b3 = dest->ub.b3==src.ub.b3?0xff:0;
00758                 dest->ub.b4 = dest->ub.b4==src.ub.b4?0xff:0;
00759                 dest->ub.b5 = dest->ub.b5==src.ub.b5?0xff:0;
00760                 dest->ub.b6 = dest->ub.b6==src.ub.b6?0xff:0;
00761                 dest->ub.b7 = dest->ub.b7==src.ub.b7?0xff:0;
00762                 break;
00763         }
00764         CASE_0F_D(0x75)                                                                                         /* PCMPEQW Pq,Qq */
00765         {
00766                 GetRM;
00767                 MMX_reg* dest=lookupRMregMM[rm];
00768                 MMX_reg src;
00769                 if (rm>=0xc0) {
00770                         src.q=reg_mmx[rm&7].q;
00771                 } else {
00772                         GetEAa;
00773                         src.q = LoadMq(eaa);
00774                 }
00775                 dest->uw.w0 = dest->uw.w0==src.uw.w0?0xffff:0;
00776                 dest->uw.w1 = dest->uw.w1==src.uw.w1?0xffff:0;
00777                 dest->uw.w2 = dest->uw.w2==src.uw.w2?0xffff:0;
00778                 dest->uw.w3 = dest->uw.w3==src.uw.w3?0xffff:0;
00779                 break;
00780         }
00781         CASE_0F_D(0x76)                                                                                         /* PCMPEQD Pq,Qq */
00782         {
00783                 GetRM;
00784                 MMX_reg* dest=lookupRMregMM[rm];
00785                 MMX_reg src;
00786                 if (rm>=0xc0) {
00787                         src.q=reg_mmx[rm&7].q;
00788                 } else {
00789                         GetEAa;
00790                         src.q = LoadMq(eaa);
00791                 }
00792                 dest->ud.d0 = dest->ud.d0==src.ud.d0?0xffffffff:0;
00793                 dest->ud.d1 = dest->ud.d1==src.ud.d1?0xffffffff:0;
00794                 break;
00795         }
00796         CASE_0F_D(0x64)                                                                                         /* PCMPGTB Pq,Qq */
00797         {
00798                 GetRM;
00799                 MMX_reg* dest=lookupRMregMM[rm];
00800                 MMX_reg src;
00801                 if (rm>=0xc0) {
00802                         src.q=reg_mmx[rm&7].q;
00803                 } else {
00804                         GetEAa;
00805                         src.q = LoadMq(eaa);
00806                 }
00807                 dest->ub.b0 = dest->sb.b0>src.sb.b0?0xff:0;
00808                 dest->ub.b1 = dest->sb.b1>src.sb.b1?0xff:0;
00809                 dest->ub.b2 = dest->sb.b2>src.sb.b2?0xff:0;
00810                 dest->ub.b3 = dest->sb.b3>src.sb.b3?0xff:0;
00811                 dest->ub.b4 = dest->sb.b4>src.sb.b4?0xff:0;
00812                 dest->ub.b5 = dest->sb.b5>src.sb.b5?0xff:0;
00813                 dest->ub.b6 = dest->sb.b6>src.sb.b6?0xff:0;
00814                 dest->ub.b7 = dest->sb.b7>src.sb.b7?0xff:0;
00815                 break;
00816         }
00817         CASE_0F_D(0x65)                                                                                         /* PCMPGTW Pq,Qq */
00818         {
00819                 GetRM;
00820                 MMX_reg* dest=lookupRMregMM[rm];
00821                 MMX_reg src;
00822                 if (rm>=0xc0) {
00823                         src.q=reg_mmx[rm&7].q;
00824                 } else {
00825                         GetEAa;
00826                         src.q = LoadMq(eaa);
00827                 }
00828                 dest->uw.w0 = dest->sw.w0>src.sw.w0?0xffff:0;
00829                 dest->uw.w1 = dest->sw.w1>src.sw.w1?0xffff:0;
00830                 dest->uw.w2 = dest->sw.w2>src.sw.w2?0xffff:0;
00831                 dest->uw.w3 = dest->sw.w3>src.sw.w3?0xffff:0;
00832                 break;
00833         }
00834         CASE_0F_D(0x66)                                                                                         /* PCMPGTD Pq,Qq */
00835         {
00836                 GetRM;
00837                 MMX_reg* dest=lookupRMregMM[rm];
00838                 MMX_reg src;
00839                 if (rm>=0xc0) {
00840                         src.q=reg_mmx[rm&7].q;
00841                 } else {
00842                         GetEAa;
00843                         src.q = LoadMq(eaa);
00844                 }
00845                 dest->ud.d0 = dest->sd.d0>src.sd.d0?0xffffffff:0;
00846                 dest->ud.d1 = dest->sd.d1>src.sd.d1?0xffffffff:0;
00847                 break;
00848         }
00849 
00850 /* Data Packing */
00851         CASE_0F_D(0x63)                                                                                         /* PACKSSWB Pq,Qq */
00852         {
00853                 GetRM;
00854                 MMX_reg* dest=lookupRMregMM[rm];
00855                 MMX_reg src;
00856                 if (rm>=0xc0) {
00857                         src.q=reg_mmx[rm&7].q;
00858                 } else {
00859                         GetEAa;
00860                         src.q = LoadMq(eaa);
00861                 }
00862                 dest->sb.b0 = SaturateWordSToByteS(dest->sw.w0);
00863                 dest->sb.b1 = SaturateWordSToByteS(dest->sw.w1);
00864                 dest->sb.b2 = SaturateWordSToByteS(dest->sw.w2);
00865                 dest->sb.b3 = SaturateWordSToByteS(dest->sw.w3);
00866                 dest->sb.b4 = SaturateWordSToByteS(src.sw.w0);
00867                 dest->sb.b5 = SaturateWordSToByteS(src.sw.w1);
00868                 dest->sb.b6 = SaturateWordSToByteS(src.sw.w2);
00869                 dest->sb.b7 = SaturateWordSToByteS(src.sw.w3);
00870                 break;
00871         }
00872         CASE_0F_D(0x6B)                                                                                         /* PACKSSDW Pq,Qq */
00873         {
00874                 GetRM;
00875                 MMX_reg* dest=lookupRMregMM[rm];
00876                 MMX_reg src;
00877                 if (rm>=0xc0) {
00878                         src.q=reg_mmx[rm&7].q;
00879                 } else {
00880                         GetEAa;
00881                         src.q = LoadMq(eaa);
00882                 }
00883                 dest->sw.w0 = SaturateDwordSToWordS(dest->sd.d0);
00884                 dest->sw.w1 = SaturateDwordSToWordS(dest->sd.d1);
00885                 dest->sw.w2 = SaturateDwordSToWordS(src.sd.d0);
00886                 dest->sw.w3 = SaturateDwordSToWordS(src.sd.d1);
00887                 break;
00888         }
00889         CASE_0F_D(0x67)                                                                                         /* PACKUSWB Pq,Qq */
00890         {
00891                 GetRM;
00892                 MMX_reg* dest=lookupRMregMM[rm];
00893                 MMX_reg src;
00894                 if (rm>=0xc0) {
00895                         src.q=reg_mmx[rm&7].q;
00896                 } else {
00897                         GetEAa;
00898                         src.q = LoadMq(eaa);
00899                 }
00900                 dest->ub.b0 = SaturateWordSToByteU(dest->sw.w0);
00901                 dest->ub.b1 = SaturateWordSToByteU(dest->sw.w1);
00902                 dest->ub.b2 = SaturateWordSToByteU(dest->sw.w2);
00903                 dest->ub.b3 = SaturateWordSToByteU(dest->sw.w3);
00904                 dest->ub.b4 = SaturateWordSToByteU(src.sw.w0);
00905                 dest->ub.b5 = SaturateWordSToByteU(src.sw.w1);
00906                 dest->ub.b6 = SaturateWordSToByteU(src.sw.w2);
00907                 dest->ub.b7 = SaturateWordSToByteU(src.sw.w3);
00908                 break;
00909         }
00910         CASE_0F_D(0x68)                                                                                         /* PUNPCKHBW Pq,Qq */
00911         {
00912                 GetRM;
00913                 MMX_reg* dest=lookupRMregMM[rm];
00914                 MMX_reg src;
00915                 if (rm>=0xc0) {
00916                         src.q=reg_mmx[rm&7].q;
00917                 } else {
00918                         GetEAa;
00919                         src.q = LoadMq(eaa);
00920                 }
00921                 dest->ub.b0 = dest->ub.b4;
00922                 dest->ub.b1 = src.ub.b4;
00923                 dest->ub.b2 = dest->ub.b5;
00924                 dest->ub.b3 = src.ub.b5;
00925                 dest->ub.b4 = dest->ub.b6;
00926                 dest->ub.b5 = src.ub.b6;
00927                 dest->ub.b6 = dest->ub.b7;
00928                 dest->ub.b7 = src.ub.b7;
00929                 break;
00930         }
00931         CASE_0F_D(0x69)                                                                                         /* PUNPCKHWD Pq,Qq */
00932         {
00933                 GetRM;
00934                 MMX_reg* dest=lookupRMregMM[rm];
00935                 MMX_reg src;
00936                 if (rm>=0xc0) {
00937                         src.q=reg_mmx[rm&7].q;
00938                 } else {
00939                         GetEAa;
00940                         src.q = LoadMq(eaa);
00941                 }
00942                 dest->uw.w0 = dest->uw.w2;
00943                 dest->uw.w1 = src.uw.w2;
00944                 dest->uw.w2 = dest->uw.w3;
00945                 dest->uw.w3 = src.uw.w3;
00946                 break;
00947         }
00948         CASE_0F_D(0x6A)                                                                                         /* PUNPCKHDQ Pq,Qq */
00949         {
00950                 GetRM;
00951                 MMX_reg* dest=lookupRMregMM[rm];
00952                 MMX_reg src;
00953                 if (rm>=0xc0) {
00954                         src.q=reg_mmx[rm&7].q;
00955                 } else {
00956                         GetEAa;
00957                         src.q = LoadMq(eaa);
00958                 }
00959                 dest->ud.d0 = dest->ud.d1;
00960                 dest->ud.d1 = src.ud.d1;
00961                 break;
00962         }
00963         CASE_0F_D(0x60)                                                                                         /* PUNPCKLBW Pq,Qq */
00964         {
00965                 GetRM;
00966                 MMX_reg* dest=lookupRMregMM[rm];
00967                 MMX_reg src;
00968                 if (rm>=0xc0) {
00969                         src.q=reg_mmx[rm&7].q;
00970                 } else {
00971                         GetEAa;
00972                         src.q = LoadMq(eaa);
00973                 }
00974                 dest->ub.b7 = src.ub.b3;
00975                 dest->ub.b6 = dest->ub.b3;
00976                 dest->ub.b5 = src.ub.b2;
00977                 dest->ub.b4 = dest->ub.b2;
00978                 dest->ub.b3 = src.ub.b1;
00979                 dest->ub.b2 = dest->ub.b1;
00980                 dest->ub.b1 = src.ub.b0;
00981                 dest->ub.b0 = dest->ub.b0;
00982                 break;
00983         }
00984         CASE_0F_D(0x61)                                                                                         /* PUNPCKLWD Pq,Qq */
00985         {
00986                 GetRM;
00987                 MMX_reg* dest=lookupRMregMM[rm];
00988                 MMX_reg src;
00989                 if (rm>=0xc0) {
00990                         src.q=reg_mmx[rm&7].q;
00991                 } else {
00992                         GetEAa;
00993                         src.q = LoadMq(eaa);
00994                 }
00995                 dest->uw.w3 = src.uw.w1;
00996                 dest->uw.w2 = dest->uw.w1;
00997                 dest->uw.w1 = src.uw.w0;
00998                 dest->uw.w0 = dest->uw.w0;
00999                 break;
01000         }
01001         CASE_0F_D(0x62)                                                                                         /* PUNPCKLDQ Pq,Qq */
01002         {
01003                 GetRM;
01004                 MMX_reg* dest=lookupRMregMM[rm];
01005                 MMX_reg src;
01006                 if (rm>=0xc0) {
01007                         src.q=reg_mmx[rm&7].q;
01008                 } else {
01009                         GetEAa;
01010                         src.q = LoadMq(eaa);
01011                 }
01012                 dest->ud.d1 = src.ud.d0;
01013                 break;
01014         }