aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gen/avx_type.hpp4
-rw-r--r--gen/gen_code.cpp19
-rw-r--r--test/apx.cpp25
-rw-r--r--xbyak/xbyak.h4
-rw-r--r--xbyak/xbyak_mnemonic.h2
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); }