Added AES-NI and PCLMULQDQ support

This commit is contained in:
ptitSeb 2023-10-29 12:25:02 +01:00
parent 7a175a9733
commit c6275bcb62
16 changed files with 1844 additions and 3 deletions

View File

@ -898,6 +898,11 @@ add_test(NAME multiple_dlopen COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_B
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref21.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
add_test(NAME aes COMMAND ${CMAKE_COMMAND} -D TEST_PROGRAM=${CMAKE_BINARY_DIR}/${BOX86}
-D TEST_ARGS=${CMAKE_SOURCE_DIR}/tests/test22 -D TEST_OUTPUT=tmpfile22.txt
-D TEST_REFERENCE=${CMAKE_SOURCE_DIR}/tests/ref22.txt
-P ${CMAKE_SOURCE_DIR}/runTest.cmake )
file(GLOB extension_tests "${CMAKE_SOURCE_DIR}/tests/extensions/*.c")
foreach(file ${extension_tests})
get_filename_component(testname "${file}" NAME_WE)

View File

@ -1100,6 +1100,7 @@ Op is 20-27
#define VMULL_U32_U16(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 1, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_S64_S32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_U64_U32(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(1, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 0, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMULL_P64(Dd, Dn, Dm) EMIT(VMULL_NEON_gen(0, ((Dd)>>4)&1, 2, (Dn)&15, (Dd)&15, 1, ((Dn)>>4)&1, ((Dm)>>4)&1, (Dm)&15))
#define VMUL_NEON_gen(op, D, size, Vn, Vd, N, Q, M, Vm) (0b1111<<28 | 0b001<<25 | (op)<<24 | 0<<23 | (D)<<22 | (size)<<20 | (Vn)<<16 | (Vd)<<12 | 0b1001<<8 | (N)<<7 | (Q)<<6 | (M)<<5 | 1<<4 | (Vm))
#define VMULQ_32(Dd, Dn, Dm) EMIT(VMUL_NEON_gen(0, ((Dd)>>4)&1, 0b10, (Dn)&15, (Dd)&15, ((Dn)>>4)&1, 1, ((Dm)>>4)&1, (Dm)&15))
@ -1397,4 +1398,17 @@ Op is 20-27
#define VABSQ_S8(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 0, (Dd)&15, 0, 1, ((Dm)>>4)&1, (Dm)&15))
#define VABSQ_F(Dd, Dm) EMIT(VABS_vgen(((Dd)>>4)&1, 2, (Dd)&15, 1, 1, ((Dm)>>4)&1, (Dm)&15))
// AES
#define AESD_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESD(Dd, Dm) EMIT(AESD_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESE_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0110<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESE(Dd, Dm) EMIT(AESE_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESIMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 1<<6 | (M)<<5 | (Vm))
#define AESIMC(Dd, Dm) EMIT(AESIMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#define AESMC_gen(D, size, Vd, M, Vm) (0b1111<<28 | 0b0011<<24 | 1<<23 | (D)<<22 | 0b11<<20 | (size)<<18 | (Vd)<<12 | 0b0111<<7 | 0<<6 | (M)<<5 | (Vm))
#define AESMC(Dd, Dm) EMIT(AESMC_gen(((Dd)>>4)&1, 0, (Dd)&15, ((Dm)>>4)&1, (Dm)&15))
#endif //__ARM_EMITTER_H__

View File

@ -131,6 +131,7 @@ arm_lock_storeifref_loop:
beq arm_lock_storeifref_loop
mov r0, r1
arm_lock_storeifref_exit:
dmb ish
bx lr
arm_lock_decifnot0b:
@ -174,13 +175,11 @@ arm_lock_incif0b_0:
bx lr
arm_lock_stored:
dmb ish
str r1, [r0]
dmb ish
bx lr
arm_lock_storeb:
dmb ish
strb r1, [r0]
dmb ish
bx lr

View File

@ -35,6 +35,11 @@
#define GETGX(a, w) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg(dyn, ninst, x1, gd, w)
#define GETGX_empty(a) \
gd = (nextop&0x38)>>3; \
a = sse_get_reg_empty(dyn, ninst, x1, gd)
#define GETG gd = (nextop&0x38)>>3
uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int ninst, int* ok, int* need_epilog)
{
@ -460,6 +465,108 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
q0 = sse_get_reg_empty(dyn, ninst, x1, gd);
VABSQ_S32(q0, q1);
break;
case 0xDB:
INST_NAME("AESIMC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX_empty(q0);
AESIMC(q0, q1);
} else {
GETEX(q1, 0);
GETGX_empty(q0);
if(q0!=q1) {
VMOVQ(q0, q1);
}
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesimc, -1, 0);
}
break;
case 0xDC:
INST_NAME("AESENC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
AESMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aese, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDD:
INST_NAME("AESENCLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESE(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aeselast, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDE:
INST_NAME("AESDEC Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
AESIMC(v0, v0);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesd, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
case 0xDF:
INST_NAME("AESDECLAST Gx, Ex"); // AES-NI
nextop = F8;
if(arm_aes) {
GETEX(q1, 0);
GETGX(q0, 1);
v0 = fpu_get_scratch_quad(dyn); // ARM64 internal operation differs a bit from x86_64
VEORQ(v0, q0, q1);
AESD(v0, q1);
VEORQ(q0, v0, q1);
} else {
GETG;
sse_forget_reg(dyn, ninst, gd, x1);
MOV32(x1, gd);
CALL(arm_aesdlast, -1, 0);
GETGX(q0, 1);
GETEX(q1, 0);
VEORQ(q0, q0, q1);
}
break;
default:
DEFAULT;
}
@ -484,6 +591,29 @@ uintptr_t dynarec660F(dynarec_arm_t* dyn, uintptr_t addr, uintptr_t ip, int nins
VEXTQ_8(q0, q1, q0, u8);
}
break;
case 0x44:
INST_NAME("PCLMULQDQ Gx, Ex, Ib");
nextop = F8;
GETGX(q0, 1);
GETEX(q1, 0);
u8 = F8;
switch (u8&0b00010001) {
case 0b00000000:
VMULL_P64(q0, q0, q1);
break;
case 0b00010001:
VMULL_P64(q0, q0+1, q1+1);
break;
case 0b00000001:
VMULL_P64(q0, q0+1, q1);
break;
case 0b00010000:
VMULL_P64(q0, q0, q1+1);
break;
}
break;
default:
DEFAULT;
}

View File

@ -246,6 +246,141 @@ void arm_fprem1(x86emu_t* emu)
}
}
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
void arm_aesimc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
}
void arm_aesmc(x86emu_t* emu, int xmm)
{
sse_regs_t eax1 = emu->xmm[xmm];
for(int j=0; j<4; ++j) {
emu->xmm[xmm].ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
emu->xmm[xmm].ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
emu->xmm[xmm].ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
}
void arm_aesdlast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = invsubbytes[eax1.ub[i]];
}
static const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
static const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
void arm_aeselast(x86emu_t* emu, int xmm)
{
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
sse_regs_t eax1;
for(int i=0; i<16; ++i)
eax1.ub[i] = emu->xmm[xmm].ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
emu->xmm[xmm].ub[i] = subbytes[eax1.ub[i]];
}
void arm_aesd(x86emu_t* emu, int xmm)
{
arm_aesdlast(emu, xmm);
arm_aesimc(emu, xmm);
}
void arm_aese(x86emu_t* emu, int xmm)
{
arm_aeselast(emu, xmm);
arm_aesmc(emu, xmm);
}
void arm_aeskeygenassist(x86emu_t* emu, int gx, int ex, void* p, uint32_t u8)
{
sse_regs_t *EX = p?((sse_regs_t*)p):&emu->xmm[ex];
sse_regs_t *GX = &emu->xmm[gx];
for (int i = 4; i < 8; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX->ub[i] = subbytes[EX->ub[i]];
GX->ud[0] = GX->ud[1];
uint8_t tmp8u = GX->ub[4];
GX->ud[1] = GX->ud[1] >> 8;
GX->ub[7] = tmp8u;
GX->ud[1] ^= u8;
GX->ud[2] = GX->ud[3];
tmp8u = GX->ub[12];
GX->ud[3] = GX->ud[3] >> 8;
GX->ub[15] = tmp8u;
GX->ud[3] ^= u8;
}
void arm_clflush(x86emu_t* emu, void* p)
{
cleanDBFromAddressRange((uintptr_t)p, 8, 0);

View File

@ -23,6 +23,13 @@ void arm_fsave(x86emu_t* emu, uint8_t* ed);
void arm_frstor(x86emu_t* emu, uint8_t* ed);
void arm_fprem1(x86emu_t* emu);
void arm_aesd(x86emu_t* emu, int xmm);
void arm_aese(x86emu_t* emu, int xmm);
void arm_aesdlast(x86emu_t* emu, int xmm);
void arm_aeselast(x86emu_t* emu, int xmm);
void arm_aesimc(x86emu_t* emu, int xmm);
void arm_aeskeygenassist(x86emu_t* emu, int gx, int ex, void* p, uint32_t u8);
void arm_clflush(x86emu_t* emu, void* p);
int64_t arm_fist64_0(double d);

View File

@ -1341,6 +1341,26 @@ int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a)
dyn->n.ssecache[a].write = 1; // it will be write...
return dyn->n.ssecache[a].reg;
}
// forget neon register for a SSE reg
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1)
{
if(dyn->n.ssecache[a].v==-1)
return;
if(dyn->n.neoncache[dyn->n.ssecache[a].reg].t == NEON_CACHE_XMMW) {
int offs = offsetof(x86emu_t, xmm[a]);
if(!(offs&3) && (offs>>2)<256) {
ADD_IMM8_ROR(s1, xEmu, offs>>2, 15);
} else {
MOV32(s1, offs);
ADD_REG_LSL_IMM5(s1, xEmu, s1, 0);
}
VST1Q_64(dyn->n.ssecache[a].reg, s1);
}
fpu_free_reg_quad(dyn, dyn->n.ssecache[a].reg);
dyn->n.ssecache[a].v = -1;
return;
}
// purge the SSE cache only(needs 1 scratch registers)
static void sse_purgecache(dynarec_arm_t* dyn, int ninst, int next, int s1)
{

View File

@ -545,6 +545,7 @@ void* arm_next(x86emu_t* emu, uintptr_t addr);
#define mmx_get_reg_empty STEPNAME(mmx_get_reg_empty)
#define sse_get_reg STEPNAME(sse_get_reg)
#define sse_get_reg_empty STEPNAME(sse_get_reg_empty)
#define sse_forget_reg STEPNAME(sse_forget_reg)
#define fpu_pushcache STEPNAME(fpu_pushcache)
#define fpu_popcache STEPNAME(fpu_popcache)
@ -740,6 +741,8 @@ int mmx_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int s2, int s3, int
int sse_get_reg(dynarec_arm_t* dyn, int ninst, int s1, int a, int forwrite);
// get neon register for a SSE reg, but don't try to synch it if it needed to be created
int sse_get_reg_empty(dynarec_arm_t* dyn, int ninst, int s1, int a);
// forget an SSE reg
void sse_forget_reg(dynarec_arm_t* dyn, int ninst, int a, int s1);
// common coproc helpers
// reset the cache

View File

@ -16,6 +16,27 @@
#include "modrm.h"
static uint8_t ff_mult(uint8_t a, uint8_t b)
{
int retval = 0;
for(int i = 0; i < 8; i++) {
if((b & 1) == 1)
retval ^= a;
if((a & 0x80)) {
a <<= 1;
a ^= 0x1b;
} else {
a <<= 1;
}
b >>= 1;
}
return retval;
}
#ifdef TEST_INTERPRETER
uintptr_t Test660F(x86test_t *test, uintptr_t addr)
#else
@ -36,6 +57,49 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
#ifndef NOALIGN
int is_nan;
#endif
// AES opcodes constants
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A F K P E J O D I N C H M B G L
const uint8_t shiftrows[] = {0, 5,10,15, 4, 9,14, 3, 8,13, 2, 7,12, 1, 6,11};
const uint8_t subbytes[256] = {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
};
// A0 B1 C2 D3 E4 F5 G6 H7 I8 J9 Ka Lb Mc Nd Oe Pf
// A N K H E B O L I F C P M J G D
const uint8_t invshiftrows[] = {0,13,10, 7, 4, 1,14,11, 8, 5, 2,15,12, 9, 6, 3};
const uint8_t invsubbytes[256] = {
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
};
#ifdef TEST_INTERPRETER
@ -540,6 +604,103 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
}
break;
case 0xDB: /* AESIMC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← InvMixColumns( STATE );
if (EX == &GX) {
for(int i=0; i<16; ++i)
eax1.ub[i] = EX->ub[i];
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
} else {
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, EX->ub[0+j*4]) ^ ff_mult(0x0B, EX->ub[1+j*4]) ^ ff_mult(0x0D, EX->ub[2+j*4]) ^ ff_mult(0x09, EX->ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, EX->ub[0+j*4]) ^ ff_mult(0x0E, EX->ub[1+j*4]) ^ ff_mult(0x0B, EX->ub[2+j*4]) ^ ff_mult(0x0D, EX->ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, EX->ub[0+j*4]) ^ ff_mult(0x09, EX->ub[1+j*4]) ^ ff_mult(0x0E, EX->ub[2+j*4]) ^ ff_mult(0x0B, EX->ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, EX->ub[0+j*4]) ^ ff_mult(0x0D, EX->ub[1+j*4]) ^ ff_mult(0x09, EX->ub[2+j*4]) ^ ff_mult(0x0E, EX->ub[3+j*4]);
}
}
break;
case 0xDC: /* AESENC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = subbytes[eax1.ub[i]];
//STATE ← MixColumns( STATE );
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x02, eax1.ub[0+j*4]) ^ ff_mult(0x03, eax1.ub[1+j*4]) ^ eax1.ub[2+j*4] ^ eax1.ub[3+j*4] ;
GX.ub[1+j*4] = eax1.ub[0+j*4] ^ ff_mult(0x02, eax1.ub[1+j*4]) ^ ff_mult(0x03, eax1.ub[2+j*4]) ^ eax1.ub[3+j*4] ;
GX.ub[2+j*4] = eax1.ub[0+j*4] ^ eax1.ub[1+j*4] ^ ff_mult(0x02, eax1.ub[2+j*4]) ^ ff_mult(0x03, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x03, eax1.ub[0+j*4]) ^ eax1.ub[1+j*4] ^ eax1.ub[2+j*4] ^ ff_mult(0x02, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDD: /* AESENCLAST Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← ShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[shiftrows[i]];
//STATE ← SubBytes( STATE );
for(int i=0; i<16; ++i)
GX.ub[i] = subbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDE: /* AESDEC Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = invsubbytes[eax1.ub[i]];
//STATE ← InvMixColumns( STATE );
for(int j=0; j<4; ++j) {
GX.ub[0+j*4] = ff_mult(0x0E, eax1.ub[0+j*4]) ^ ff_mult(0x0B, eax1.ub[1+j*4]) ^ ff_mult(0x0D, eax1.ub[2+j*4]) ^ ff_mult(0x09, eax1.ub[3+j*4]);
GX.ub[1+j*4] = ff_mult(0x09, eax1.ub[0+j*4]) ^ ff_mult(0x0E, eax1.ub[1+j*4]) ^ ff_mult(0x0B, eax1.ub[2+j*4]) ^ ff_mult(0x0D, eax1.ub[3+j*4]);
GX.ub[2+j*4] = ff_mult(0x0D, eax1.ub[0+j*4]) ^ ff_mult(0x09, eax1.ub[1+j*4]) ^ ff_mult(0x0E, eax1.ub[2+j*4]) ^ ff_mult(0x0B, eax1.ub[3+j*4]);
GX.ub[3+j*4] = ff_mult(0x0B, eax1.ub[0+j*4]) ^ ff_mult(0x0D, eax1.ub[1+j*4]) ^ ff_mult(0x09, eax1.ub[2+j*4]) ^ ff_mult(0x0E, eax1.ub[3+j*4]);
}
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
case 0xDF: /* AESDECLAST Gx, Ex */
nextop = F8;
GET_EX;
//STATE ← SRC1;
//RoundKey ← SRC2;
//STATE ← InvShiftRows( STATE );
for(int i=0; i<16; ++i)
eax1.ub[i] = GX.ub[invshiftrows[i]];
//STATE ← InvSubBytes( STATE );
for(int i=0; i<16; ++i)
GX.ub[i] = invsubbytes[eax1.ub[i]];
//DEST[127:0] ← STATE XOR RoundKey;
GX.q[0] ^= EX->q[0];
GX.q[1] ^= EX->q[1];
break;
default:
return 0;
}
@ -699,6 +860,47 @@ uintptr_t Run660F(x86emu_t *emu, uintptr_t addr)
GX.ud[tmp8u&0x3] = ED->dword[0];
break;
case 0x44: /* PCLMULQDQ Gx, Ex, Ib */
nextop = F8;
GET_EX;
tmp8u = F8;
{
int g = (tmp8u&1)?1:0;
int e = (tmp8u&0b10000)?1:0;
uint64_t result[2] = { 0 };
uint64_t op2[2] = { 0 };
op2[0] = EX->q[e];
for (int i=0; i<64; ++i)
if(GX.q[g]&(1LL<<i)) {
result[0] ^= (op2[0]<<i);
result[1] ^= ((op2[1]<<i)|(op2[0]>>(64-i)));
}
GX.q[0] = result[0];
GX.q[1] = result[1];
}
break;
case 0xDF: // AESKEYGENASSIST Gx, Ex, u8
nextop = F8;
GET_EX;
tmp32u = F8;
for (int i = 4; i < 8; ++i)
GX.ub[i] = subbytes[EX->ub[i]];
for (int i = 12; i < 16; ++i)
GX.ub[i] = subbytes[EX->ub[i]];
GX.ud[0] = GX.ud[1];
tmp8u = GX.ub[4];
GX.ud[1] = GX.ud[1] >> 8;
GX.ub[7] = tmp8u;
GX.ud[1] ^= tmp32u;
GX.ud[2] = GX.ud[3];
tmp8u = GX.ub[12];
GX.ud[3] = GX.ud[3] >> 8;
GX.ub[15] = tmp8u;
GX.ud[3] ^= tmp32u;
break;
default:
return 0;
}

View File

@ -33,6 +33,7 @@ extern int box86_dynarec_jvm;
extern int arm_vfp; // vfp version (3 or 4), with 32 registers is mendatory
extern int arm_swap;
extern int arm_div;
extern int arm_aes;
#endif
#endif
extern int box86_libcef;

View File

@ -81,6 +81,7 @@ int arm_vfp = 0; // vfp version (3 or 4), with 32 registers is mendatory
int arm_swap = 0;
int arm_div = 0;
int arm_v8 = 0;
int arm_aes = 0;
#endif
#else //DYNAREC
int box86_dynarec = 0;
@ -235,6 +236,8 @@ void GatherDynarecExtensions()
arm_div = 1;
#ifdef AT_HWCAP2
unsigned long hwcap2 = real_getauxval(AT_HWCAP2);
if(hwcap2&HWCAP2_AES)
arm_aes = 1;
if((hwcap2&HWCAP2_AES) || (hwcap2&HWCAP2_CRC32))
arm_v8 = 1;
#endif
@ -243,6 +246,8 @@ void GatherDynarecExtensions()
printf_log(LOG_INFO, " SWP");
if(arm_div)
printf_log(LOG_INFO, " IDIVA");
if(arm_aes)
printf_log(LOG_INFO, " AES");
printf_log(LOG_INFO, " PageSize:%zd ", box86_pagesize);
#endif

View File

@ -206,10 +206,12 @@ void my_cpuid(x86emu_t* emu, uint32_t tmp32u)
| 1<<28 // HT / Multi-core
;
R_ECX = 1<<0 // SSE3
| 1<<1 // PCLMULQDQ
| 1<<9 // SSSE3
| 1<<12 // fma
| 1<<13 // cx16 (cmpxchg16)
| 1<<22 // MOVBE
| 1<<25 // aesni
;
break;
case 0x2: // TLB and Cache info. Sending 1st gen P4 info...

View File

@ -1694,7 +1694,7 @@ void CreateCPUInfoFile(int fd)
P;
sprintf(buff, "bogomips\t: %g\n", getBogoMips());
P;
sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 rdtscp ssse3 fma fxsr cx16 movbe pni\n");
sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 rdtscp ssse3 fma cpuid pclmulqdq cx16 aes movbe pni\n");
P;
sprintf(buff, "\n");
P;

1248
tests/ref22.txt Normal file

File diff suppressed because it is too large Load Diff

BIN
tests/test22 Executable file

Binary file not shown.

70
tests/test22.c Normal file
View File

@ -0,0 +1,70 @@
// build with gcc -march=corei7 -O2 -g -maes -mpclmul -m32 test22.c -o test22
#include <stdio.h>
#include <stdint.h>
#include <wmmintrin.h>
// Hard coding types and alignment
typedef long long v2di __attribute__((vector_size(16)));
typedef union {
unsigned long long v[2];
v2di m;
} mm128i;
int need_stop(mm128i *var) {
if (var->v[0] >= 0xEEEEFFFFFFFFEEEFULL) {
if (var->v[1] == 0xFFFFFFFFFFFFFFFFULL) return 1;
else {
var->v[0] += 0x1111000000001111ULL;
++var->v[1];
}
} else var->v[0] += 0x1111000000001111ULL;
if (var->v[1] >= 0xF000000000000000ULL) return 1;
else var->v[1] += 0x1000000000000000ULL;
return 0;
}
int main() {
mm128i x = { .v = {0, 0} };
do {
mm128i y = { .v = {0, 0} };
do {
mm128i enc = { .m = _mm_aesenc_si128(x.m, y.m) };
mm128i enclast = { .m = _mm_aesenclast_si128(x.m, y.m) };
mm128i dec = { .m = _mm_aesdec_si128(x.m, y.m) };
mm128i declast = { .m = _mm_aesdeclast_si128(x.m, y.m) };
printf("enc (0x%016llX%016llX, 0x%016llX%016llX) = 0x%016llX%016llX\n", x.v[1], x.v[0], y.v[1], y.v[0], enc.v[1], enc.v[0]);
printf("enclast(0x%016llX%016llX, 0x%016llX%016llX) = 0x%016llX%016llX\n", x.v[1], x.v[0], y.v[1], y.v[0], enclast.v[1], enclast.v[0]);
printf("dec (0x%016llX%016llX, 0x%016llX%016llX) = 0x%016llX%016llX\n", x.v[1], x.v[0], y.v[1], y.v[0], dec.v[1], dec.v[0]);
printf("declast(0x%016llX%016llX, 0x%016llX%016llX) = 0x%016llX%016llX\n", x.v[1], x.v[0], y.v[1], y.v[0], declast.v[1], declast.v[0]);
} while (!need_stop(&y));
mm128i keygenassist00 = { .m = _mm_aeskeygenassist_si128(x.m, 0) };
printf("keygenassist(0x%016llX%016llX, 0x00) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist00.v[1], keygenassist00.v[0]);
mm128i keygenassist01 = { .m = _mm_aeskeygenassist_si128(x.m, 0x01) };
printf("keygenassist(0x%016llX%016llX, 0x01) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist01.v[1], keygenassist01.v[0]);
mm128i keygenassist02 = { .m = _mm_aeskeygenassist_si128(x.m, 0x02) };
printf("keygenassist(0x%016llX%016llX, 0x02) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist02.v[1], keygenassist02.v[0]);
mm128i keygenassist04 = { .m = _mm_aeskeygenassist_si128(x.m, 0x04) };
printf("keygenassist(0x%016llX%016llX, 0x04) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist04.v[1], keygenassist04.v[0]);
mm128i keygenassist08 = { .m = _mm_aeskeygenassist_si128(x.m, 0x08) };
printf("keygenassist(0x%016llX%016llX, 0x08) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist08.v[1], keygenassist08.v[0]);
mm128i keygenassist10 = { .m = _mm_aeskeygenassist_si128(x.m, 0x10) };
printf("keygenassist(0x%016llX%016llX, 0x10) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist10.v[1], keygenassist10.v[0]);
mm128i keygenassist38 = { .m = _mm_aeskeygenassist_si128(x.m, 0x38) };
printf("keygenassist(0x%016llX%016llX, 0x38) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist38.v[1], keygenassist38.v[0]);
mm128i keygenassist4F = { .m = _mm_aeskeygenassist_si128(x.m, 0x4F) };
printf("keygenassist(0x%016llX%016llX, 0x4F) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassist4F.v[1], keygenassist4F.v[0]);
mm128i keygenassistFF = { .m = _mm_aeskeygenassist_si128(x.m, 0xFF) };
printf("keygenassist(0x%016llX%016llX, 0xFF) = 0x%016llX%016llX\n", x.v[1], x.v[0], keygenassistFF.v[1], keygenassistFF.v[0]);
mm128i imc = { .m = _mm_aesimc_si128(x.m) };
printf("imc (0x%016llX%016llX) = 0x%016llX%016llX\n", x.v[1], x.v[0], imc.v[1], imc.v[0]);
mm128i pclmul00 = { .m = _mm_clmulepi64_si128(keygenassist00.m, x.m, 0) };
printf("pclmul(0x%016llX%016llX, 0x00) = 0x%016llX%016llX\n", x.v[1], x.v[0], pclmul00.v[1], pclmul00.v[0]);
mm128i pclmul01 = { .m = _mm_clmulepi64_si128(keygenassist00.m, x.m, 0x01) };
printf("pclmul(0x%016llX%016llX, 0x01) = 0x%016llX%016llX\n", x.v[1], x.v[0], pclmul01.v[1], pclmul01.v[0]);
mm128i pclmul10 = { .m = _mm_clmulepi64_si128(keygenassist00.m, x.m, 0x10) };
printf("pclmul(0x%016llX%016llX, 0x10) = 0x%016llX%016llX\n", x.v[1], x.v[0], pclmul10.v[1], pclmul10.v[0]);
mm128i pclmul11 = { .m = _mm_clmulepi64_si128(keygenassist00.m, x.m, 0x11) };
printf("pclmul(0x%016llX%016llX, 0xFF) = 0x%016llX%016llX\n", x.v[1], x.v[0], pclmul11.v[1], pclmul11.v[0]);
} while (!need_stop(&x));
}