From 50875294c25b38168c5ff60177295541df1ad30d Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Fri, 17 Nov 2023 14:39:03 +0900 Subject: [PATCH] add tests of 2-op imul --- test/apx.cpp | 69 ++++++++++++++++++++++++++++++--------------------- xbyak/xbyak.h | 5 ++-- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/test/apx.cpp b/test/apx.cpp index a5ada010..08cbbb91 100644 --- a/test/apx.cpp +++ b/test/apx.cpp @@ -735,7 +735,7 @@ CYBOZU_TEST_AUTO(inc_dec) CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n); } -CYBOZU_TEST_AUTO(div) +CYBOZU_TEST_AUTO(div_op1) { struct Code : Xbyak::CodeGenerator { Code() @@ -804,29 +804,6 @@ CYBOZU_TEST_AUTO(div) not_(word [r20+r30*1]); not_(dword [r20+r30*1]); not_(qword [r20+r30*1]); - - // 2op - // imul(r30b, al); // QQQ : not supported? - imul(r30w, ax); - imul(r30d, eax); - imul(r30, rax); - imul(r30|T_nf, rax); - imul(rcx|T_nf, rax); - imul(rcx, ptr [r30]); - - neg(r30b, al); - neg(r30w, ax); - neg(r30d, eax); - neg(r30, rax); - neg(r30|T_nf, rax); - neg(rcx|T_nf, rax); - neg(rcx, ptr [r30]); - - not_(r30b, al); - not_(r30w, ax); - not_(r30d, eax); - not_(r30, rax); - not_(rcx, ptr [r30]); } } c; const uint8_t tbl[] = { @@ -862,12 +839,48 @@ CYBOZU_TEST_AUTO(div) 0xf7, 0xd4, 0x62, 0xfc, 0xfc, 0x08, 0xf7, 0xd4, 0x62, 0xbc, 0x78, 0x08, 0xf6, 0x14, 0x34, 0x62, 0xbc, 0x79, 0x08, 0xf7, 0x14, 0x34, 0x62, 0xbc, 0x78, 0x08, 0xf7, 0x14, 0x34, 0x62, 0xbc, 0xf8, 0x08, 0xf7, 0x14, 0x34, + }; + const size_t n = sizeof(tbl); + CYBOZU_TEST_EQUAL(c.getSize(), n); + CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n); +} - // 2op +CYBOZU_TEST_AUTO(imul_2op) +{ + struct Code : Xbyak::CodeGenerator { + Code() + { + // imul(r30b, al); // QQQ : not supported? + imul(r30w, ax); + imul(r30d, eax); + imul(r30, rax); + imul(r30|T_nf, rax); + imul(rcx|T_nf, rax); + imul(rcx, ptr [r30]); + + neg(r30b, al); + neg(r30w, ax); + neg(r30d, eax); + neg(r30, rax); + neg(r30|T_nf, rax); + neg(rcx|T_nf, rax); + neg(rcx, ptr [r30]); + + not_(r30b, al); + not_(r30w, ax); + not_(r30d, eax); + not_(r30, rax); + not_(rcx, ptr [r30]); + } + } c; + const uint8_t tbl[] = { // imul - 0x62, 0x64, 0x7d, 0x08, 0xaf, 0xf0, 0x62, 0x64, 0x7c, 0x08, 0xaf, 0xf0, 0x62, 0x64, 0xfc, 0x08, - 0xaf, 0xf0, 0x62, 0x64, 0xfc, 0x0c, 0xaf, 0xf0, 0x62, 0xf4, 0xfc, 0x0c, 0xaf, 0xc8, 0x62, 0xdc, - 0xfc, 0x08, 0xaf, 0x0e, + 0x62, 0x64, 0x7d, 0x08, 0xaf, 0xf0, + 0x62, 0x64, 0x7c, 0x08, 0xaf, 0xf0, + 0x62, 0x64, 0xfc, 0x08, 0xaf, 0xf0, + 0x62, 0x64, 0xfc, 0x0c, 0xaf, 0xf0, + 0x62, 0xf4, 0xfc, 0x0c, 0xaf, 0xc8, + 0x62, 0xdc, 0xfc, 0x08, 0xaf, 0x0e, // neg 0x62, 0xf4, 0x0c, 0x10, 0xf6, 0xd8, 0x62, 0xf4, 0x0d, 0x10, 0xf7, 0xd8, 0x62, 0xf4, 0x0c, 0x10, diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index b4243349..afa6c6ae 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -606,6 +606,7 @@ class Operand { XBYAK_CONSTEXPR bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); } XBYAK_CONSTEXPR bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); } XBYAK_CONSTEXPR bool hasRex2() const; + XBYAK_CONSTEXPR bool hasRex2NF() const { return hasRex2() || NF_; } XBYAK_CONSTEXPR bool hasZero() const { return zero_; } XBYAK_CONSTEXPR int getOpmaskIdx() const { return mask_; } XBYAK_CONSTEXPR int getRounding() const { return rounding_; } @@ -2176,7 +2177,7 @@ class CodeGenerator : public CodeArray { int opBit = op.getBit(); if (disableRex && opBit == 64) opBit = 32; const Reg r(ext, Operand::REG, opBit); - if ((type & T_VEX) && (op.hasRex2() || op.getNF()) && opROO(Reg(0, Operand::REG, opBit), op, r, type, code)) return; + if ((type & T_VEX) && op.hasRex2NF() && opROO(Reg(0, Operand::REG, opBit), op, r, type, code)) return; if (op.isMEM()) { opMR(op.getAddress(), r, type, code, immSize); } else if (op.isREG(bit)) { @@ -2899,7 +2900,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) { - if (!(type & T_VEX) && !d.isREG() && !(d.hasRex2() || op1.hasRex2() || op2.hasRex2())) return false; + if (!d.isREG() && !(d.hasRex2NF() || op1.hasRex2NF() || op2.hasRex2NF())) 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)