aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <[email protected]>2023-11-17 14:39:03 +0900
committerMITSUNARI Shigeo <[email protected]>2023-11-17 14:39:03 +0900
commit50875294c25b38168c5ff60177295541df1ad30d (patch)
tree0bde291b0aa5321c167613bf3b50312e9752aa8e
parentd20142d0140859e385cb3dd4becda1e43ea30108 (diff)
downloadxbyak-50875294c25b38168c5ff60177295541df1ad30d.tar.gz
xbyak-50875294c25b38168c5ff60177295541df1ad30d.zip
add tests of 2-op imul
-rw-r--r--test/apx.cpp69
-rw-r--r--xbyak/xbyak.h5
2 files changed, 44 insertions, 30 deletions
diff --git a/test/apx.cpp b/test/apx.cpp
index a5ada01..08cbbb9 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 b424334..afa6c6a 100644
--- a/xbyak/xbyak.h
+++ b/xbyak/xbyak.h
@@ -606,6 +606,7 @@ public:
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 @@ private:
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 @@ public:
// (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)