diff options
author | MITSUNARI Shigeo <[email protected]> | 2023-12-28 20:42:27 +0900 |
---|---|---|
committer | MITSUNARI Shigeo <[email protected]> | 2023-12-28 20:42:27 +0900 |
commit | e1b6896c22eacb71bf2481ec245f0bb6351dc971 (patch) | |
tree | f6ff3fd0e3f3fe0d86e375f7bb9e57f7bd46202f | |
parent | 2e93baa6a63c34cd7775eae25de32d71ff46e226 (diff) | |
parent | c0888cc45fc275ad7ea5850eda8383d0ac381c37 (diff) | |
download | xbyak-e1b6896c22eacb71bf2481ec245f0bb6351dc971.tar.gz xbyak-e1b6896c22eacb71bf2481ec245f0bb6351dc971.zip |
Merge branch 'dev'v7.04
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | doc/changelog.md | 1 | ||||
-rw-r--r-- | gen/gen_code.cpp | 1 | ||||
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | readme.md | 2 | ||||
-rw-r--r-- | readme.txt | 3 | ||||
-rw-r--r-- | test/apx.cpp | 40 | ||||
-rw-r--r-- | xbyak/xbyak.h | 49 | ||||
-rw-r--r-- | xbyak/xbyak_mnemonic.h | 3 |
9 files changed, 78 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 182a5de..5a710cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.5) -project(xbyak LANGUAGES CXX VERSION 7.03) +project(xbyak LANGUAGES CXX VERSION 7.04) file(GLOB headers xbyak/*.h) diff --git a/doc/changelog.md b/doc/changelog.md index df966c9..401bfb8 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,5 +1,6 @@ # History +* 2023/Dec/28 ver 7.04 rex2 supports two-byte opecode * 2023/Dec/26 ver 7.03 set the default value of dfv to 0 * 2023/Dec/20 ver 7.02 SHA* support APX * 2023/Dec/19 ver 7.01 support AESKLE, WIDE_KL, KEYLOCKER, KEYLOCKER_WIDE, detection of APX10/APX diff --git a/gen/gen_code.cpp b/gen/gen_code.cpp index 84e5804..a174e6a 100644 --- a/gen/gen_code.cpp +++ b/gen/gen_code.cpp @@ -1144,7 +1144,6 @@ void put() // misc { puts("void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opMR(addr, reg, 0, 0x8D); }"); - puts("void bswap(const Reg32e& reg) { opRR(Reg32(1), reg, 0, 0x0F); }"); puts("void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } }"); puts("void retf(int imm = 0) { if (imm) { db(0xCA); dw(imm); } else { db(0xCB); } }"); diff --git a/meson.build b/meson.build index abe46f8..b184932 100644 --- a/meson.build +++ b/meson.build @@ -5,7 +5,7 @@ project( 'xbyak', 'cpp', - version: '7.03', + version: '7.04', license: 'BSD-3-Clause', default_options: 'b_ndebug=if-release' ) @@ -1,5 +1,5 @@ -# Xbyak 7.03 [![Badge Build]][Build Status] +# Xbyak 7.04 [![Badge Build]][Build Status] *A C++ JIT assembler for x86 (IA32), x64 (AMD64, x86-64)* @@ -1,5 +1,5 @@ - C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 7.03
+ C++用x86(IA-32), x64(AMD64, x86-64) JITアセンブラ Xbyak 7.04
-----------------------------------------------------------------------------
◎概要
@@ -404,6 +404,7 @@ sample/{echo,hello}.bfは http://www.kmonos.net/alang/etc/brainfuck.php から -----------------------------------------------------------------------------
◎履歴
+2023/12/28 ver 7.04 2バイトオペコードのrex2対応
2023/12/26 ver 7.03 dfvのデフォルト値を0に設定
2023/12/20 ver 7.02 SHA*のAPX対応
2023/12/19 ver 7.01 AESKLE, WIDE_KL, KEYLOCKER, KEYLOCKER_WIDE対応 APX10/APX判定対応
diff --git a/test/apx.cpp b/test/apx.cpp index 207389c..70b7d02 100644 --- a/test/apx.cpp +++ b/test/apx.cpp @@ -1074,6 +1074,13 @@ CYBOZU_TEST_AUTO(mov_misc) setb(r31b|T_zu); setb(r15b|T_zu); setb(ptr [r30]); + + bswap(eax); + bswap(r8d); + bswap(r16d); + bswap(rcx); + bswap(r9); + bswap(r17); } } c; const uint8_t tbl[] = { @@ -1101,7 +1108,13 @@ CYBOZU_TEST_AUTO(mov_misc) 0x62, 0xdc, 0x7f, 0x18, 0x42, 0xc7, 0x62, 0xd4, 0x7f, 0x18, 0x42, 0xc7, 0x62, 0xdc, 0x7f, 0x08, 0x42, 0x06, - + // bswap + 0x0f, 0xc8, + 0x41, 0x0f, 0xc8, + 0xd5, 0x90, 0xc8, + 0x48, 0x0f, 0xc9, + 0x49, 0x0f, 0xc9, + 0xd5, 0x98, 0xc9, }; const size_t n = sizeof(tbl); CYBOZU_TEST_EQUAL(c.getSize(), n); @@ -1898,3 +1911,28 @@ CYBOZU_TEST_AUTO(sha) CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n); } +CYBOZU_TEST_AUTO(0x0f_rex2) +{ + struct Code : Xbyak::CodeGenerator { + Code() + { + addps(xmm3, ptr [r30+r20*4+0x4]); + movups(xmm5, ptr [r16]); + movq(r31, xmm5); + cvtsd2si(r20, ptr [r30]); + bsr(r20, r30); + } + } c; + const uint8_t tbl[] = { + 0xd5, 0xb1, 0x58, 0x5c, 0xa6, 0x04, + 0xd5, 0x90, 0x10, 0x28, 0x66, + 0xd5, 0x99, 0x7e, 0xef, 0xf2, + 0xd5, 0xd9, 0x2d, 0x26, + 0xd5, 0xd9, 0xbd, 0xe6, + + }; + const size_t n = sizeof(tbl); + CYBOZU_TEST_EQUAL(c.getSize(), n); + CYBOZU_TEST_EQUAL_ARRAY(c.getCode(), tbl, n); +} + diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h index 0a4337e..990728d 100644 --- a/xbyak/xbyak.h +++ b/xbyak/xbyak.h @@ -155,7 +155,7 @@ namespace Xbyak { enum { DEFAULT_MAX_CODE_SIZE = 4096, - VERSION = 0x7030 /* 0xABCD = A.BC(.D) */ + VERSION = 0x7040 /* 0xABCD = A.BC(.D) */ }; #ifndef MIE_INTEGER_TYPE_DEFINED @@ -1736,14 +1736,15 @@ private: db(0xD5); db((rexRXB(4, bit3, r, b, x) << 4) | rex4bit); } - void rex(const Operand& op1, const Operand& op2 = Operand(), uint64_t type = 0) + // return true if rex2 is selected + bool rex(const Operand& op1, const Operand& op2 = Operand(), uint64_t type = 0) { - if (op1.getNF() | op2.getNF()) XBYAK_THROW(ERR_INVALID_NF) - if (op1.getZU() | op2.getZU()) XBYAK_THROW(ERR_INVALID_ZU) + if (op1.getNF() | op2.getNF()) XBYAK_THROW_RET(ERR_INVALID_NF, false) + if (op1.getZU() | op2.getZU()) XBYAK_THROW_RET(ERR_INVALID_ZU, false) uint8_t rex = 0; const Operand *p1 = &op1, *p2 = &op2; if (p1->isMEM()) std::swap(p1, p2); - if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) + if (p1->isMEM()) XBYAK_THROW_RET(ERR_BAD_COMBINATION, false) // except movsx(16bit, 32/64bit) bool p66 = (op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e)); if ((type & T_66) || p66) db(0x66); @@ -1753,6 +1754,7 @@ private: if (type & T_F3) { db(0xF3); } + bool is0F = type & T_0F; if (p2->isMEM()) { const Reg& r = *static_cast<const Reg*>(p1); const Address& addr = p2->getAddress(); @@ -1762,9 +1764,9 @@ private: if (BIT == 64 && addr.is32bit()) db(0x67); rex = rexRXB(3, r.isREG(64), r, base, idx); if (r.hasRex2() || addr.hasRex2()) { - if (type & (T_0F|T_0F38|T_0F3A)) XBYAK_THROW(ERR_CANT_USE_REX2) - rex2(0, rex, r, base, idx); - return; + if (type & (T_0F38|T_0F3A)) XBYAK_THROW_RET(ERR_CANT_USE_REX2, false) + rex2(is0F, rex, r, base, idx); + return true; } if (rex || r.isExt8bit()) rex |= 0x40; } else { @@ -1773,13 +1775,14 @@ private: // ModRM(reg, base); rex = rexRXB(3, r1.isREG(64) || r2.isREG(64), r2, r1); if (r1.hasRex2() || r2.hasRex2()) { - if (type & (T_0F|T_0F38|T_0F3A)) XBYAK_THROW(ERR_CANT_USE_REX2) - rex2(0, rex, r2, r1); - return; + if (type & (T_0F38|T_0F3A)) XBYAK_THROW_RET(ERR_CANT_USE_REX2, 0) + rex2(is0F, rex, r2, r1); + return true; } if (rex || r1.isExt8bit() || r2.isExt8bit()) rex |= 0x40; } if (rex) db(rex); + return false; } // @@@begin of avx_type_def.h static const uint64_t T_NONE = 0ull; @@ -2022,9 +2025,9 @@ private: } LabelManager labelMgr_; bool isInDisp16(uint32_t x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; } - void writeCode(uint64_t type, const Reg& r, int code) + void writeCode(uint64_t type, const Reg& r, int code, bool rex2 = false) { - if (!(type & T_APX)) { + if (!(type&T_APX || rex2)) { if (type & T_0F) { db(0x0F); } else if (type & T_0F38) { @@ -2037,15 +2040,15 @@ private: } void opRR(const Reg& reg1, const Reg& reg2, uint64_t type, int code) { - rex(reg2, reg1, type); - writeCode(type, reg1, code); + bool rex2 = rex(reg2, reg1, type); + writeCode(type, reg1, code, rex2); setModRM(3, reg1.getIdx(), reg2.getIdx()); } void opMR(const Address& addr, const Reg& r, uint64_t type, int code, int immSize = 0) { if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP) - rex(addr, r, type); - writeCode(type, r, code); + bool rex2 = rex(addr, r, type); + writeCode(type, r, code, rex2); opAddr(addr, r.getIdx(), immSize); } void opLoadSeg(const Address& addr, const Reg& reg, uint64_t type, int code) @@ -3133,6 +3136,18 @@ public: { opROO(Reg(), op, x, T_MUST_EVEX, 0xD9); } + void bswap(const Reg32e& r) + { + int idx = r.getIdx(); + uint8_t rex = (r.isREG(64) ? 8 : 0) | ((idx & 8) ? 1 : 0); + if (idx >= 16) { + db(0xD5); db((1<<7) | (idx & 16) | rex); + } else { + if (rex) db(0x40 | rex); + db(0x0F); + } + db(0xC8 + (idx & 7)); + } /* use single byte nop if useMultiByteNop = false */ diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h index ff7900f..7771417 100644 --- a/xbyak/xbyak_mnemonic.h +++ b/xbyak/xbyak_mnemonic.h @@ -1,4 +1,4 @@ -const char *getVersionString() const { return "7.03"; } +const char *getVersionString() const { return "7.04"; } void aadd(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38, 0x0FC); } void aand(const Address& addr, const Reg32e ®) { opMR(addr, reg, T_0F38 | T_66, 0x0FC); } void adc(const Operand& op, uint32_t imm) { opOI(op, imm, 0x10, 2); } @@ -55,7 +55,6 @@ void bndmov(const BoundsReg& bnd, const Operand& op) { opRO(bnd, op, T_66 | T_0F void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, T_0F, 0x1B); } void bsf(const Reg®, const Operand& op) { opRO(reg, op, T_0F, 0xBC, op.isREG(16|i32e)); } void bsr(const Reg®, const Operand& op) { opRO(reg, op, T_0F, 0xBD, op.isREG(16|i32e)); } -void bswap(const Reg32e& reg) { opRR(Reg32(1), reg, 0, 0x0F); } void bt(const Operand& op, const Reg& reg) { opRO(reg, op, T_0F, 0xA3, op.isREG(16|i32e) && op.getBit() == reg.getBit()); } void bt(const Operand& op, uint8_t imm) { opRext(op, 16|i32e, 4, T_0F, 0xba, false, 1); db(imm); } void btc(const Operand& op, const Reg& reg) { opRO(reg, op, T_0F, 0xBB, op.isREG(16|i32e) && op.getBit() == reg.getBit()); } |