diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/emu/x64runavx660f.c | 175 |
1 files changed, 173 insertions, 2 deletions
diff --git a/src/emu/x64runavx660f.c b/src/emu/x64runavx660f.c index f9f7acf4..662119b7 100644 --- a/src/emu/x64runavx660f.c +++ b/src/emu/x64runavx660f.c @@ -58,17 +58,57 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) switch(opcode) { + case 0x64: /* VPCMPGTB Gx,Ex */ + nextop = F8; + GETEX(0); + GETGX; + GETGY; + for(int i=0; i<16; ++i) + GX->ub[i] = (GX->sb[i]>EX->sb[i])?0xFF:0x00; + if(vex.l) + for(int i=0; i<16; ++i) + GY->ub[i] = (GY->sb[i]>EY->sb[i])?0xFF:0x00; + else + GY->q[0] = GY->q[1] = 0; + break; + case 0x65: /* VPCMPGTW Gx,Ex */ + nextop = F8; + GETEX(0); + GETGX; + GETGY; + for(int i=0; i<8; ++i) + GX->uw[i] = (GX->sw[i]>EX->sw[i])?0xFFFF:0x0000; + if(vex.l) + for(int i=0; i<8; ++i) + GY->uw[i] = (GY->sw[i]>EY->sw[i])?0xFFFF:0x0000; + else + GY->q[0] = GY->q[1] = 0; + break; + case 0x66: /* VPCMPGTD Gx,Ex */ + nextop = F8; + GETEX(0); + GETGX; + GETGY; + for(int i=0; i<4; ++i) + GX->ud[i] = (GX->sd[i]>EX->sd[i])?0xFFFFFFFF:0x00000000; + if(vex.l) + for(int i=0; i<4; ++i) + GY->ud[i] = (GY->sd[i]>EY->sd[i])?0xFFFFFFFF:0x00000000; + else + GY->q[0] = GY->q[1] = 0; + break; + case 0x70: /* PSHUFD Gx,Ex,Ib */ nextop = F8; GETEX(1); GETGX; - tmp8u = F8; GETGY; + tmp8u = F8; if(vex.l) { GETEY; if(EY==GY) {eay1 = *GY; EY = &eay1;} // copy is needed for (int i=0; i<4; ++i) - GY->ud[4+i] = EY->ud[4+(tmp8u>>(i*2))&3]; + GY->ud[4+i] = EY->ud[4+((tmp8u>>(i*2))&3)]; } else memset(GY, 0, 16); if(EX==GX) {eax1 = *GX; EX = &eax1;} // copy is needed @@ -76,6 +116,137 @@ uintptr_t RunAVX_660F(x64emu_t *emu, vex_t vex, uintptr_t addr, int *step) GX->ud[i] = EX->ud[(tmp8u>>(i*2))&3]; break; + case 0x72: /* GRP */ + nextop = F8; + GETEX(1); + GETEY; + if(!vex.l && MODREG) + memset(EY, 0, 16); + switch((nextop>>3)&7) { + case 2: /* PSRLD Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>31) + {EX->q[0] = EX->q[1] = 0;} + else + for (int i=0; i<4; ++i) EX->ud[i] >>= tmp8u; + } + break; + case 4: /* PSRAD Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>31) tmp8u=31; + for (int i=0; i<4; ++i) EX->sd[i] >>= tmp8u; + } + break; + case 6: /* PSLLD Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>31) + {EX->q[0] = EX->q[1] = 0;} + else + for (int i=0; i<4; ++i) EX->ud[i] <<= tmp8u; + } + break; + default: + return 0; + } + break; + case 0x73: /* GRP */ + nextop = F8; + GETEX(1); + GETEY; + if(!vex.l && MODREG) + memset(EY, 0, 16); + switch((nextop>>3)&7) { + case 2: /* PSRLQ Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>63) + {EX->q[0] = EX->q[1] = 0;} + else + {EX->q[0] >>= tmp8u; EX->q[1] >>= tmp8u;} + } + break; + case 3: /* PSRLDQ Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>15) + {EX->q[0] = EX->q[1] = 0;} + else if (tmp8u!=0) { + tmp8u*=8; + if (tmp8u < 64) { + EX->q[0] = (EX->q[0] >> tmp8u) | (EX->q[1] << (64 - tmp8u)); + EX->q[1] = (EX->q[1] >> tmp8u); + } else { + EX->q[0] = EX->q[1] >> (tmp8u - 64); + EX->q[1] = 0; + } + } + } + break; + case 6: /* PSLLQ Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>63) + {EX->q[0] = EX->q[1] = 0;} + else + {EX->q[0] <<= tmp8u; EX->q[1] <<= tmp8u;} + } + break; + case 7: /* PSLLDQ Ex, Ib */ + tmp8u = F8; + if(vex.l) { + emit_signal(emu, SIGILL, (void*)R_RIP, 0); + } else { + if(tmp8u>15) + {EX->q[0] = EX->q[1] = 0;} + else if (tmp8u!=0) { + tmp8u*=8; + if (tmp8u < 64) { + EX->q[1] = (EX->q[1] << tmp8u) | (EX->q[0] >> (64 - tmp8u)); + EX->q[0] = (EX->q[0] << tmp8u); + } else { + EX->q[1] = EX->q[0] << (tmp8u - 64); + EX->q[0] = 0; + } + } + } + break; + default: + return 0; + } + break; + + case 0xEF: /* VPXOR Gx,Ex */ + nextop = F8; + GETEX(0); + GETGX; + GX->q[0] ^= EX->q[0]; + GX->q[1] ^= EX->q[1]; + GETGY; + if(vex.l) { + GETEY; + GY->q[0] ^= EY->q[0]; + GY->q[1] ^= EY->q[1]; + } else { + GY->q[0] = GY->q[1] = 0; + } + + break; + default: return 0; } |