diff options
-rw-r--r-- | gen/avx_type.hpp | 4 | ||||
-rw-r--r-- | gen/gen_code.cpp | 19 | ||||
-rw-r--r-- | test/apx.cpp | 25 | ||||
-rw-r--r-- | xbyak/xbyak.h | 4 | ||||
-rw-r--r-- | xbyak/xbyak_mnemonic.h | 2 |
5 files changed, 46 insertions, 8 deletions
diff --git a/gen/avx_type.hpp b/gen/avx_type.hpp index 6375f11..7106702 100644 --- a/gen/avx_type.hpp +++ b/gen/avx_type.hpp @@ -67,8 +67,8 @@ std::string type2String(uint64_t type) if (type & T_MEM_EVEX) str += "|T_MEM_EVEX"; if (type & T_NF) str += "|T_NF"; if (type & T_CODE1_IF1) str += "|T_CODE1_IF1"; - if (type & T_MAP3) str += "T_MAP3"; - if (type & T_ND1) str += "T_ND1"; + if (type & T_MAP3) str += "|T_MAP3"; + if (type & T_ND1) str += "|T_ND1"; if (str[0] == '|') str = str.substr(1); return str; diff --git a/gen/gen_code.cpp b/gen/gen_code.cpp index d12ae65..fdaf891 100644 --- a/gen/gen_code.cpp +++ b/gen/gen_code.cpp @@ -870,13 +870,14 @@ void put() uint8_t ext; const char *name; bool NF; + int n; // # of op } tbl[] = { - { 0xF6, 6, "div", true }, - { 0xF6, 7, "idiv", true }, - { 0xF6, 5, "imul", true }, - { 0xF6, 4, "mul", true }, - { 0xF6, 3, "neg", true }, - { 0xF6, 2, "not_", false }, + { 0xF6, 6, "div", true, 1 }, + { 0xF6, 7, "idiv", true, 1 }, + { 0xF6, 5, "imul", true ,3 }, + { 0xF6, 4, "mul", true, 1 }, + { 0xF6, 3, "neg", true, 2 }, + { 0xF6, 2, "not_", false, 2 }, }; for (size_t i = 0; i < NUM_OF_ARRAY(tbl); i++) { const Tbl *p = &tbl[i]; @@ -885,6 +886,12 @@ void put() if (p->NF) type |= T_NF; std::string s = type2String(type); printf("void %s(const Operand& op) { opRext(op, 0, %d, %s, 0x%02X); }\n", p->name, p->ext, s.c_str(), p->code); + if (p->n == 2) { + uint64_t type = T_VEX|T_ND1|T_CODE1_IF1; + if (p->NF) type |= T_NF; + std::string s = type2String(type); + printf("void %s(const Reg& d, const Operand& op) { opROO(d, op, Reg(%d, Operand::REG, d.getBit()), %s, 0xF6); }\n", p->name, p->ext, s.c_str()); + } } } { diff --git a/test/apx.cpp b/test/apx.cpp index 19c6694..87a354b 100644 --- a/test/apx.cpp +++ b/test/apx.cpp @@ -804,6 +804,21 @@ CYBOZU_TEST_AUTO(div) not_(word [r20+r30*1]); not_(dword [r20+r30*1]); not_(qword [r20+r30*1]); + + // 2op + 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[] = { @@ -839,6 +854,16 @@ 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, + + // 2op + // neg + 0x62, 0xf4, 0x0c, 0x10, 0xf6, 0xd8, 0x62, 0xf4, 0x0d, 0x10, 0xf7, 0xd8, 0x62, 0xf4, 0x0c, 0x10, + 0xf7, 0xd8, 0x62, 0xf4, 0x8c, 0x10, 0xf7, 0xd8, 0x62, 0xf4, 0x8c, 0x14, 0xf7, 0xd8, 0x62, 0xf4, + 0xf4, 0x1c, 0xf7, 0xd8, 0x62, 0xdc, 0xf4, 0x18, 0xf7, 0x1e, + + // not + 0x62, 0xf4, 0x0c, 0x10, 0xf6, 0xd0, 0x62, 0xf4, 0x0d, 0x10, 0xf7, 0xd0, 0x62, 0xf4, 0x0c, 0x10, + 0xf7, 0xd0, 0x62, 0xf4, 0x8c, 0x10, 0xf7, 0xd0, 0x62, 0xdc, 0xf4, 0x18, 0xf7, 0x16, }; const size_t n = sizeof(tbl); CYBOZU_TEST_EQUAL(c.getSize(), n); diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index 5ca6d44..cc762df 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -3044,6 +3044,10 @@ public: size -= len; } } + void not2(const Reg& d, const Operand& op) + { + opROO(d, op, Reg(2, Operand::REG, d.getBit()), T_VEX|T_ND1|T_CODE1_IF1, 0xF6); + } #ifndef XBYAK_DONT_READ_LIST #include "xbyak_mnemonic.h" /* diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index d7c8d68..f70c46e 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -566,7 +566,9 @@ void mulx(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opRRO(r1, r2, void mwait() { db(0x0F); db(0x01); db(0xC9); } void mwaitx() { db(0x0F); db(0x01); db(0xFB); } void neg(const Operand& op) { opRext(op, 0, 3, T_VEX|T_NF|T_CODE1_IF1, 0xF6); } +void neg(const Reg& d, const Operand& op) { opROO(d, op, Reg(3, Operand::REG, d.getBit()), T_VEX|T_NF|T_CODE1_IF1|T_ND1, 0xF6); } void not_(const Operand& op) { opRext(op, 0, 2, T_VEX|T_CODE1_IF1, 0xF6); } +void not_(const Reg& d, const Operand& op) { opROO(d, op, Reg(2, Operand::REG, d.getBit()), T_VEX|T_CODE1_IF1|T_ND1, 0xF6); } 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 Reg& d, const Operand& op, uint32_t imm) { opROI(d, op, imm, T_NF|T_CODE1_IF1, 1); } |