Skip to content

Commit

Permalink
add cfcmov
Browse files Browse the repository at this point in the history
  • Loading branch information
herumi committed Nov 29, 2023
1 parent a4ec97c commit e2d9685
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 1 deletion.
29 changes: 29 additions & 0 deletions gen/gen_code.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,6 +641,35 @@ void put()
printf("void ctest%s(const Operand& op, int imm, int dfv) { opTesti(op, imm, dfv, %d); }\n", s, p->ext);
}
}
{
// cfcmov
const struct Tbl {
uint8_t code;
const char *suf;
} tbl[] = {
{0x40, "o"},
{0x41, "no"},
{0x42, "b"},
{0x43, "nb"},
{0x44, "z"},
{0x45, "nz"},
{0x46, "be"},
{0x47, "nbe"},
{0x48, "s"},
{0x49, "ns"},
{0x4A, "p"},
{0x4B, "np"},
{0x4C, "l"},
{0x4D, "nl"},
{0x4E, "le"},
{0x4F, "nle"},
};
for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) {
const Tbl *p = &tbl[i];
printf("void cfcmov%s(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x%02X); }\n", p->suf, p->code);
printf("void cfcmov%s(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x%02X); }\n", p->suf, p->code);
}
}
{
const struct Tbl {
const char *name;
Expand Down
35 changes: 35 additions & 0 deletions test/apx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1601,3 +1601,38 @@ CYBOZU_TEST_AUTO(ctestb)
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}

CYBOZU_TEST_AUTO(cfcmov)
{
struct Code : Xbyak::CodeGenerator {
Code()
{
cfcmovb(r30w, r31w);
cfcmovb(r30d, r31d);
cfcmovb(r30, r31);
cfcmovb(ptr [r8+r20*4+0x3], r19w);
cfcmovb(ptr [r8+r20*4+0x3], r19d);
cfcmovb(ptr [r8+r20*4+0x3], r19);
cfcmovb(r30w, ptr [r9]);
cfcmovb(r30d, ptr [r9]);
cfcmovb(r30, ptr [r9]);
cfcmovb(r20w, r30w, r31w);
cfcmovb(r20d, r30d, r31d);
cfcmovb(r20, r30, r31);
cfcmovb(r20w, r30w, ptr [r9]);
cfcmovb(r20d, r30d, ptr [r9]);
cfcmovb(r20, r30, ptr [r9]);
}
} c;
const uint8_t tbl[] = {
0x62, 0x4c, 0x7d, 0x0c, 0x42, 0xfe, 0x62, 0x4c, 0x7c, 0x0c, 0x42, 0xfe, 0x62, 0x4c, 0xfc, 0x0c,
0x42, 0xfe, 0x62, 0xc4, 0x79, 0x0c, 0x42, 0x5c, 0xa0, 0x03, 0x62, 0xc4, 0x78, 0x0c, 0x42, 0x5c,
0xa0, 0x03, 0x62, 0xc4, 0xf8, 0x0c, 0x42, 0x5c, 0xa0, 0x03, 0x62, 0x44, 0x7d, 0x08, 0x42, 0x31,
0x62, 0x44, 0x7c, 0x08, 0x42, 0x31, 0x62, 0x44, 0xfc, 0x08, 0x42, 0x31, 0x62, 0x4c, 0x5d, 0x14,
0x42, 0xf7, 0x62, 0x4c, 0x5c, 0x14, 0x42, 0xf7, 0x62, 0x4c, 0xdc, 0x14, 0x42, 0xf7, 0x62, 0x44,
0x5d, 0x14, 0x42, 0x31, 0x62, 0x44, 0x5c, 0x14, 0x42, 0x31, 0x62, 0x44, 0xdc, 0x14, 0x42, 0x31,
};
const size_t n = sizeof(tbl);
CYBOZU_TEST_EQUAL(c.getSize(), n);
CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n);
}

16 changes: 15 additions & 1 deletion xbyak/xbyak.h
Original file line number Diff line number Diff line change
Expand Up @@ -2192,7 +2192,7 @@ class CodeGenerator : public CodeArray {
// (r, r, m) or (r, m, r)
bool opROO(const Reg& d, const Operand& op1, const Operand& op2, uint64_t type, int code, int immSize = 0, int sc = NONE)
{
if (!d.isREG() && !(d.hasRex2NFZU() || op1.hasRex2NFZU() || op2.hasRex2NFZU())) return false;
if (!(type & T_MUST_EVEX) && !d.isREG() && !(d.hasRex2NFZU() || op1.hasRex2NFZU() || op2.hasRex2NFZU())) return false;
const Operand *p1 = &op1, *p2 = &op2;
if (p1->isMEM()) { std::swap(p1, p2); } else { if (p2->isMEM()) code |= 2; }
if (p1->isMEM()) XBYAK_THROW_RET(ERR_BAD_COMBINATION, false)
Expand Down Expand Up @@ -2681,6 +2681,20 @@ class CodeGenerator : public CodeArray {
opROO(Reg(15 - dfv, Operand::REG, opBit), op, Reg(0, Operand::REG, opBit), T_VEX|T_CODE1_IF1, 0xF6, immBit / 8, sc);
db(imm, immBit / 8);
}
void opCfcmov(const Reg& d, const Operand& op1, const Operand& op2, int code)
{
const int dBit = d.getBit();
const int op2Bit = op2.getBit();
if (dBit > 0 && op2Bit > 0 && dBit != op2Bit) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
if (op1.isBit(8) || op2Bit == 8) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER)
if (op2.isMEM()) {
if (op1.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION)
uint64_t type = dBit > 0 ? (T_MUST_EVEX|T_NF) : T_MUST_EVEX;
opROO(d, op2, op1, type, code);
} else {
opROO(d, op1, static_cast<const Reg&>(op2)|T_nf, T_MUST_EVEX|T_NF, 0x42);
}
}
#ifdef XBYAK64
void opAMX(const Tmm& t1, const Address& addr, uint64_t type, int code)
{
Expand Down
32 changes: 32 additions & 0 deletions xbyak/xbyak_mnemonic.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,38 @@ void ccmpt(const Operand& op1, const Operand& op2, int dfv) { opCcmp(op1, op2, d
void ccmpz(const Operand& op, int imm, int dfv) { opCcmpi(op, imm, dfv, 4); }
void ccmpz(const Operand& op1, const Operand& op2, int dfv) { opCcmp(op1, op2, dfv, 0x38, 4); }
void cdq() { db(0x99); }
void cfcmovb(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x42); }
void cfcmovb(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x42); }
void cfcmovbe(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x46); }
void cfcmovbe(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x46); }
void cfcmovl(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4C); }
void cfcmovl(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4C); }
void cfcmovle(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4E); }
void cfcmovle(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4E); }
void cfcmovnb(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x43); }
void cfcmovnb(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x43); }
void cfcmovnbe(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x47); }
void cfcmovnbe(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x47); }
void cfcmovnl(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4D); }
void cfcmovnl(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4D); }
void cfcmovnle(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4F); }
void cfcmovnle(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4F); }
void cfcmovno(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x41); }
void cfcmovno(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x41); }
void cfcmovnp(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4B); }
void cfcmovnp(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4B); }
void cfcmovns(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x49); }
void cfcmovns(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x49); }
void cfcmovnz(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x45); }
void cfcmovnz(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x45); }
void cfcmovo(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x40); }
void cfcmovo(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x40); }
void cfcmovp(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x4A); }
void cfcmovp(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x4A); }
void cfcmovs(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x48); }
void cfcmovs(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x48); }
void cfcmovz(const Operand& op1, const Operand& op2) { opCfcmov(Reg(), op1, op2, 0x44); }
void cfcmovz(const Reg& d, const Reg& r, const Operand& op) { opCfcmov(d|T_nf, op, r, 0x44); }
void clc() { db(0xF8); }
void cld() { db(0xFC); }
void cldemote(const Address& addr) { opMR(addr, eax, T_0F, 0x1C); }
Expand Down

0 comments on commit e2d9685

Please sign in to comment.