add test of 3op apx

This commit is contained in:
MITSUNARI Shigeo 2023-11-09 11:16:40 +09:00
parent 9b21727ba0
commit b1f0fef4d0
4 changed files with 61 additions and 26 deletions

View file

@ -796,24 +796,25 @@ void put()
uint8_t ext; // (reg, imm) uint8_t ext; // (reg, imm)
const char *name; const char *name;
bool support3op; bool support3op;
bool allowNF; uint64_t type;
} tbl[] = { } tbl[] = {
{ 0x10, 2, "adc", true, false }, { 0x10, 2, "adc", true, T_NONE },
{ 0x00, 0, "add", true, true }, { 0x00, 0, "add", true, T_NF },
{ 0x20, 4, "and_", true, true }, { 0x20, 4, "and_", true, T_NF },
{ 0x38, 7, "cmp", false, false }, { 0x38, 7, "cmp", false, T_NONE },
{ 0x08, 1, "or_", true, true }, { 0x08, 1, "or_", true, T_NF },
{ 0x18, 3, "sbb", true, false }, { 0x18, 3, "sbb", true, T_NONE },
{ 0x28, 5, "sub", true, true }, { 0x28, 5, "sub", true, T_NF },
{ 0x30, 6, "xor_", true, true }, { 0x30, 6, "xor_", true, T_NF },
}; };
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i]; const Tbl *p = &tbl[i];
printf("void %s(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x%02X); }\n", p->name, p->code); printf("void %s(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x%02X); }\n", p->name, p->code);
printf("void %s(const Operand& op, uint32_t imm) { opOI(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext); printf("void %s(const Operand& op, uint32_t imm) { opOI(op, imm, 0x%02X, %d); }\n", p->name, p->code, p->ext);
if (!p->support3op) continue; if (!p->support3op) continue;
printf("void %s(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x%02X); }\n", p->name, p->code); std::string type = type2String(0);//p->type);
printf("void %s(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, %d); }\n", p->name, p->ext); printf("void %s(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, %s, 0x%02X); }\n", p->name, type.c_str(), p->code);
printf("void %s(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, %s, %d); }\n", p->name, type.c_str(), p->ext);
} }
} }
{ {

View file

@ -378,3 +378,37 @@ CYBOZU_TEST_AUTO(adcx_adox)
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n); CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
} }
CYBOZU_TEST_AUTO(r3_2)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
add(rax, rcx, rdx);
adc(rax, rcx, rdx);
and_(rax, rcx, rdx);
or_(rax, rcx, rdx);
sbb(rax, rcx, rdx);
sub(rax, rcx, rdx);
xor_(rax, rcx, rdx);
add(r30, ptr [r20], r9);
adc(r30, ptr [r20], r9);
and_(r30, ptr [r20], r9);
or_(r30, ptr [r20], r9);
sbb(r30, ptr [r20], r9);
sub(r30, ptr [r20], r9);
xor_(r30, ptr [r20], r9);
}
} c;
const uint8_t tbl[] = {
0x62, 0xf4, 0xfc, 0x18, 0x01, 0xd1, 0x62, 0xf4, 0xfc, 0x18, 0x11, 0xd1, 0x62, 0xf4, 0xfc, 0x18,
0x21, 0xd1, 0x62, 0xf4, 0xfc, 0x18, 0x09, 0xd1, 0x62, 0xf4, 0xfc, 0x18, 0x19, 0xd1, 0x62, 0xf4,
0xfc, 0x18, 0x29, 0xd1, 0x62, 0xf4, 0xfc, 0x18, 0x31, 0xd1, 0x62, 0x7c, 0x8c, 0x10, 0x01, 0x0c,
0x24, 0x62, 0x7c, 0x8c, 0x10, 0x11, 0x0c, 0x24, 0x62, 0x7c, 0x8c, 0x10, 0x21, 0x0c, 0x24, 0x62,
0x7c, 0x8c, 0x10, 0x09, 0x0c, 0x24, 0x62, 0x7c, 0x8c, 0x10, 0x19, 0x0c, 0x24, 0x62, 0x7c, 0x8c,
0x10, 0x29, 0x0c, 0x24, 0x62, 0x7c, 0x8c, 0x10, 0x31, 0x0c, 0x24,
};
const size_t n = sizeof(tbl);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}

View file

@ -1911,7 +1911,7 @@ private:
int pp = type ? getPP(type) : r.isBit(16); int pp = type ? getPP(type) : r.isBit(16);
int V4 = !v.isExtIdx2(); int V4 = !v.isExtIdx2();
int ND = v.isREG(); int ND = v.isREG();
int NF = r.getNF(); int NF = v.getNF();
if ((type & T_NF) == 0 && NF) XBYAK_THROW(ERR_INVALID_NF) if ((type & T_NF) == 0 && NF) XBYAK_THROW(ERR_INVALID_NF)
db(0x62); db(0x62);
db((R3<<7) | (X3<<6) | B3 | R4 | B4 | M); db((R3<<7) | (X3<<6) | B3 | R4 | B4 | M);

View file

@ -3,14 +3,14 @@ void aadd(const Address& addr, const Reg32e &reg) { opMR(addr, reg, T_0F38, 0x0F
void aand(const Address& addr, const Reg32e &reg) { opMR(addr, reg, T_0F38 | T_66, 0x0FC); } void aand(const Address& addr, const Reg32e &reg) { opMR(addr, reg, T_0F38 | T_66, 0x0FC); }
void adc(const Operand& op, uint32_t imm) { opOI(op, imm, 0x10, 2); } void adc(const Operand& op, uint32_t imm) { opOI(op, imm, 0x10, 2); }
void adc(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x10); } void adc(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x10); }
void adc(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 2); } void adc(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 2); }
void adc(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x10); } void adc(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x10); }
void adcx(const Reg32e& d, const Reg32e& reg, const Operand& op) { opROO(d, op, reg, T_66, 0x66); } void adcx(const Reg32e& d, const Reg32e& reg, const Operand& op) { opROO(d, op, reg, T_66, 0x66); }
void adcx(const Reg32e& reg, const Operand& op) { if (!reg.isREG(16|i32e) && reg.getBit() == op.getBit()) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) if (opROO(Reg(), op, reg, T_66, 0x66)) return; opRO(reg, op, T_66 | T_0F38, 0xF6); } void adcx(const Reg32e& reg, const Operand& op) { if (!reg.isREG(16|i32e) && reg.getBit() == op.getBit()) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) if (opROO(Reg(), op, reg, T_66, 0x66)) return; opRO(reg, op, T_66 | T_0F38, 0xF6); }
void add(const Operand& op, uint32_t imm) { opOI(op, imm, 0x00, 0); } void add(const Operand& op, uint32_t imm) { opOI(op, imm, 0x00, 0); }
void add(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x00); } void add(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x00); }
void add(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 0); } void add(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 0); }
void add(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x00); } void add(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x00); }
void addpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x58, isXMM_XMMorMEM); } void addpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x58, isXMM_XMMorMEM); }
void addps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x58, isXMM_XMMorMEM); } void addps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x58, isXMM_XMMorMEM); }
void addsd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_F2, 0x58, isXMM_XMMorMEM); } void addsd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_F2, 0x58, isXMM_XMMorMEM); }
@ -27,8 +27,8 @@ void aesimc(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_66|T_0F38|T_W0
void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8_t imm) { opSSE(xmm, op, T_66|T_0F3A, 0xDF, isXMM_XMMorMEM, imm); } void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8_t imm) { opSSE(xmm, op, T_66|T_0F3A, 0xDF, isXMM_XMMorMEM, imm); }
void and_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x20, 4); } void and_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x20, 4); }
void and_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x20); } void and_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x20); }
void and_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 4); } void and_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 4); }
void and_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x20); } void and_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x20); }
void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opRRO(r1, r2, op, T_0F38, 0xf2); } void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opRRO(r1, r2, op, T_0F38, 0xf2); }
void andnpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x55, isXMM_XMMorMEM); } void andnpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x55, isXMM_XMMorMEM); }
void andnps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x55, isXMM_XMMorMEM); } void andnps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x55, isXMM_XMMorMEM); }
@ -567,8 +567,8 @@ void neg(const Operand& op) { opRext(op, 0, 3, 0, 0xF6); }
void not_(const Operand& op) { opRext(op, 0, 2, 0, 0xF6); } void not_(const Operand& op) { opRext(op, 0, 2, 0, 0xF6); }
void or_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x08, 1); } void or_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x08, 1); }
void or_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x08); } void or_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x08); }
void or_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 1); } void or_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 1); }
void or_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x08); } void or_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x08); }
void orpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x56, isXMM_XMMorMEM); } void orpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x56, isXMM_XMMorMEM); }
void orps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x56, isXMM_XMMorMEM); } void orps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x56, isXMM_XMMorMEM); }
void out_(const Reg& d, const Reg& a) { opInOut(a, d, 0xEE); } void out_(const Reg& d, const Reg& a) { opInOut(a, d, 0xEE); }
@ -760,8 +760,8 @@ void sar(const Operand& op, int imm) { opShift(op, imm, 7); }
void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opRRO(r1, r2, op, T_F3|T_0F38, 0xf7); } void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opRRO(r1, r2, op, T_F3|T_0F38, 0xf7); }
void sbb(const Operand& op, uint32_t imm) { opOI(op, imm, 0x18, 3); } void sbb(const Operand& op, uint32_t imm) { opOI(op, imm, 0x18, 3); }
void sbb(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x18); } void sbb(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x18); }
void sbb(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 3); } void sbb(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 3); }
void sbb(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x18); } void sbb(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x18); }
void scasb() { db(0xAE); } void scasb() { db(0xAE); }
void scasd() { db(0xAF); } void scasd() { db(0xAF); }
void scasw() { db(0x66); db(0xAF); } void scasw() { db(0x66); db(0xAF); }
@ -830,8 +830,8 @@ void stosd() { db(0xAB); }
void stosw() { db(0x66); db(0xAB); } void stosw() { db(0x66); db(0xAB); }
void sub(const Operand& op, uint32_t imm) { opOI(op, imm, 0x28, 5); } void sub(const Operand& op, uint32_t imm) { opOI(op, imm, 0x28, 5); }
void sub(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x28); } void sub(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x28); }
void sub(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 5); } void sub(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 5); }
void sub(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x28); } void sub(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x28); }
void subpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x5C, isXMM_XMMorMEM); } void subpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x5C, isXMM_XMMorMEM); }
void subps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x5C, isXMM_XMMorMEM); } void subps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x5C, isXMM_XMMorMEM); }
void subsd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_F2, 0x5C, isXMM_XMMorMEM); } void subsd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_F2, 0x5C, isXMM_XMMorMEM); }
@ -1410,8 +1410,8 @@ void xgetbv() { db(0x0F); db(0x01); db(0xD0); }
void xlatb() { db(0xD7); } void xlatb() { db(0xD7); }
void xor_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x30, 6); } void xor_(const Operand& op, uint32_t imm) { opOI(op, imm, 0x30, 6); }
void xor_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x30); } void xor_(const Operand& op1, const Operand& op2) { opRO_MR(op1, op2, 0x30); }
void xor_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, 0, 6); } void xor_(const Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NONE, 6); }
void xor_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, 0, 0x30); } void xor_(const Reg& d, const Operand& op1, const Operand& op2) { opROO(d, op1, op2, T_NONE, 0x30); }
void xorpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x57, isXMM_XMMorMEM); } void xorpd(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F | T_66, 0x57, isXMM_XMMorMEM); }
void xorps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x57, isXMM_XMMorMEM); } void xorps(const Xmm& xmm, const Operand& op) { opSSE(xmm, op, T_0F, 0x57, isXMM_XMMorMEM); }
#ifdef XBYAK_ENABLE_OMITTED_OPERAND #ifdef XBYAK_ENABLE_OMITTED_OPERAND