Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
xbyak.h
Go to the documentation of this file.
1#pragma once
2#ifndef XBYAK_XBYAK_H_
3#define XBYAK_XBYAK_H_
12#ifndef XBYAK_NO_OP_NAMES
13 #if not +0 // trick to detect whether 'not' is operator or not
14 #error "use -fno-operator-names option if you want to use and(), or(), xor(), not() as function names, Or define XBYAK_NO_OP_NAMES and use and_(), or_(), xor_(), not_()."
15 #endif
16#endif
18#include <stdio.h> // for debug print
19#include <assert.h>
20#include <list>
21#include <string>
22#include <algorithm>
23#ifndef NDEBUG
24#include <iostream>
25#endif
27// #define XBYAK_DISABLE_AVX512
29//#define XBYAK_USE_MMAP_ALLOCATOR
30#if !defined(__GNUC__) || defined(__MINGW32__)
31 #undef XBYAK_USE_MMAP_ALLOCATOR
32#endif
34#ifdef __GNUC__
35 #define XBYAK_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor))
36#else
37 #define XBYAK_GNUC_PREREQ(major, minor) 0
38#endif
40// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft.
41#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\
42 ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)))
43 #include <unordered_map>
44 #define XBYAK_STD_UNORDERED_MAP std::unordered_map
45 #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap
47/*
48 Clang/llvm-gcc and ICC-EDG in 'GCC-mode' always claim to be GCC 4.2, using
49 libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version).
50*/
51#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__)
52 #include <tr1/unordered_map>
53 #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
54 #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
56#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600)
57 #include <unordered_map>
58 #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map
59 #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap
61#else
62 #include <map>
63 #define XBYAK_STD_UNORDERED_MAP std::map
64 #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap
65#endif
66#ifdef _WIN32
67 #include <winsock2.h>
68 #include <windows.h>
69 #include <malloc.h>
70#elif defined(__GNUC__)
71 #include <unistd.h>
72 #include <sys/mman.h>
73 #include <stdlib.h>
74#endif
75#if !defined(_MSC_VER) || (_MSC_VER >= 1600)
76 #include <stdint.h>
77#endif
79#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__))
80 #define XBYAK64_WIN
81#elif defined(__x86_64__)
82 #define XBYAK64_GCC
83#endif
84#if !defined(XBYAK64) && !defined(XBYAK32)
85 #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN)
86 #define XBYAK64
87 #else
88 #define XBYAK32
89 #endif
90#endif
92#if (__cplusplus >= 201103) || (_MSC_VER >= 1800)
93 #define XBYAK_VARIADIC_TEMPLATE
94#endif
96#ifdef _MSC_VER
97 #pragma warning(push)
98 #pragma warning(disable : 4514) /* remove inline function */
99 #pragma warning(disable : 4786) /* identifier is too long */
100 #pragma warning(disable : 4503) /* name is too long */
101 #pragma warning(disable : 4127) /* constant expresison */
102#endif
104namespace Xbyak {
106enum {
108 VERSION = 0x5630 /* 0xABCD = A.BC(D) */
111#ifndef MIE_INTEGER_TYPE_DEFINED
112#define MIE_INTEGER_TYPE_DEFINED
113#ifdef _MSC_VER
114 typedef unsigned __int64 uint64;
115 typedef __int64 sint64;
116#else
119#endif
120typedef unsigned int uint32;
121typedef unsigned short uint16;
122typedef unsigned char uint8;
123#endif
125#ifndef MIE_ALIGN
126 #ifdef _MSC_VER
127 #define MIE_ALIGN(x) __declspec(align(x))
128 #else
129 #define MIE_ALIGN(x) __attribute__((aligned(x)))
130 #endif
131#endif
132#ifndef MIE_PACK // for shufps
133 #define MIE_PACK(x, y, z, w) ((x) * 64 + (y) * 16 + (z) * 4 + (w))
134#endif
136enum {
184class Error : public std::exception {
185 int err_;
186public:
187 explicit Error(int err) : err_(err)
189 if (err_ < 0 || err_ > ERR_INTERNAL) {
190 fprintf(stderr, "bad err=%d in Xbyak::Error\n", err_);
191 exit(1);
194 operator int() const { return err_; }
195 const char *what() const throw()
197 static const char *errTbl[] = {
198 "none",
199 "bad addressing",
200 "code is too big",
201 "bad scale",
202 "esp can't be index",
203 "bad combination",
204 "bad size of register",
205 "imm is too big",
206 "bad align",
207 "label is redefined",
208 "label is too far",
209 "label is not found",
210 "code is not copyable",
211 "bad parameter",
212 "can't protect",
213 "can't use 64bit disp(use (void*))",
214 "offset is too big",
215 "MEM size is not specified",
216 "bad mem size",
217 "bad st combination",
218 "over local label",
219 "under local label",
220 "can't alloc",
221 "T_SHORT is not supported in AutoGrow",
222 "bad protect mode",
223 "bad pNum",
224 "bad tNum",
225 "bad vsib addressing",
226 "can't convert",
227 "label is not set by L()",
228 "label is already set by L()",
229 "bad label string",
230 "err munmap",
231 "opmask is already set",
232 "rounding is already set",
233 "k0 is invalid",
234 "evex is invalid",
235 "sae(suppress all exceptions) is invalid",
236 "er(embedded rounding) is invalid",
237 "invalid broadcast",
238 "invalid opmask with memory",
239 "invalid zero",
240 "invalid rip in AutoGrow",
241 "invalid mib address",
242 "internal error",
243 };
244 assert((size_t)err_ < sizeof(errTbl) / sizeof(*errTbl));
245 return errTbl[err_];
249inline const char *ConvertErrorToString(const Error& err)
251 return err.what();
254inline void *AlignedMalloc(size_t size, size_t alignment)
256#ifdef __MINGW32__
257 return __mingw_aligned_malloc(size, alignment);
258#elif defined(_WIN32)
259 return _aligned_malloc(size, alignment);
260#else
261 void *p;
262 int ret = posix_memalign(&p, alignment, size);
263 return (ret == 0) ? p : 0;
264#endif
267inline void AlignedFree(void *p)
269#ifdef __MINGW32__
270 __mingw_aligned_free(p);
271#elif defined(_MSC_VER)
272 _aligned_free(p);
273#else
274 free(p);
275#endif
278template<class To, class From>
279inline const To CastTo(From p) throw()
281 return (const To)(size_t)(p);
283namespace inner {
285static const size_t ALIGN_PAGE_SIZE = 4096;
287inline bool IsInDisp8(uint32 x) { return 0xFFFFFF80 <= x || x <= 0x7F; }
288inline bool IsInInt32(uint64 x) { return ~uint64(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; }
292#ifdef XBYAK64
294#endif
295 return static_cast<uint32>(x);
299 LasIs, // as is
300 Labs, // absolute
301 LaddTop // (addr + top) for mov(reg, label) with AutoGrow
304} // inner
307 custom allocator
309struct Allocator {
310 virtual uint8 *alloc(size_t size) { return reinterpret_cast<uint8*>(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); }
311 virtual void free(uint8 *p) { AlignedFree(p); }
312 virtual ~Allocator() {}
313 /* override to return false if you call protect() manually */
314 virtual bool useProtect() const { return true; }
317#ifdef XBYAK_USE_MMAP_ALLOCATOR
318class MmapAllocator : Allocator {
320 SizeList sizeList_;
321public:
322 uint8 *alloc(size_t size)
324 const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1;
325 size = (size + alignedSizeM1) & ~alignedSizeM1;
326#ifdef MAP_ANONYMOUS
327 const int mode = MAP_PRIVATE | MAP_ANONYMOUS;
328#elif defined(MAP_ANON)
329 const int mode = MAP_PRIVATE | MAP_ANON;
330#else
331 #error "not supported"
332#endif
333 void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, -1, 0);
334 if (p == MAP_FAILED) throw Error(ERR_CANT_ALLOC);
335 assert(p);
336 sizeList_[(uintptr_t)p] = size;
337 return (uint8*)p;
339 void free(uint8 *p)
341 if (p == 0) return;
342 SizeList::iterator i = sizeList_.find((uintptr_t)p);
343 if (i == sizeList_.end()) throw Error(ERR_BAD_PARAMETER);
344 if (munmap((void*)i->first, i->second) < 0) throw Error(ERR_MUNMAP);
345 sizeList_.erase(i);
348#endif
351class Reg;
353class Operand {
354 static const uint8 EXT8BIT = 0x20;
355 unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil
356 unsigned int kind_:9;
357 unsigned int bit_:10;
358protected:
359 unsigned int zero_:1;
360 unsigned int mask_:3;
361 unsigned int rounding_:3;
362 void setIdx(int idx) { idx_ = idx; }
363public:
364 enum Kind {
365 NONE = 0,
366 MEM = 1 << 0,
367 REG = 1 << 1,
368 MMX = 1 << 2,
369 FPU = 1 << 3,
370 XMM = 1 << 4,
371 YMM = 1 << 5,
372 ZMM = 1 << 6,
373 OPMASK = 1 << 7,
374 BNDREG = 1 << 8
375 };
376 enum Code {
377#ifdef XBYAK64
378 RAX = 0, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15,
379 R8D = 8, R9D, R10D, R11D, R12D, R13D, R14D, R15D,
380 R8W = 8, R9W, R10W, R11W, R12W, R13W, R14W, R15W,
381 R8B = 8, R9B, R10B, R11B, R12B, R13B, R14B, R15B,
382 SPL = 4, BPL, SIL, DIL,
383#endif
384 EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI,
385 AX = 0, CX, DX, BX, SP, BP, SI, DI,
386 AL = 0, CL, DL, BL, AH, CH, DH, BH
387 };
388 Operand() : idx_(0), kind_(0), bit_(0), zero_(0), mask_(0), rounding_(0) { }
389 Operand(int idx, Kind kind, int bit, bool ext8bit = 0)
390 : idx_(static_cast<uint8>(idx | (ext8bit ? EXT8BIT : 0)))
391 , kind_(kind)
392 , bit_(bit)
393 , zero_(0), mask_(0), rounding_(0)
395 assert((bit_ & (bit_ - 1)) == 0); // bit must be power of two
397 Kind getKind() const { return static_cast<Kind>(kind_); }
398 int getIdx() const { return idx_ & (EXT8BIT - 1); }
399 bool isNone() const { return kind_ == 0; }
400 bool isMMX() const { return is(MMX); }
401 bool isXMM() const { return is(XMM); }
402 bool isYMM() const { return is(YMM); }
403 bool isZMM() const { return is(ZMM); }
404 bool isXMEM() const { return is(XMM | MEM); }
405 bool isYMEM() const { return is(YMM | MEM); }
406 bool isZMEM() const { return is(ZMM | MEM); }
407 bool isOPMASK() const { return is(OPMASK); }
408 bool isBNDREG() const { return is(BNDREG); }
409 bool isREG(int bit = 0) const { return is(REG, bit); }
410 bool isMEM(int bit = 0) const { return is(MEM, bit); }
411 bool isFPU() const { return is(FPU); }
412 bool isExt8bit() const { return (idx_ & EXT8BIT) != 0; }
413 bool isExtIdx() const { return (getIdx() & 8) != 0; }
414 bool isExtIdx2() const { return (getIdx() & 16) != 0; }
415 bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); }
416 bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); }
417 bool hasZero() const { return zero_; }
418 int getOpmaskIdx() const { return mask_; }
419 int getRounding() const { return rounding_; }
420 void setKind(Kind kind)
422 if ((kind & (XMM|YMM|ZMM)) == 0) return;
423 kind_ = kind;
424 bit_ = kind == XMM ? 128 : kind == YMM ? 256 : 512;
426 void setBit(int bit) { bit_ = bit; }
427 void setOpmaskIdx(int idx, bool ignore_idx0 = false)
429 if (!ignore_idx0 && idx == 0) throw Error(ERR_K0_IS_INVALID);
431 mask_ = idx;
433 void setRounding(int idx)
438 void setZero() { zero_ = true; }
439 // ah, ch, dh, bh?
440 bool isHigh8bit() const
442 if (!isBit(8)) return false;
443 if (isExt8bit()) return false;
444 const int idx = getIdx();
445 return AH <= idx && idx <= BH;
447 // any bit is accetable if bit == 0
448 bool is(int kind, uint32 bit = 0) const
450 return (kind == 0 || (kind_ & kind)) && (bit == 0 || (bit_ & bit)); // cf. you can set (8|16)
452 bool isBit(uint32 bit) const { return (bit_ & bit) != 0; }
453 uint32 getBit() const { return bit_; }
454 const char *toString() const
456 const int idx = getIdx();
457 if (kind_ == REG) {
458 if (isExt8bit()) {
459 static const char *tbl[4] = { "spl", "bpl", "sil", "dil" };
460 return tbl[idx - 4];
462 static const char *tbl[4][16] = {
463 { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" },
464 { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" },
465 { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" },
466 { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" },
467 };
468 return tbl[bit_ == 8 ? 0 : bit_ == 16 ? 1 : bit_ == 32 ? 2 : 3][idx];
469 } else if (isOPMASK()) {
470 static const char *tbl[8] = { "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" };
471 return tbl[idx];
472 } else if (isZMM()) {
473 static const char *tbl[32] = {
474 "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15",
475 "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31"
476 };
477 return tbl[idx];
478 } else if (isYMM()) {
479 static const char *tbl[32] = {
480 "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15",
481 "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31"
482 };
483 return tbl[idx];
484 } else if (isXMM()) {
485 static const char *tbl[32] = {
486 "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15",
487 "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31"
488 };
489 return tbl[idx];
490 } else if (isMMX()) {
491 static const char *tbl[8] = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" };
492 return tbl[idx];
493 } else if (isFPU()) {
494 static const char *tbl[8] = { "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7" };
495 return tbl[idx];
496 } else if (isBNDREG()) {
497 static const char *tbl[4] = { "bnd0", "bnd1", "bnd2", "bnd3" };
498 return tbl[idx];
502 bool isEqualIfNotInherited(const Operand& rhs) const { return idx_ == rhs.idx_ && kind_ == rhs.kind_ && bit_ == rhs.bit_ && zero_ == rhs.zero_ && mask_ == rhs.mask_ && rounding_ == rhs.rounding_; }
503 bool operator==(const Operand& rhs) const;
504 bool operator!=(const Operand& rhs) const { return !operator==(rhs); }
505 const Address& getAddress() const;
506 const Reg& getReg() const;
509class Label;
511struct Reg8;
512struct Reg16;
513struct Reg32;
514#ifdef XBYAK64
515struct Reg64;
516#endif
517class Reg : public Operand {
518public:
519 Reg() { }
520 Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { }
521 Reg changeBit(int bit) const { return Reg(getIdx(), getKind(), bit, isExt8bit()); }
522 uint8 getRexW() const { return isREG(64) ? 8 : 0; }
523 uint8 getRexR() const { return isExtIdx() ? 4 : 0; }
524 uint8 getRexX() const { return isExtIdx() ? 2 : 0; }
525 uint8 getRexB() const { return isExtIdx() ? 1 : 0; }
526 uint8 getRex(const Reg& base = Reg()) const
528 uint8 rex = getRexW() | getRexR() | base.getRexW() | base.getRexB();
529 if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40;
530 return rex;
532 Reg8 cvt8() const;
533 Reg16 cvt16() const;
534 Reg32 cvt32() const;
535#ifdef XBYAK64
536 Reg64 cvt64() const;
537#endif
540inline const Reg& Operand::getReg() const
542 assert(!isMEM());
543 return static_cast<const Reg&>(*this);
546struct Reg8 : public Reg {
547 explicit Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { }
550struct Reg16 : public Reg {
551 explicit Reg16(int idx = 0) : Reg(idx, Operand::REG, 16) { }
554struct Mmx : public Reg {
555 explicit Mmx(int idx = 0, Kind kind = Operand::MMX, int bit = 64) : Reg(idx, kind, bit) { }
559 enum {
565 };
571struct Xmm : public Mmx {
572 explicit Xmm(int idx = 0, Kind kind = Operand::XMM, int bit = 128) : Mmx(idx, kind, bit) { }
573 Xmm(Kind kind, int idx) : Mmx(idx, kind, kind == XMM ? 128 : kind == YMM ? 256 : 512) { }
574 Xmm operator|(const EvexModifierRounding& emr) const { Xmm r(*this); r.setRounding(emr.rounding); return r; }
575 Xmm copyAndSetIdx(int idx) const { Xmm ret(*this); ret.setIdx(idx); return ret; }
576 Xmm copyAndSetKind(Operand::Kind kind) const { Xmm ret(*this); ret.setKind(kind); return ret; }
579struct Ymm : public Xmm {
580 explicit Ymm(int idx = 0, Kind kind = Operand::YMM, int bit = 256) : Xmm(idx, kind, bit) { }
581 Ymm operator|(const EvexModifierRounding& emr) const { Ymm r(*this); r.setRounding(emr.rounding); return r; }
584struct Zmm : public Ymm {
585 explicit Zmm(int idx = 0) : Ymm(idx, Operand::ZMM, 512) { }
586 Zmm operator|(const EvexModifierRounding& emr) const { Zmm r(*this); r.setRounding(emr.rounding); return r; }
589struct Opmask : public Reg {
590 explicit Opmask(int idx = 0) : Reg(idx, Operand::OPMASK, 64) {}
593struct BoundsReg : public Reg {
594 explicit BoundsReg(int idx = 0) : Reg(idx, Operand::BNDREG, 128) {}
597template<class T>T operator|(const T& x, const Opmask& k) { T r(x); r.setOpmaskIdx(k.getIdx()); return r; }
598template<class T>T operator|(const T& x, const EvexModifierZero&) { T r(x); r.setZero(); return r; }
599template<class T>T operator|(const T& x, const EvexModifierRounding& emr) { T r(x); r.setRounding(emr.rounding); return r; }
601struct Fpu : public Reg {
602 explicit Fpu(int idx = 0) : Reg(idx, Operand::FPU, 32) { }
605struct Reg32e : public Reg {
606 explicit Reg32e(int idx, int bit) : Reg(idx, Operand::REG, bit) {}
608struct Reg32 : public Reg32e {
609 explicit Reg32(int idx = 0) : Reg32e(idx, 32) {}
611#ifdef XBYAK64
612struct Reg64 : public Reg32e {
613 explicit Reg64(int idx = 0) : Reg32e(idx, 64) {}
615struct RegRip {
616 sint64 disp_;
617 const Label* label_;
618 bool isAddr_;
619 explicit RegRip(sint64 disp = 0, const Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {}
620 friend const RegRip operator+(const RegRip& r, sint64 disp) {
621 return RegRip(r.disp_ + disp, r.label_, r.isAddr_);
623 friend const RegRip operator-(const RegRip& r, sint64 disp) {
624 return RegRip(r.disp_ - disp, r.label_, r.isAddr_);
626 friend const RegRip operator+(const RegRip& r, const Label& label) {
627 if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING);
628 return RegRip(r.disp_, &label);
630 friend const RegRip operator+(const RegRip& r, const void *addr) {
631 if (r.label_ || r.isAddr_) throw Error(ERR_BAD_ADDRESSING);
632 return RegRip(r.disp_ + (sint64)addr, 0, true);
635#endif
637inline Reg8 Reg::cvt8() const
639 const int idx = getIdx();
640 if (isBit(8)) return Reg8(idx, isExt8bit());
641#ifdef XBYAK32
642 if (idx >= 4) throw Error(ERR_CANT_CONVERT);
643#endif
644 return Reg8(idx, 4 <= idx && idx < 8);
647inline Reg16 Reg::cvt16() const
649 const int idx = getIdx();
650 if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
651 return Reg16(idx);
654inline Reg32 Reg::cvt32() const
656 const int idx = getIdx();
657 if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
658 return Reg32(idx);
661#ifdef XBYAK64
662inline Reg64 Reg::cvt64() const
664 const int idx = getIdx();
665 if (isBit(8) && (4 <= idx && idx < 8) && !isExt8bit()) throw Error(ERR_CANT_CONVERT);
666 return Reg64(idx);
668#endif
670#ifndef XBYAK_DISABLE_SEGMENT
671// not derived from Reg
672class Segment {
673 int idx_;
674public:
675 enum {
676 es, cs, ss, ds, fs, gs
677 };
678 explicit Segment(int idx) : idx_(idx) { assert(0 <= idx_ && idx_ < 6); }
679 int getIdx() const { return idx_; }
680 const char *toString() const
682 static const char tbl[][3] = {
683 "es", "cs", "ss", "ds", "fs", "gs"
684 };
685 return tbl[idx_];
688#endif
690class RegExp {
691public:
692#ifdef XBYAK64
693 enum { i32e = 32 | 64 };
694#else
695 enum { i32e = 32 };
696#endif
697 RegExp(size_t disp = 0) : scale_(0), disp_(disp) { }
698 RegExp(const Reg& r, int scale = 1)
699 : scale_(scale)
700 , disp_(0)
703 if (scale == 0) return;
704 if (scale != 1 && scale != 2 && scale != 4 && scale != 8) throw Error(ERR_BAD_SCALE);
705 if (r.getBit() >= 128 || scale != 1) { // xmm/ymm is always index
706 index_ = r;
707 } else {
708 base_ = r;
711 bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); }
714 RegExp exp = *this;
715 // [reg * 2] => [reg + reg]
716 if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) {
717 exp.base_ = index_;
718 exp.scale_ = 1;
720 return exp;
722 bool operator==(const RegExp& rhs) const
724 return base_ == rhs.base_ && index_ == rhs.index_ && disp_ == rhs.disp_ && scale_ == rhs.scale_;
726 const Reg& getBase() const { return base_; }
727 const Reg& getIndex() const { return index_; }
728 int getScale() const { return scale_; }
729 size_t getDisp() const { return disp_; }
730 void verify() const
732 if (base_.getBit() >= 128) throw Error(ERR_BAD_SIZE_OF_REGISTER);
733 if (index_.getBit() && index_.getBit() <= 64) {
735 if (base_.getBit() && base_.getBit() != index_.getBit()) throw Error(ERR_BAD_SIZE_OF_REGISTER);
738 friend RegExp operator+(const RegExp& a, const RegExp& b);
739 friend RegExp operator-(const RegExp& e, size_t disp);
740 uint8 getRex() const
742 uint8 rex = index_.getRexX() | base_.getRexB();
743 return rex ? uint8(rex | 0x40) : 0;
745private:
746 /*
747 [base_ + index_ * scale_ + disp_]
748 base : Reg32e, index : Reg32e(w/o esp), Xmm, Ymm
749 */
750 Reg base_;
751 Reg index_;
752 int scale_;
753 size_t disp_;
756inline RegExp operator+(const RegExp& a, const RegExp& b)
758 if (a.index_.getBit() && b.index_.getBit()) throw Error(ERR_BAD_ADDRESSING);
760 if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; }
761 if (b.base_.getBit()) {
762 if (ret.base_.getBit()) {
763 if (ret.index_.getBit()) throw Error(ERR_BAD_ADDRESSING);
764 // base + base => base + index * 1
765 ret.index_ = b.base_;
766 // [reg + esp] => [esp + reg]
767 if (ret.index_.getIdx() == Operand::ESP) std::swap(ret.base_, ret.index_);
768 ret.scale_ = 1;
769 } else {
770 ret.base_ = b.base_;
773 ret.disp_ += b.disp_;
774 return ret;
776inline RegExp operator*(const Reg& r, int scale)
778 return RegExp(r, scale);
780inline RegExp operator-(const RegExp& e, size_t disp)
783 ret.disp_ -= disp;
784 return ret;
787// 2nd parameter for constructor of CodeArray(maxSize, userPtr, alloc)
788void *const AutoGrow = (void*)1; //-V566
791 enum Type {
792 USER_BUF = 1, // use userPtr(non alignment, non protect)
793 ALLOC_BUF, // use new(alignment, protect)
794 AUTO_GROW // automatically move and grow memory if necessary
795 };
796 CodeArray(const CodeArray& rhs);
797 void operator=(const CodeArray&);
798 bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; }
799 struct AddrInfo {
800 size_t codeOffset; // position to write
801 size_t jmpAddr; // value to write
802 int jmpSize; // size of jmpAddr
804 AddrInfo(size_t _codeOffset, size_t _jmpAddr, int _jmpSize, inner::LabelMode _mode)
805 : codeOffset(_codeOffset), jmpAddr(_jmpAddr), jmpSize(_jmpSize), mode(_mode) {}
806 uint64 getVal(const uint8 *top) const
808 uint64 disp = (mode == inner::LaddTop) ? jmpAddr + size_t(top) : (mode == inner::LasIs) ? jmpAddr : jmpAddr - size_t(top);
809 if (jmpSize == 4) disp = inner::VerifyInInt32(disp);
810 return disp;
812 };
813 typedef std::list<AddrInfo> AddrInfoList;
814 AddrInfoList addrInfoList_;
815 const Type type_;
816#ifdef XBYAK_USE_MMAP_ALLOCATOR
817 MmapAllocator defaultAllocator_;
818#else
819 Allocator defaultAllocator_;
820#endif
821 Allocator *alloc_;
822protected:
823 size_t maxSize_;
825 size_t size_;
828 /*
829 allocate new memory and copy old data to the new area
830 */
833 const size_t newSize = (std::max<size_t>)(DEFAULT_MAX_CODE_SIZE, maxSize_ * 2);
834 uint8 *newTop = alloc_->alloc(newSize);
835 if (newTop == 0) throw Error(ERR_CANT_ALLOC);
836 for (size_t i = 0; i < size_; i++) newTop[i] = top_[i];
837 alloc_->free(top_);
838 top_ = newTop;
839 maxSize_ = newSize;
841 /*
842 calc jmp address for AutoGrow mode
843 */
847 for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) {
848 uint64 disp = i->getVal(top_);
849 rewrite(i->codeOffset, disp, i->jmpSize);
851 if (alloc_->useProtect() && !protect(top_, size_, true)) throw Error(ERR_CANT_PROTECT);
854public:
855 explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0)
856 : type_(userPtr == AutoGrow ? AUTO_GROW : userPtr ? USER_BUF : ALLOC_BUF)
857 , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_)
858 , maxSize_(maxSize)
859 , top_(type_ == USER_BUF ? reinterpret_cast<uint8*>(userPtr) : alloc_->alloc((std::max<size_t>)(maxSize, 1)))
860 , size_(0)
863 if (maxSize_ > 0 && top_ == 0) throw Error(ERR_CANT_ALLOC);
864 if ((type_ == ALLOC_BUF && alloc_->useProtect()) && !protect(top_, maxSize, true)) {
865 alloc_->free(top_);
869 virtual ~CodeArray()
871 if (isAllocType()) {
872 if (alloc_->useProtect()) protect(top_, maxSize_, false);
873 alloc_->free(top_);
878 size_ = 0;
879 addrInfoList_.clear();
882 void db(int code)
884 if (size_ >= maxSize_) {
885 if (type_ == AUTO_GROW) {
887 } else {
891 top_[size_++] = static_cast<uint8>(code);
893 void db(const uint8 *code, size_t codeSize)
895 for (size_t i = 0; i < codeSize; i++) db(code[i]);
897 void db(uint64 code, size_t codeSize)
899 if (codeSize > 8) throw Error(ERR_BAD_PARAMETER);
900 for (size_t i = 0; i < codeSize; i++) db(static_cast<uint8>(code >> (i * 8)));
902 void dw(uint32 code) { db(code, 2); }
903 void dd(uint32 code) { db(code, 4); }
904 void dq(uint64 code) { db(code, 8); }
905 const uint8 *getCode() const { return top_; }
906 template<class F>
907 const F getCode() const { return CastTo<F>(top_); }
908 const uint8 *getCurr() const { return &top_[size_]; }
909 template<class F>
910 const F getCurr() const { return CastTo<F>(&top_[size_]); }
911 size_t getSize() const { return size_; }
912 void setSize(size_t size)
915 size_ = size;
917 void dump() const
919 const uint8 *p = getCode();
920 size_t bufSize = getSize();
921 size_t remain = bufSize;
922 for (int i = 0; i < 4; i++) {
923 size_t disp = 16;
924 if (remain < 16) {
925 disp = remain;
927 for (size_t j = 0; j < 16; j++) {
928 if (j < disp) {
929 printf("%02X", p[i * 16 + j]);
932 putchar('\n');
933 remain -= disp;
934 if (remain == 0) {
935 break;
939 /*
940 @param offset [in] offset from top
941 @param disp [in] offset from the next of jmp
942 @param size [in] write size(1, 2, 4, 8)
943 */
944 void rewrite(size_t offset, uint64 disp, size_t size)
946 assert(offset < maxSize_);
947 if (size != 1 && size != 2 && size != 4 && size != 8) throw Error(ERR_BAD_PARAMETER);
948 uint8 *const data = top_ + offset;
949 for (size_t i = 0; i < size; i++) {
950 data[i] = static_cast<uint8>(disp >> (i * 8));
953 void save(size_t offset, size_t val, int size, inner::LabelMode mode)
955 addrInfoList_.push_back(AddrInfo(offset, val, size, mode));
957 bool isAutoGrow() const { return type_ == AUTO_GROW; }
966 static inline bool protect(const void *addr, size_t size, bool canExec)
968#if defined(_WIN32)
969 DWORD oldProtect;
970 return VirtualProtect(const_cast<void*>(addr), size, canExec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldProtect) != 0;
971#elif defined(__GNUC__)
972 size_t pageSize = sysconf(_SC_PAGESIZE);
973 size_t iaddr = reinterpret_cast<size_t>(addr);
974 size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1));
975 int mode = PROT_READ | PROT_WRITE | (canExec ? PROT_EXEC : 0);
976 return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0;
977#else
978 return true;
979#endif
987 static inline uint8 *getAlignedAddress(uint8 *addr, size_t alignedSize = 16)
989 return reinterpret_cast<uint8*>((reinterpret_cast<size_t>(addr) + alignedSize - 1) & ~(alignedSize - static_cast<size_t>(1)));
993class Address : public Operand {
994public:
1001 Address(uint32 sizeBit, bool broadcast, const RegExp& e)
1002 : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), permitVsib_(false), broadcast_(broadcast)
1006#ifdef XBYAK64
1007 explicit Address(size_t disp)
1008 : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), permitVsib_(false), broadcast_(false){ }
1009 Address(uint32 sizeBit, bool broadcast, const RegRip& addr)
1010 : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), permitVsib_(false), broadcast_(broadcast) { }
1011#endif
1012 void permitVsib() const { permitVsib_ = true; }
1013 RegExp getRegExp(bool optimize = true) const
1015 return optimize ? e_.optimize() : e_;
1017 Mode getMode() const { return mode_; }
1018 bool is32bit() const { verify(); return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; }
1019 bool isOnlyDisp() const { verify(); return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax
1020 size_t getDisp() const { verify(); return e_.getDisp(); }
1023 verify();
1024 if (mode_ != M_ModRM) return 0;
1025 return getRegExp().getRex();
1027 bool is64bitDisp() const { verify(); return mode_ == M_64bitDisp; } // for moffset
1028 bool isBroadcast() const { return broadcast_; }
1029 const Label* getLabel() const { return label_; }
1030 bool operator==(const Address& rhs) const
1032 return getBit() == rhs.getBit() && e_ == rhs.e_ && label_ == rhs.label_ && mode_ == rhs.mode_ && permitVsib_ == rhs.permitVsib_ && broadcast_ == rhs.broadcast_;
1034 bool operator!=(const Address& rhs) const { return !operator==(rhs); }
1035private:
1037 const Label* label_;
1038 Mode mode_;
1039 mutable bool permitVsib_;
1040 bool broadcast_;
1041 void verify() const { if (e_.isVsib() && !permitVsib_) throw Error(ERR_BAD_VSIB_ADDRESSING); }
1044inline const Address& Operand::getAddress() const
1046 assert(isMEM());
1047 return static_cast<const Address&>(*this);
1050inline bool Operand::operator==(const Operand& rhs) const
1052 if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress();
1057 void operator=(const AddressFrame&);
1059public:
1061 const bool broadcast_;
1062 explicit AddressFrame(uint32 bit, bool broadcast = false) : bit_(bit), broadcast_(broadcast) { }
1067 Address operator[](const void *disp) const
1069 return Address(bit_, broadcast_, RegExp(reinterpret_cast<size_t>(disp)));
1071#ifdef XBYAK64
1072 Address operator[](uint64 disp) const { return Address(disp); }
1073 Address operator[](const RegRip& addr) const { return Address(bit_, broadcast_, addr); }
1074#endif
1077struct JmpLabel {
1078 size_t endOfJmp; /* offset from top to the end address of jmp */
1081 size_t disp; // disp for [rip + disp]
1090class Label {
1091 mutable LabelManager *mgr;
1092 mutable int id;
1093 friend class LabelManager;
1094public:
1095 Label() : mgr(0), id(0) {}
1096 Label(const Label& rhs);
1097 Label& operator=(const Label& rhs);
1099 int getId() const { return id; }
1100 const uint8 *getAddress() const;
1102 // backward compatibility
1103 static inline std::string toStr(int num)
1105 char buf[16];
1106#if defined(_MSC_VER) && (_MSC_VER < 1900)
1107 _snprintf_s
1108#else
1109 snprintf
1110#endif
1111 (buf, sizeof(buf), ".%08x", num);
1112 return buf;
1117 // for string label
1118 struct SlabelVal {
1119 size_t offset;
1120 SlabelVal(size_t offset) : offset(offset) {}
1124 struct SlabelState {
1125 SlabelDefList defList;
1126 SlabelUndefList undefList;
1128 typedef std::list<SlabelState> StateList;
1129 // for Label class
1130 struct ClabelVal {
1131 ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {}
1132 size_t offset;
1133 int refCount;
1139 // global : stateList_.front(), local : stateList_.back()
1140 StateList stateList_;
1141 mutable int labelId_;
1142 ClabelDefList clabelDefList_;
1143 ClabelUndefList clabelUndefList_;
1145 int getId(const Label& label) const
1147 if (label.id == 0) label.id = labelId_++;
1148 return label.id;
1150 template<class DefList, class UndefList, class T>
1151 void define_inner(DefList& defList, UndefList& undefList, const T& labelId, size_t addrOffset)
1153 // add label
1154 typename DefList::value_type item(labelId, addrOffset);
1155 std::pair<typename DefList::iterator, bool> ret = defList.insert(item);
1156 if (!ret.second) throw Error(ERR_LABEL_IS_REDEFINED);
1157 // search undefined label
1158 for (;;) {
1159 typename UndefList::iterator itr = undefList.find(labelId);
1160 if (itr == undefList.end()) break;
1161 const JmpLabel *jmp = &itr->second;
1162 const size_t offset = jmp->endOfJmp - jmp->jmpSize;
1163 size_t disp;
1164 if (jmp->mode == inner::LaddTop) {
1165 disp = addrOffset;
1166 } else if (jmp->mode == inner::Labs) {
1167 disp = size_t(base_->getCurr());
1168 } else {
1169 disp = addrOffset - jmp->endOfJmp + jmp->disp;
1170#ifdef XBYAK64
1171 if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) throw Error(ERR_OFFSET_IS_TOO_BIG);
1172#endif
1175 if (base_->isAutoGrow()) {
1176 base_->save(offset, disp, jmp->jmpSize, jmp->mode);
1177 } else {
1178 base_->rewrite(offset, disp, jmp->jmpSize);
1180 undefList.erase(itr);
1183 template<class DefList, class T>
1184 bool getOffset_inner(const DefList& defList, size_t *offset, const T& label) const
1186 typename DefList::const_iterator i = defList.find(label);
1187 if (i == defList.end()) return false;
1188 *offset = i->second.offset;
1189 return true;
1191 friend class Label;
1192 void incRefCount(int id) { clabelDefList_[id].refCount++; }
1193 void decRefCount(int id)
1195 ClabelDefList::iterator i = clabelDefList_.find(id);
1196 if (i == clabelDefList_.end()) return;
1197 if (i->second.refCount == 1) {
1198 clabelDefList_.erase(id);
1199 } else {
1200 --i->second.refCount;
1203 template<class T>
1204 bool hasUndefinedLabel_inner(const T& list) const
1206#ifndef NDEBUG
1207 for (typename T::const_iterator i = list.begin(); i != list.end(); ++i) {
1208 std::cerr << "undefined label:" << i->first << std::endl;
1210#endif
1211 return !list.empty();
1213public:
1218 void reset()
1220 base_ = 0;
1221 labelId_ = 1;
1222 stateList_.clear();
1223 stateList_.push_back(SlabelState());
1224 stateList_.push_back(SlabelState());
1225 clabelDefList_.clear();
1226 clabelUndefList_.clear();
1230 stateList_.push_back(SlabelState());
1234 if (stateList_.size() <= 2) throw Error(ERR_UNDER_LOCAL_LABEL);
1235 if (hasUndefinedLabel_inner(stateList_.back().undefList)) throw Error(ERR_LABEL_IS_NOT_FOUND);
1236 stateList_.pop_back();
1238 void set(CodeArray *base) { base_ = base; }
1239 void defineSlabel(std::string label)
1241 if (label == "@b" || label == "@f") throw Error(ERR_BAD_LABEL_STR);
1242 if (label == "@@") {
1243 SlabelDefList& defList = stateList_.front().defList;
1244 SlabelDefList::iterator i = defList.find("@f");
1245 if (i != defList.end()) {
1246 defList.erase(i);
1247 label = "@b";
1248 } else {
1249 i = defList.find("@b");
1250 if (i != defList.end()) {
1251 defList.erase(i);
1253 label = "@f";
1256 SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
1257 define_inner(st.defList, st.undefList, label, base_->getSize());
1261 define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize());
1262 label.mgr = this;
1264 void assign(Label& dst, const Label& src)
1266 ClabelDefList::const_iterator i = clabelDefList_.find(src.id);
1267 if (i == clabelDefList_.end()) throw Error(ERR_LABEL_ISNOT_SET_BY_L);
1268 define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset);
1269 dst.mgr = this;
1271 bool getOffset(size_t *offset, std::string& label) const
1273 const SlabelDefList& defList = stateList_.front().defList;
1274 if (label == "@b") {
1275 if (defList.find("@f") != defList.end()) {
1276 label = "@f";
1277 } else if (defList.find("@b") == defList.end()) {
1280 } else if (label == "@f") {
1281 if (defList.find("@f") != defList.end()) {
1282 label = "@b";
1283 }
1284 }
1285 const SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
1286 return getOffset_inner(st.defList, offset, label);
1287 }
1288 bool getOffset(size_t *offset, const Label& label) const
1289 {
1290 return getOffset_inner(clabelDefList_, offset, getId(label));
1291 }
1292 void addUndefinedLabel(const std::string& label, const JmpLabel& jmp)
1293 {
1294 SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front();
1295 st.undefList.insert(SlabelUndefList::value_type(label, jmp));
1296 }
1297 void addUndefinedLabel(const Label& label, const JmpLabel& jmp)
1298 {
1299 clabelUndefList_.insert(ClabelUndefList::value_type(label.id, jmp));
1300 }
1301 bool hasUndefSlabel() const
1302 {
1303 for (StateList::const_iterator i = stateList_.begin(), ie = stateList_.end(); i != ie; ++i) {
1304 if (hasUndefinedLabel_inner(i->undefList)) return true;
1305 }
1306 return false;
1307 }
1308 bool hasUndefClabel() const { return hasUndefinedLabel_inner(clabelUndefList_); }
1309 const uint8 *getCode() const { return base_->getCode(); }
1310 bool isReady() const { return !base_->isAutoGrow() || base_->isCalledCalcJmpAddress(); }
1311};
1312
1313inline Label::Label(const Label& rhs)
1314{
1315 id = rhs.id;
1316 mgr = rhs.mgr;
1317 if (mgr) mgr->incRefCount(id);
1318}
1319inline Label& Label::operator=(const Label& rhs)
1320{
1321 if (id) throw Error(ERR_LABEL_IS_ALREADY_SET_BY_L);
1322 id = rhs.id;
1323 mgr = rhs.mgr;
1324 if (mgr) mgr->incRefCount(id);
1325 return *this;
1326}
1328{
1329 if (id && mgr) mgr->decRefCount(id);
1330}
1331inline const uint8* Label::getAddress() const
1332{
1333 if (mgr == 0 || !mgr->isReady()) return 0;
1334 size_t offset;
1335 if (!mgr->getOffset(&offset, *this)) return 0;
1336 return mgr->getCode() + offset;
1337}
1338
1339class CodeGenerator : public CodeArray {
1340public:
1344 T_AUTO // T_SHORT if possible
1346private:
1347 CodeGenerator operator=(const CodeGenerator&); // don't call
1348#ifdef XBYAK64
1349 enum { i32e = 32 | 64, BIT = 64 };
1350 static const size_t dummyAddr = (size_t(0x11223344) << 32) | 55667788;
1351 typedef Reg64 NativeReg;
1352#else
1353 enum { i32e = 32, BIT = 32 };
1354 static const size_t dummyAddr = 0x12345678;
1355 typedef Reg32 NativeReg;
1356#endif
1357 // (XMM, XMM|MEM)
1358 static inline bool isXMM_XMMorMEM(const Operand& op1, const Operand& op2)
1359 {
1360 return op1.isXMM() && (op2.isXMM() || op2.isMEM());
1361 }
1362 // (MMX, MMX|MEM) or (XMM, XMM|MEM)
1363 static inline bool isXMMorMMX_MEM(const Operand& op1, const Operand& op2)
1364 {
1365 return (op1.isMMX() && (op2.isMMX() || op2.isMEM())) || isXMM_XMMorMEM(op1, op2);
1366 }
1367 // (XMM, MMX|MEM)
1368 static inline bool isXMM_MMXorMEM(const Operand& op1, const Operand& op2)
1369 {
1370 return op1.isXMM() && (op2.isMMX() || op2.isMEM());
1371 }
1372 // (MMX, XMM|MEM)
1373 static inline bool isMMX_XMMorMEM(const Operand& op1, const Operand& op2)
1374 {
1375 return op1.isMMX() && (op2.isXMM() || op2.isMEM());
1376 }
1377 // (XMM, REG32|MEM)
1378 static inline bool isXMM_REG32orMEM(const Operand& op1, const Operand& op2)
1379 {
1380 return op1.isXMM() && (op2.isREG(i32e) || op2.isMEM());
1381 }
1382 // (REG32, XMM|MEM)
1383 static inline bool isREG32_XMMorMEM(const Operand& op1, const Operand& op2)
1384 {
1385 return op1.isREG(i32e) && (op2.isXMM() || op2.isMEM());
1386 }
1387 // (REG32, REG32|MEM)
1388 static inline bool isREG32_REG32orMEM(const Operand& op1, const Operand& op2)
1389 {
1390 return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM());
1391 }
1392 void rex(const Operand& op1, const Operand& op2 = Operand())
1393 {
1394 uint8 rex = 0;
1395 const Operand *p1 = &op1, *p2 = &op2;
1396 if (p1->isMEM()) std::swap(p1, p2);
1397 if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
1398 if (p2->isMEM()) {
1399 const Address& addr = p2->getAddress();
1400 if (BIT == 64 && addr.is32bit()) db(0x67);
1401 rex = addr.getRex() | p1->getReg().getRex();
1402 } else {
1403 // ModRM(reg, base);
1404 rex = op2.getReg().getRex(op1.getReg());
1405 }
1406 // except movsx(16bit, 32/64bit)
1407 if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66);
1408 if (rex) db(rex);
1409 }
1410 enum AVXtype {
1411 // low 3 bit
1412 T_N1 = 1,
1413 T_N2 = 2,
1414 T_N4 = 3,
1415 T_N8 = 4,
1416 T_N16 = 5,
1417 T_N32 = 6,
1418 T_NX_MASK = 7,
1419 //
1420 T_N_VL = 1 << 3, // N * (1, 2, 4) for VL
1421 T_DUP = 1 << 4, // N = (8, 32, 64)
1422 T_66 = 1 << 5,
1423 T_F3 = 1 << 6,
1424 T_F2 = 1 << 7,
1425 T_0F = 1 << 8,
1426 T_0F38 = 1 << 9,
1427 T_0F3A = 1 << 10,
1428 T_L0 = 1 << 11,
1429 T_L1 = 1 << 12,
1430 T_W0 = 1 << 13,
1431 T_W1 = 1 << 14,
1432 T_EW0 = 1 << 15,
1433 T_EW1 = 1 << 16,
1434 T_YMM = 1 << 17, // support YMM, ZMM
1435 T_EVEX = 1 << 18,
1436 T_ER_X = 1 << 19, // xmm{er}
1437 T_ER_Y = 1 << 20, // ymm{er}
1438 T_ER_Z = 1 << 21, // zmm{er}
1439 T_SAE_X = 1 << 22, // xmm{sae}
1440 T_SAE_Y = 1 << 23, // ymm{sae}
1441 T_SAE_Z = 1 << 24, // zmm{sae}
1442 T_MUST_EVEX = 1 << 25, // contains T_EVEX
1443 T_B32 = 1 << 26, // m32bcst
1444 T_B64 = 1 << 27, // m64bcst
1445 T_M_K = 1 << 28, // mem{k}
1446 T_XXX
1447 };
1448 void vex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false)
1449 {
1450 int w = (type & T_W1) ? 1 : 0;
1451 bool is256 = (type & T_L1) ? true : (type & T_L0) ? false : reg.isYMM();
1452 bool r = reg.isExtIdx();
1453 bool b = base.isExtIdx();
1454 int idx = v ? v->getIdx() : 0;
1455 if ((idx | reg.getIdx() | base.getIdx()) >= 16) throw Error(ERR_BAD_COMBINATION);
1456 uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0;
1457 uint32 vvvv = (((~idx) & 15) << 3) | (is256 ? 4 : 0) | pp;
1458 if (!b && !x && !w && (type & T_0F)) {
1459 db(0xC5); db((r ? 0 : 0x80) | vvvv);
1460 } else {
1461 uint32 mmmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
1462 db(0xC4); db((r ? 0 : 0x80) | (x ? 0 : 0x40) | (b ? 0 : 0x20) | mmmm); db((w << 7) | vvvv);
1463 }
1464 db(code);
1465 }
1466 void verifySAE(const Reg& r, int type) const
1467 {
1468 if (((type & T_SAE_X) && r.isXMM()) || ((type & T_SAE_Y) && r.isYMM()) || ((type & T_SAE_Z) && r.isZMM())) return;
1470 }
1471 void verifyER(const Reg& r, int type) const
1472 {
1473 if (((type & T_ER_X) && r.isXMM()) || ((type & T_ER_Y) && r.isYMM()) || ((type & T_ER_Z) && r.isZMM())) return;
1474 throw Error(ERR_ER_IS_INVALID);
1475 }
1476 // (a, b, c) contains non zero two or three values then err
1477 int verifyDuplicate(int a, int b, int c, int err)
1478 {
1479 int v = a | b | c;
1480 if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) return Error(err);
1481 return v;
1482 }
1483 int evex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false, bool b = false, int aaa = 0, uint32 VL = 0)
1484 {
1485 if (!(type & (T_EVEX | T_MUST_EVEX))) throw Error(ERR_EVEX_IS_INVALID);
1486 int w = (type & T_EW1) ? 1 : 0;
1487 uint32 mm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0;
1488 uint32 pp = (type & T_66) ? 1 : (type & T_F3) ? 2 : (type & T_F2) ? 3 : 0;
1489
1490 int idx = v ? v->getIdx() : 0;
1491 uint32 vvvv = ~idx;
1492
1493 bool R = !reg.isExtIdx();
1494 bool X = x ? false : !base.isExtIdx2();
1495 bool B = !base.isExtIdx();
1496 bool Rp = !reg.isExtIdx2();
1497 int LL;
1498 int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET);
1499 int disp8N = 1;
1500 if (rounding) {
1501 if (rounding == EvexModifierRounding::T_SAE) {
1502 verifySAE(base, type); LL = 0;
1503 } else {
1504 verifyER(base, type); LL = rounding - 1;
1505 }
1506 b = true;
1507 } else {
1508 if (v) VL = (std::max)(VL, v->getBit());
1509 VL = (std::max)((std::max)(reg.getBit(), base.getBit()), VL);
1510 LL = (VL == 512) ? 2 : (VL == 256) ? 1 : 0;
1511 if (b) {
1512 disp8N = (type & T_B32) ? 4 : 8;
1513 } else if (type & T_DUP) {
1514 disp8N = VL == 128 ? 8 : VL == 256 ? 32 : 64;
1515 } else {
1516 if ((type & (T_NX_MASK | T_N_VL)) == 0) {
1517 type |= T_N16 | T_N_VL; // default
1518 }
1519 int low = type & T_NX_MASK;
1520 if (low > 0) {
1521 disp8N = 1 << (low - 1);
1522 if (type & T_N_VL) disp8N *= (VL == 512 ? 4 : VL == 256 ? 2 : 1);
1523 }
1524 }
1525 }
1526 bool Vp = !(v ? v->isExtIdx2() : 0);
1527 bool z = reg.hasZero() || base.hasZero() || (v ? v->hasZero() : false);
1528 if (aaa == 0) aaa = verifyDuplicate(base.getOpmaskIdx(), reg.getOpmaskIdx(), (v ? v->getOpmaskIdx() : 0), ERR_OPMASK_IS_ALREADY_SET);
1529 db(0x62);
1530 db((R ? 0x80 : 0) | (X ? 0x40 : 0) | (B ? 0x20 : 0) | (Rp ? 0x10 : 0) | (mm & 3));
1531 db((w == 1 ? 0x80 : 0) | ((vvvv & 15) << 3) | 4 | (pp & 3));
1532 db((z ? 0x80 : 0) | ((LL & 3) << 5) | (b ? 0x10 : 0) | (Vp ? 8 : 0) | (aaa & 7));
1533 db(code);
1534 return disp8N;
1535 }
1536 void setModRM(int mod, int r1, int r2)
1537 {
1538 db(static_cast<uint8>((mod << 6) | ((r1 & 7) << 3) | (r2 & 7)));
1539 }
1540 void setSIB(const RegExp& e, int reg, int disp8N = 0)
1541 {
1542 size_t disp64 = e.getDisp();
1543#ifdef XBYAK64
1544 size_t high = disp64 >> 32;
1545 if (high != 0 && high != 0xFFFFFFFF) throw Error(ERR_OFFSET_IS_TOO_BIG);
1546#endif
1547 uint32 disp = static_cast<uint32>(disp64);
1548 const Reg& base = e.getBase();
1549 const Reg& index = e.getIndex();
1550 const int baseIdx = base.getIdx();
1551 const int baseBit = base.getBit();
1552 const int indexBit = index.getBit();
1553 enum {
1554 mod00 = 0, mod01 = 1, mod10 = 2
1555 };
1556 int mod = mod10; // disp32
1557 if (!baseBit || ((baseIdx & 7) != Operand::EBP && disp == 0)) {
1558 mod = mod00;
1559 } else {
1560 if (disp8N == 0) {
1561 if (inner::IsInDisp8(disp)) {
1562 mod = mod01;
1564 } else {
1565 // disp must be casted to signed
1566 uint32 t = static_cast<uint32>(static_cast<int>(disp) / disp8N);
1567 if ((disp % disp8N) == 0 && inner::IsInDisp8(t)) {
1568 disp = t;
1569 mod = mod01;
1573 const int newBaseIdx = baseBit ? (baseIdx & 7) : Operand::EBP;
1574 /* ModR/M = [2:3:3] = [Mod:reg/code:R/M] */
1575 bool hasSIB = indexBit || (baseIdx & 7) == Operand::ESP;
1576#ifdef XBYAK64
1577 if (!baseBit && !indexBit) hasSIB = true;
1578#endif
1579 if (hasSIB) {
1580 setModRM(mod, reg, Operand::ESP);
1581 /* SIB = [2:3:3] = [SS:index:base(=rm)] */
1582 const int idx = indexBit ? (index.getIdx() & 7) : Operand::ESP;
1583 const int scale = e.getScale();
1584 const int SS = (scale == 8) ? 3 : (scale == 4) ? 2 : (scale == 2) ? 1 : 0;
1585 setModRM(SS, idx, newBaseIdx);
1586 } else {
1587 setModRM(mod, reg, newBaseIdx);
1588 }
1589 if (mod == mod01) {
1590 db(disp);
1591 } else if (mod == mod10 || (mod == mod00 && !baseBit)) {
1592 dd(disp);
1595 LabelManager labelMgr_;
1596 bool isInDisp16(uint32 x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; }
1597 void opModR(const Reg& reg1, const Reg& reg2, int code0, int code1 = NONE, int code2 = NONE)
1599 rex(reg2, reg1);
1600 db(code0 | (reg1.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
1601 setModRM(3, reg1.getIdx(), reg2.getIdx());
1603 void opModM(const Address& addr, const Reg& reg, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
1606 rex(addr, reg);
1607 db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2);
1608 opAddr(addr, reg.getIdx(), immSize);
1610 void opMIB(const Address& addr, const Reg& reg, int code0, int code1)
1614 if (BIT == 64 && addr.is32bit()) db(0x67);
1615 const RegExp& regExp = addr.getRegExp(false);
1616 uint8 rex = regExp.getRex();
1617 if (rex) db(rex);
1618 db(code0); db(code1);
1619 setSIB(regExp, reg.getIdx());
1621 void makeJmp(uint32 disp, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
1623 const int shortJmpSize = 2;
1624 const int longHeaderSize = longPref ? 2 : 1;
1625 const int longJmpSize = longHeaderSize + 4;
1626 if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) {
1627 db(shortCode); db(disp - shortJmpSize);
1628 } else {
1630 if (longPref) db(longPref);
1631 db(longCode); dd(disp - longJmpSize);
1634 template<class T>
1635 void opJmp(T& label, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref)
1637 if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */
1638 size_t offset = 0;
1639 if (labelMgr_.getOffset(&offset, label)) { /* label exists */
1640 makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref);
1641 } else {
1642 int jmpSize = 0;
1643 if (type == T_NEAR) {
1644 jmpSize = 4;
1645 if (longPref) db(longPref);
1646 db(longCode); dd(0);
1647 } else {
1648 jmpSize = 1;
1649 db(shortCode); db(0);
1655 void opJmpAbs(const void *addr, LabelType type, uint8 shortCode, uint8 longCode, uint8 longPref = 0)
1657 if (isAutoGrow()) {
1659 if (size_ + 16 >= maxSize_) growMemory();
1660 if (longPref) db(longPref);
1661 db(longCode);
1662 dd(0);
1663 save(size_ - 4, size_t(addr) - size_, 4, inner::Labs);
1664 } else {
1665 makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8*>(addr) - getCurr()), type, shortCode, longCode, longPref);
1669 // reg is reg field of ModRM
1670 // immSize is the size for immediate value
1671 // disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement
1672 void opAddr(const Address &addr, int reg, int immSize = 0, int disp8N = 0)
1674 if (addr.getMode() == Address::M_ModRM) {
1675 setSIB(addr.getRegExp(), reg, disp8N);
1676 } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) {
1677 setModRM(0, reg, 5);
1678 if (addr.getLabel()) { // [rip + Label]
1679 putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize);
1680 } else {
1681 size_t disp = addr.getDisp();
1684 disp -= (size_t)getCurr() + 4 + immSize;
1690 /* preCode is for SSSE3/SSE4 */
1691 void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE)
1693 if (isValid && !isValid(reg, op)) throw Error(ERR_BAD_COMBINATION);
1694 if (pref != NONE) db(pref);
1695 if (op.isMEM()) {
1696 opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0);
1697 } else {
1698 opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code);
1700 if (imm8 != NONE) db(imm8);
1702 void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext)
1704 if (mmx.isXMM()) db(0x66);
1705 opModR(Reg32(ext), mmx, 0x0F, code);
1706 db(imm8);
1708 void opMMX(const Mmx& mmx, const Operand& op, int code, int pref = 0x66, int imm8 = NONE, int preCode = NONE)
1710 opGen(mmx, op, code, mmx.isXMM() ? pref : NONE, isXMMorMMX_MEM, imm8, preCode);
1712 void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref)
1714 if (pref != NONE) db(pref);
1715 if (op1.isXMM() && op2.isMEM()) {
1716 opModM(op2.getAddress(), op1.getReg(), 0x0F, code);
1717 } else if (op1.isMEM() && op2.isXMM()) {
1718 opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1);
1719 } else {
1723 void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false)
1725 if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */
1726 if (mmx.isXMM()) db(0x66);
1727 opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm);
1728 } else {
1729 opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A);
1732 void opR_ModM(const Operand& op, int bit, int ext, int code0, int code1 = NONE, int code2 = NONE, bool disableRex = false, int immSize = 0)
1734 int opBit = op.getBit();
1735 if (disableRex && opBit == 64) opBit = 32;
1736 if (op.isREG(bit)) {
1737 opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2);
1738 } else if (op.isMEM()) {
1739 opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize);
1740 } else {
1744 void opShift(const Operand& op, int imm, int ext)
1746 verifyMemHasSize(op);
1747 opR_ModM(op, 0, ext, (0xC0 | ((imm == 1 ? 1 : 0) << 4)), NONE, NONE, false, (imm != 1) ? 1 : 0);
1748 if (imm != 1) db(imm);
1750 void opShift(const Operand& op, const Reg8& _cl, int ext)
1753 opR_ModM(op, 0, ext, 0xD2);
1755 void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0)
1757 if (condR) {
1758 opModR(op1.getReg(), op2.getReg(), code0, code1, code2);
1759 } else if (condM) {
1760 opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize);
1761 } else {
1765 void opShxd(const Operand& op, const Reg& reg, uint8 imm, int code, const Reg8 *_cl = 0)
1767 if (_cl && _cl->getIdx() != Operand::CL) throw Error(ERR_BAD_COMBINATION);
1768 opModRM(reg, op, (op.isREG(16 | i32e) && op.getBit() == reg.getBit()), op.isMEM() && (reg.isREG(16 | i32e)), 0x0F, code | (_cl ? 1 : 0), NONE, _cl ? 0 : 1);
1769 if (!_cl) db(imm);
1771 // (REG, REG|MEM), (MEM, REG)
1772 void opRM_RM(const Operand& op1, const Operand& op2, int code)
1774 if (op1.isREG() && op2.isMEM()) {
1775 opModM(op2.getAddress(), op1.getReg(), code | 2);
1776 } else {
1777 opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code);
1780 // (REG|MEM, IMM)
1781 void opRM_I(const Operand& op, uint32 imm, int code, int ext)
1783 verifyMemHasSize(op);
1784 uint32 immBit = inner::IsInDisp8(imm) ? 8 : isInDisp16(imm) ? 16 : 32;
1785 if (op.isBit(8)) immBit = 8;
1786 if (op.getBit() < immBit) throw Error(ERR_IMM_IS_TOO_BIG);
1787 if (op.isBit(32|64) && immBit == 16) immBit = 32; /* don't use MEM16 if 32/64bit mode */
1788 if (op.isREG() && op.getIdx() == 0 && (op.getBit() == immBit || (op.isBit(64) && immBit == 32))) { // rax, eax, ax, al
1789 rex(op);
1790 db(code | 4 | (immBit == 8 ? 0 : 1));
1791 } else {
1792 int tmp = immBit < (std::min)(op.getBit(), 32U) ? 2 : 0;
1793 opR_ModM(op, 0, ext, 0x80 | tmp, NONE, NONE, false, immBit / 8);
1795 db(imm, immBit / 8);
1797 void opIncDec(const Operand& op, int code, int ext)
1799 verifyMemHasSize(op);
1800#ifndef XBYAK64
1801 if (op.isREG() && !op.isBit(8)) {
1802 rex(op); db(code | op.getIdx());
1803 return;
1805#endif
1806 code = 0xFE;
1807 if (op.isREG()) {
1808 opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code);
1809 } else {
1810 opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
1813 void opPushPop(const Operand& op, int code, int ext, int alt)
1815 if (op.isREG()) {
1816 if (op.isBit(16)) db(0x66);
1817 if (op.getReg().getIdx() >= 8) db(0x41);
1818 db(alt | (op.getIdx() & 7));
1819 } else if (op.isMEM()) {
1820 opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code);
1821 } else {
1825 void verifyMemHasSize(const Operand& op) const
1827 if (op.isMEM() && op.getBit() == 0) throw Error(ERR_MEM_SIZE_IS_NOT_SPECIFIED);
1830 mov(r, imm) = db(imm, mov_imm(r, imm))
1832 int mov_imm(const Reg& reg, size_t imm)
1834 int bit = reg.getBit();
1835 const int idx = reg.getIdx();
1836 int code = 0xB0 | ((bit == 8 ? 0 : 1) << 3);
1837 if (bit == 64 && (imm & ~size_t(0xffffffffu)) == 0) {
1838 rex(Reg32(idx));
1839 bit = 32;
1840 } else {
1841 rex(reg);
1842 if (bit == 64 && inner::IsInInt32(imm)) {
1843 db(0xC7);
1844 code = 0xC0;
1845 bit = 32;
1848 db(code | (idx & 7));
1849 return bit / 8;
1851 template<class T>
1852 void putL_inner(T& label, bool relative = false, size_t disp = 0)
1854 const int jmpSize = relative ? 4 : (int)sizeof(size_t);
1856 size_t offset = 0;
1857 if (labelMgr_.getOffset(&offset, label)) {
1858 if (relative) {
1859 db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize);
1860 } else if (isAutoGrow()) {
1861 db(uint64(0), jmpSize);
1862 save(size_ - jmpSize, offset, jmpSize, inner::LaddTop);
1863 } else {
1864 db(size_t(top_) + offset, jmpSize);
1866 return;
1868 db(uint64(0), jmpSize);
1869 JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp);
1872 void opMovxx(const Reg& reg, const Operand& op, uint8 code)
1874 if (op.isBit(32)) throw Error(ERR_BAD_COMBINATION);
1875 int w = op.isBit(16);
1876#ifdef XBYAK64
1877 if (op.isHigh8bit()) throw Error(ERR_BAD_COMBINATION);
1878#endif
1879 bool cond = reg.isREG() && (reg.getBit() > op.getBit());
1880 opModRM(reg, op, cond && op.isREG(), cond && op.isMEM(), 0x0F, code | w);
1882 void opFpuMem(const Address& addr, uint8 m16, uint8 m32, uint8 m64, uint8 ext, uint8 m64ext)
1885 uint8 code = addr.isBit(16) ? m16 : addr.isBit(32) ? m32 : addr.isBit(64) ? m64 : 0;
1886 if (!code) throw Error(ERR_BAD_MEM_SIZE);
1887 if (m64ext && addr.isBit(64)) ext = m64ext;
1889 rex(addr, st0);
1890 db(code);
1891 opAddr(addr, ext);
1893 // use code1 if reg1 == st0
1894 // use code2 if reg1 != st0 && reg2 == st0
1895 void opFpuFpu(const Fpu& reg1, const Fpu& reg2, uint32 code1, uint32 code2)
1897 uint32 code = reg1.getIdx() == 0 ? code1 : reg2.getIdx() == 0 ? code2 : 0;
1899 db(uint8(code >> 8));
1900 db(uint8(code | (reg1.getIdx() | reg2.getIdx())));
1902 void opFpu(const Fpu& reg, uint8 code1, uint8 code2)
1904 db(code1); db(code2 | reg.getIdx());
1906 void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE)
1908 if (op2.isMEM()) {
1909 const Address& addr = op2.getAddress();
1910 const RegExp& regExp = addr.getRegExp();
1911 const Reg& base = regExp.getBase();
1912 if (BIT == 64 && addr.is32bit()) db(0x67);
1913 int disp8N = 0;
1914 bool x = regExp.getIndex().isExtIdx();
1915 if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) {
1916 int aaa = addr.getOpmaskIdx();
1917 if (aaa && !(type & T_M_K)) throw Error(ERR_INVALID_OPMASK_WITH_MEMORY);
1918 bool b = false;
1919 if (addr.isBroadcast()) {
1920 if (!(type & (T_B32 | T_B64))) throw Error(ERR_INVALID_BROADCAST);
1921 b = true;
1923 int VL = regExp.isVsib() ? regExp.getIndex().getBit() : 0;
1924 disp8N = evex(r, base, p1, type, code, x, b, aaa, VL);
1925 } else {
1926 vex(r, base, p1, type, code, x);
1928 opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N);
1929 } else {
1930 const Reg& base = op2.getReg();
1931 if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) {
1932 evex(r, base, p1, type, code);
1933 } else {
1934 vex(r, base, p1, type, code);
1936 setModRM(3, r.getIdx(), base.getIdx());
1938 if (imm8 != NONE) db(imm8);
1940 // (r, r, r/m) if isR_R_RM
1941 // (r, r/m, r)
1942 void opGpr(const Reg32e& r, const Operand& op1, const Operand& op2, int type, uint8 code, bool isR_R_RM, int imm8 = NONE)
1944 const Operand *p1 = &op1;
1945 const Operand *p2 = &op2;
1946 if (!isR_R_RM) std::swap(p1, p2);
1947 const unsigned int bit = r.getBit();
1948 if (p1->getBit() != bit || (p2->isREG() && p2->getBit() != bit)) throw Error(ERR_BAD_COMBINATION);
1949 type |= (bit == 64) ? T_W1 : T_W0;
1950 opVex(r, p1, *p2, type, code, imm8);
1952 void opAVX_X_X_XM(const Xmm& x1, const Operand& op1, const Operand& op2, int type, int code0, int imm8 = NONE)
1954 const Xmm *x2 = static_cast<const Xmm*>(&op1);
1955 const Operand *op = &op2;
1956 if (op2.isNone()) { // (x1, op1) -> (x1, x1, op1)
1957 x2 = &x1;
1958 op = &op1;
1959 }
1960 // (x1, x2, op)
1961 if (!((x1.isXMM() && x2->isXMM()) || ((type & T_YMM) && ((x1.isYMM() && x2->isYMM()) || (x1.isZMM() && x2->isZMM()))))) throw Error(ERR_BAD_COMBINATION);
1962 opVex(x1, x2, *op, type, code0, imm8);
1963 }
1964 void opAVX_K_X_XM(const Opmask& k, const Xmm& x2, const Operand& op3, int type, int code0, int imm8 = NONE)
1965 {
1966 if (!op3.isMEM() && (x2.getKind() != op3.getKind())) throw Error(ERR_BAD_COMBINATION);
1967 opVex(k, &x2, op3, type, code0, imm8);
1968 }
1969 // (x, x/m), (y, x/m256), (z, y/m)
1970 void checkCvt1(const Operand& x, const Operand& op) const
1971 {
1972 if (!op.isMEM() && !(x.is(Operand::XMM | Operand::YMM) && op.isXMM()) && !(x.isZMM() && op.isYMM())) throw Error(ERR_BAD_COMBINATION);
1973 }
1974 // (x, x/m), (x, y/m256), (y, z/m)
1975 void checkCvt2(const Xmm& x, const Operand& op) const
1976 {
1977 if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) throw Error(ERR_BAD_COMBINATION);
1978 }
1979 void opCvt2(const Xmm& x, const Operand& op, int type, int code)
1980 {
1981 checkCvt2(x, op);
1982 Operand::Kind kind = x.isXMM() ? (op.isBit(256) ? Operand::YMM : Operand::XMM) : Operand::ZMM;
1983 opVex(x.copyAndSetKind(kind), &xm0, op, type, code);
1984 }
1985 void opCvt3(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int type64, int type32, uint8 code)
1986 {
1987 if (!(x1.isXMM() && x2.isXMM() && (op.isREG(i32e) || op.isMEM()))) throw Error(ERR_BAD_SIZE_OF_REGISTER);
1988 Xmm x(op.getIdx());
1989 const Operand *p = op.isREG() ? &x : &op;
1990 opVex(x1, &x2, *p, type | (op.isBit(64) ? type64 : type32), code);
1991 }
1992 const Xmm& cvtIdx0(const Operand& x) const
1993 {
1994 return x.isZMM() ? zm0 : x.isYMM() ? ym0 : xm0;
1995 }
1996 // support (x, x/m, imm), (y, y/m, imm)
1997 void opAVX_X_XM_IMM(const Xmm& x, const Operand& op, int type, int code, int imm8 = NONE)
1998 {
1999 opAVX_X_X_XM(x, cvtIdx0(x), op, type, code, imm8);
2000 }
2001 // QQQ:need to refactor
2002 void opSp1(const Reg& reg, const Operand& op, uint8 pref, uint8 code0, uint8 code1)
2003 {
2004 if (reg.isBit(8)) throw Error(ERR_BAD_SIZE_OF_REGISTER);
2005 bool is16bit = reg.isREG(16) && (op.isREG(16) || op.isMEM());
2006 if (!is16bit && !(reg.isREG(i32e) && (op.isREG(reg.getBit()) || op.isMEM()))) throw Error(ERR_BAD_COMBINATION);
2007 if (is16bit) db(0x66);
2008 db(pref); opModRM(reg.changeBit(i32e == 32 ? 32 : reg.getBit()), op, op.isREG(), true, code0, code1);
2009 }
2010 void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8 code, int mode)
2011 {
2012 const RegExp& regExp = addr.getRegExp();
2013 if (!regExp.isVsib(128 | 256)) throw Error(ERR_BAD_VSIB_ADDRESSING);
2014 const int y_vx_y = 0;
2015 const int y_vy_y = 1;
2016// const int x_vy_x = 2;
2017 const bool isAddrYMM = regExp.getIndex().getBit() == 256;
2018 if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) {
2019 bool isOK = false;
2020 if (mode == y_vx_y) {
2021 isOK = x1.isYMM() && !isAddrYMM && x2.isYMM();
2022 } else if (mode == y_vy_y) {
2023 isOK = x1.isYMM() && isAddrYMM && x2.isYMM();
2024 } else { // x_vy_x
2025 isOK = !x1.isYMM() && isAddrYMM && !x2.isYMM();
2026 }
2027 if (!isOK) throw Error(ERR_BAD_VSIB_ADDRESSING);
2028 }
2029 addr.permitVsib();
2030 opAVX_X_X_XM(isAddrYMM ? Ymm(x1.getIdx()) : x1, isAddrYMM ? Ymm(x2.getIdx()) : x2, addr, type | T_YMM, code);
2031 }
2032 enum {
2033 xx_yy_zz = 0,
2034 xx_yx_zy = 1,
2035 xx_xy_yz = 2
2036 };
2037 void checkGather2(const Xmm& x1, const Reg& x2, int mode) const
2038 {
2039 if (x1.isXMM() && x2.isXMM()) return;
2040 switch (mode) {
2041 case xx_yy_zz: if ((x1.isYMM() && x2.isYMM()) || (x1.isZMM() && x2.isZMM())) return;
2042 break;
2043 case xx_yx_zy: if ((x1.isYMM() && x2.isXMM()) || (x1.isZMM() && x2.isYMM())) return;
2044 break;
2045 case xx_xy_yz: if ((x1.isXMM() && x2.isYMM()) || (x1.isYMM() && x2.isZMM())) return;
2046 break;
2047 }
2049 }
2050 void opGather2(const Xmm& x, const Address& addr, int type, uint8 code, int mode)
2051 {
2052 if (x.hasZero()) throw Error(ERR_INVALID_ZERO);
2053 checkGather2(x, addr.getRegExp().getIndex(), mode);
2054 addr.permitVsib();
2055 opVex(x, 0, addr, type, code);
2056 }
2057 /*
2058 xx_xy_yz ; mode = true
2059 xx_xy_xz ; mode = false
2060 */
2061 void opVmov(const Operand& op, const Xmm& x, int type, uint8 code, bool mode)
2062 {
2063 if (mode) {
2064 if (!op.isMEM() && !((op.isXMM() && x.isXMM()) || (op.isXMM() && x.isYMM()) || (op.isYMM() && x.isZMM()))) throw Error(ERR_BAD_COMBINATION);
2065 } else {
2066 if (!op.isMEM() && !op.isXMM()) throw Error(ERR_BAD_COMBINATION);
2067 }
2068 opVex(x, 0, op, type, code);
2069 }
2070 void opGatherFetch(const Address& addr, const Xmm& x, int type, uint8 code, Operand::Kind kind)
2071 {
2072 if (addr.hasZero()) throw Error(ERR_INVALID_ZERO);
2073 if (addr.getRegExp().getIndex().getKind() != kind) throw Error(ERR_BAD_VSIB_ADDRESSING);
2074 addr.permitVsib();
2075 opVex(x, 0, addr, type, code);
2076 }
2077public:
2078 unsigned int getVersion() const { return VERSION; }
2079 using CodeArray::db;
2080 const Mmx mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
2084 const Xmm &xm0, &xm1, &xm2, &xm3, &xm4, &xm5, &xm6, &xm7;
2085 const Ymm &ym0, &ym1, &ym2, &ym3, &ym4, &ym5, &ym6, &ym7;
2086 const Ymm &zm0, &zm1, &zm2, &zm3, &zm4, &zm5, &zm6, &zm7;
2087 const Reg32 eax, ecx, edx, ebx, esp, ebp, esi, edi;
2088 const Reg16 ax, cx, dx, bx, sp, bp, si, di;
2089 const Reg8 al, cl, dl, bl, ah, ch, dh, bh;
2090 const AddressFrame ptr, byte, word, dword, qword, xword, yword, zword; // xword is same as oword of NASM
2091 const AddressFrame ptr_b, xword_b, yword_b, zword_b; // broadcast such as {1to2}, {1to4}, {1to8}, {1to16}, {b}
2092 const Fpu st0, st1, st2, st3, st4, st5, st6, st7;
2093 const Opmask k0, k1, k2, k3, k4, k5, k6, k7;
2095 const EvexModifierRounding T_sae, T_rn_sae, T_rd_sae, T_ru_sae, T_rz_sae; // {sae}, {rn-sae}, {rd-sae}, {ru-sae}, {rz-sae}
2096 const EvexModifierZero T_z; // {z}
2097#ifdef XBYAK64
2098 const Reg64 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15;
2099 const Reg32 r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d;
2100 const Reg16 r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w;
2101 const Reg8 r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b;
2102 const Reg8 spl, bpl, sil, dil;
2103 const Xmm xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15;
2104 const Xmm xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23;
2105 const Xmm xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31;
2106 const Ymm ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15;
2107 const Ymm ymm16, ymm17, ymm18, ymm19, ymm20, ymm21, ymm22, ymm23;
2108 const Ymm ymm24, ymm25, ymm26, ymm27, ymm28, ymm29, ymm30, ymm31;
2109 const Zmm zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15;
2110 const Zmm zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23;
2111 const Zmm zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31;
2112 const Xmm &xm8, &xm9, &xm10, &xm11, &xm12, &xm13, &xm14, &xm15; // for my convenience
2113 const Xmm &xm16, &xm17, &xm18, &xm19, &xm20, &xm21, &xm22, &xm23;
2114 const Xmm &xm24, &xm25, &xm26, &xm27, &xm28, &xm29, &xm30, &xm31;
2115 const Ymm &ym8, &ym9, &ym10, &ym11, &ym12, &ym13, &ym14, &ym15;
2116 const Ymm &ym16, &ym17, &ym18, &ym19, &ym20, &ym21, &ym22, &ym23;
2117 const Ymm &ym24, &ym25, &ym26, &ym27, &ym28, &ym29, &ym30, &ym31;
2118 const Zmm &zm8, &zm9, &zm10, &zm11, &zm12, &zm13, &zm14, &zm15;
2119 const Zmm &zm16, &zm17, &zm18, &zm19, &zm20, &zm21, &zm22, &zm23;
2120 const Zmm &zm24, &zm25, &zm26, &zm27, &zm28, &zm29, &zm30, &zm31;
2121 const RegRip rip;
2122#endif
2123#ifndef XBYAK_DISABLE_SEGMENT
2124 const Segment es, cs, ss, ds, fs, gs;
2125#endif
2126 void L(const std::string& label) { labelMgr_.defineSlabel(label); }
2127 void L(const Label& label) { labelMgr_.defineClabel(label); }
2128 void inLocalLabel() { labelMgr_.enterLocal(); }
2129 void outLocalLabel() { labelMgr_.leaveLocal(); }
2130 /*
2131 assign src to dst
2132 require
2133 dst : does not used by L()
2134 src : used by L()
2135 */
2136 void assignL(Label& dst, const Label& src) { labelMgr_.assign(dst, src); }
2137 /*
2138 put address of label to buffer
2139 @note the put size is 4(32-bit), 8(64-bit)
2140 */
2141 void putL(std::string label) { putL_inner(label); }
2142 void putL(const Label& label) { putL_inner(label); }
2143
2144 void jmp(const Operand& op) { opR_ModM(op, BIT, 4, 0xFF, NONE, NONE, true); }
2145 void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
2146 void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); }
2147 void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); }
2148 void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); }
2149
2150 void call(const Operand& op) { opR_ModM(op, 16 | i32e, 2, 0xFF, NONE, NONE, true); }
2151 // call(string label), not const std::string&
2152 void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
2153 void call(const char *label) { call(std::string(label)); }
2154 void call(const Label& label) { opJmp(label, T_NEAR, 0, 0xE8, 0); }
2155 // call(function pointer)
2156#ifdef XBYAK_VARIADIC_TEMPLATE
2157 template<class Ret, class... Params>
2158 void call(Ret(*func)(Params...)) { call(CastTo<const void*>(func)); }
2159#endif
2160 void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); }
2161
2162 void test(const Operand& op, const Reg& reg)
2163 {
2164 opModRM(reg, op, op.isREG() && (op.getKind() == reg.getKind()), op.isMEM(), 0x84);
2165 }
2166 void test(const Operand& op, uint32 imm)
2167 {
2168 verifyMemHasSize(op);
2169 int immSize = (std::min)(op.getBit() / 8, 4U);
2170 if (op.isREG() && op.getIdx() == 0) { // al, ax, eax
2171 rex(op);
2172 db(0xA8 | (op.isBit(8) ? 0 : 1));
2173 } else {
2174 opR_ModM(op, 0, 0, 0xF6, NONE, NONE, false, immSize);
2175 }
2176 db(imm, immSize);
2177 }
2178 void imul(const Reg& reg, const Operand& op)
2179 {
2180 opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x0F, 0xAF);
2181 }
2182 void imul(const Reg& reg, const Operand& op, int imm)
2183 {
2184 int s = inner::IsInDisp8(imm) ? 1 : 0;
2185 int immSize = s ? 1 : reg.isREG(16) ? 2 : 4;
2186 opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x69 | (s << 1), NONE, NONE, immSize);
2187 db(imm, immSize);
2188 }
2189 void push(const Operand& op) { opPushPop(op, 0xFF, 6, 0x50); }
2190 void pop(const Operand& op) { opPushPop(op, 0x8F, 0, 0x58); }
2191 void push(const AddressFrame& af, uint32 imm)
2192 {
2193 if (af.bit_ == 8 && inner::IsInDisp8(imm)) {
2194 db(0x6A); db(imm);
2195 } else if (af.bit_ == 16 && isInDisp16(imm)) {
2196 db(0x66); db(0x68); dw(imm);
2197 } else {
2198 db(0x68); dd(imm);
2199 }
2200 }
2201 /* use "push(word, 4)" if you want "push word 4" */
2202 void push(uint32 imm)
2203 {
2204 if (inner::IsInDisp8(imm)) {
2205 push(byte, imm);
2206 } else {
2207 push(dword, imm);
2208 }
2209 }
2210 void mov(const Operand& reg1, const Operand& reg2)
2211 {
2212 const Reg *reg = 0;
2213 const Address *addr = 0;
2214 uint8 code = 0;
2215 if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp]
2216 reg = &reg1.getReg();
2217 addr= &reg2.getAddress();
2218 code = 0xA0;
2219 } else
2220 if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al
2221 reg = &reg2.getReg();
2222 addr= &reg1.getAddress();
2223 code = 0xA2;
2224 }
2225#ifdef XBYAK64
2226 if (addr && addr->is64bitDisp()) {
2227 if (code) {
2228 rex(*reg);
2229 db(reg1.isREG(8) ? 0xA0 : reg1.isREG() ? 0xA1 : reg2.isREG(8) ? 0xA2 : 0xA3);
2230 db(addr->getDisp(), 8);
2231 } else {
2233 }
2234 } else
2235#else
2236 if (code && addr->isOnlyDisp()) {
2237 rex(*reg, *addr);
2238 db(code | (reg->isBit(8) ? 0 : 1));
2239 dd(static_cast<uint32>(addr->getDisp()));
2240 } else
2241#endif
2242 {
2243 opRM_RM(reg1, reg2, 0x88);
2244 }
2245 }
2246 void mov(const Operand& op, size_t imm)
2247 {
2248 if (op.isREG()) {
2249 const int size = mov_imm(op.getReg(), imm);
2250 db(imm, size);
2251 } else if (op.isMEM()) {
2252 verifyMemHasSize(op);
2253 int immSize = op.getBit() / 8;
2254 if (immSize <= 4) {
2255 sint64 s = sint64(imm) >> (immSize * 8);
2256 if (s != 0 && s != -1) throw Error(ERR_IMM_IS_TOO_BIG);
2257 } else {
2258 if (!inner::IsInInt32(imm)) throw Error(ERR_IMM_IS_TOO_BIG);
2259 immSize = 4;
2260 }
2261 opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize);
2262 db(static_cast<uint32>(imm), immSize);
2263 } else {
2265 }
2266 }
2267 void mov(const NativeReg& reg, const char *label) // can't use std::string
2268 {
2269 if (label == 0) {
2270 mov(static_cast<const Operand&>(reg), 0); // call imm
2271 return;
2272 }
2273 mov_imm(reg, dummyAddr);
2274 putL(label);
2275 }
2276 void mov(const NativeReg& reg, const Label& label)
2277 {
2278 mov_imm(reg, dummyAddr);
2279 putL(label);
2280 }
2281 void xchg(const Operand& op1, const Operand& op2)
2282 {
2283 const Operand *p1 = &op1, *p2 = &op2;
2284 if (p1->isMEM() || (p2->isREG(16 | i32e) && p2->getIdx() == 0)) {
2285 p1 = &op2; p2 = &op1;
2286 }
2287 if (p1->isMEM()) throw Error(ERR_BAD_COMBINATION);
2288 if (p2->isREG() && (p1->isREG(16 | i32e) && p1->getIdx() == 0)
2289#ifdef XBYAK64
2290 && (p2->getIdx() != 0 || !p1->isREG(32))
2291#endif
2292 ) {
2293 rex(*p2, *p1); db(0x90 | (p2->getIdx() & 7));
2294 return;
2295 }
2296 opModRM(*p1, *p2, (p1->isREG() && p2->isREG() && (p1->getBit() == p2->getBit())), p2->isMEM(), 0x86 | (p1->isBit(8) ? 0 : 1));
2297 }
2298
2299#ifndef XBYAK_DISABLE_SEGMENT
2300 void push(const Segment& seg)
2301 {
2302 switch (seg.getIdx()) {
2303 case Segment::es: db(0x06); break;
2304 case Segment::cs: db(0x0E); break;
2305 case Segment::ss: db(0x16); break;
2306 case Segment::ds: db(0x1E); break;
2307 case Segment::fs: db(0x0F); db(0xA0); break;
2308 case Segment::gs: db(0x0F); db(0xA8); break;
2309 default:
2310 assert(0);
2311 }
2312 }
2313 void pop(const Segment& seg)
2314 {
2315 switch (seg.getIdx()) {
2316 case Segment::es: db(0x07); break;
2318 case Segment::ss: db(0x17); break;
2319 case Segment::ds: db(0x1F); break;
2320 case Segment::fs: db(0x0F); db(0xA1); break;
2321 case Segment::gs: db(0x0F); db(0xA9); break;
2322 default:
2323 assert(0);
2324 }
2325 }
2326 void putSeg(const Segment& seg)
2327 {
2328 switch (seg.getIdx()) {
2329 case Segment::es: db(0x2E); break;
2330 case Segment::cs: db(0x36); break;
2331 case Segment::ss: db(0x3E); break;
2332 case Segment::ds: db(0x26); break;
2333 case Segment::fs: db(0x64); break;
2334 case Segment::gs: db(0x65); break;
2335 default:
2336 assert(0);
2337 }
2338 }
2339 void mov(const Operand& op, const Segment& seg)
2340 {
2341 opModRM(Reg8(seg.getIdx()), op, op.isREG(16|i32e), op.isMEM(), 0x8C);
2342 }
2343 void mov(const Segment& seg, const Operand& op)
2344 {
2345 opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E);
2346 }
2347#endif
2348
2349 enum { NONE = 256 };
2350 // constructor
2351 CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0)
2352 : CodeArray(maxSize, userPtr, allocator)
2353 , mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7)
2354 , xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7)
2355 , ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7)
2356 , zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7)
2357 // for my convenience
2358 , xm0(xmm0), xm1(xmm1), xm2(xmm2), xm3(xmm3), xm4(xmm4), xm5(xmm5), xm6(xmm6), xm7(xmm7)
2359 , ym0(ymm0), ym1(ymm1), ym2(ymm2), ym3(ymm3), ym4(ymm4), ym5(ymm5), ym6(ymm6), ym7(ymm7)
2360 , zm0(zmm0), zm1(zmm1), zm2(zmm2), zm3(zmm3), zm4(zmm4), zm5(zmm5), zm6(zmm6), zm7(zmm7)
2361
2362 , eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI)
2363 , ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI)
2364 , al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH)
2365 , ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512)
2366 , ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true)
2367 , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7)
2368 , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7)
2369 , bnd0(0), bnd1(1), bnd2(2), bnd3(3)
2371 , T_z()
2372#ifdef XBYAK64
2373 , rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15)
2374 , r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15)
2375 , r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15)
2376 , r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15)
2377 , spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true)
2378 , xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15)
2379 , xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23)
2380 , xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31)
2381 , ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15)
2382 , ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23)
2383 , ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31)
2384 , zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15)
2385 , zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23)
2386 , zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31)
2387 // for my convenience
2388 , xm8(xmm8), xm9(xmm9), xm10(xmm10), xm11(xmm11), xm12(xmm12), xm13(xmm13), xm14(xmm14), xm15(xmm15)
2389 , xm16(xmm16), xm17(xmm17), xm18(xmm18), xm19(xmm19), xm20(xmm20), xm21(xmm21), xm22(xmm22), xm23(xmm23)
2390 , xm24(xmm24), xm25(xmm25), xm26(xmm26), xm27(xmm27), xm28(xmm28), xm29(xmm29), xm30(xmm30), xm31(xmm31)
2391 , ym8(ymm8), ym9(ymm9), ym10(ymm10), ym11(ymm11), ym12(ymm12), ym13(ymm13), ym14(ymm14), ym15(ymm15)
2392 , ym16(ymm16), ym17(ymm17), ym18(ymm18), ym19(ymm19), ym20(ymm20), ym21(ymm21), ym22(ymm22), ym23(ymm23)
2393 , ym24(ymm24), ym25(ymm25), ym26(ymm26), ym27(ymm27), ym28(ymm28), ym29(ymm29), ym30(ymm30), ym31(ymm31)
2394 , zm8(zmm8), zm9(zmm9), zm10(zmm10), zm11(zmm11), zm12(zmm12), zm13(zmm13), zm14(zmm14), zm15(zmm15)
2395 , zm16(zmm16), zm17(zmm17), zm18(zmm18), zm19(zmm19), zm20(zmm20), zm21(zmm21), zm22(zmm22), zm23(zmm23)
2396 , zm24(zmm24), zm25(zmm25), zm26(zmm26), zm27(zmm27), zm28(zmm28), zm29(zmm29), zm30(zmm30), zm31(zmm31)
2397 , rip()
2398#endif
2399#ifndef XBYAK_DISABLE_SEGMENT
2401#endif
2402 {
2403 labelMgr_.set(this);
2404 }
2405 void reset()
2406 {
2407 resetSize();
2408 labelMgr_.reset();
2409 labelMgr_.set(this);
2410 }
2411 bool hasUndefinedLabel() const { return labelMgr_.hasUndefSlabel() || labelMgr_.hasUndefClabel(); }
2412 /*
2413 MUST call ready() to complete generating code if you use AutoGrow mode.
2414 It is not necessary for the other mode if hasUndefinedLabel() is true.
2415 */
2416 void ready()
2417 {
2419 if (isAutoGrow()) calcJmpAddress();
2420 }
2421#ifdef XBYAK_TEST
2422 void dump(bool doClear = true)
2423 {
2425 if (doClear) size_ = 0;
2426 }
2427#endif
2428
2429#ifdef XBYAK_UNDEF_JNL
2430 #undef jnl
2431#endif
2432
2433 /*
2434 use single byte nop if useMultiByteNop = false
2435 */
2436 void nop(size_t size = 1, bool useMultiByteNop = true)
2437 {
2438 if (!useMultiByteNop) {
2439 for (size_t i = 0; i < size; i++) {
2440 db(0x90);
2441 }
2442 return;
2443 }
2444 /*
2445 Intel Architectures Software Developer's Manual Volume 2
2446 recommended multi-byte sequence of NOP instruction
2447 AMD and Intel seem to agree on the same sequences for up to 9 bytes:
2448 https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf
2449 */
2450 static const uint8 nopTbl[9][9] = {
2451 {0x90},
2452 {0x66, 0x90},
2453 {0x0F, 0x1F, 0x00},
2454 {0x0F, 0x1F, 0x40, 0x00},
2455 {0x0F, 0x1F, 0x44, 0x00, 0x00},
2456 {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00},
2457 {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00},
2458 {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
2459 {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00},
2460 };
2461 const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]);
2462 while (size > 0) {
2463 size_t len = (std::min)(n, size);
2464 const uint8 *seq = nopTbl[len - 1];
2465 db(seq, len);
2466 size -= len;
2467 }
2468 }
2469
2470#ifndef XBYAK_DONT_READ_LIST
2471#include "xbyak_mnemonic.h"
2472 /*
2473 use single byte nop if useMultiByteNop = false
2474 */
2475 void align(size_t x = 16, bool useMultiByteNop = true)
2476 {
2477 if (x == 1) return;
2478 if (x < 1 || (x & (x - 1))) throw Error(ERR_BAD_ALIGN);
2479 if (isAutoGrow() && x > inner::ALIGN_PAGE_SIZE) fprintf(stderr, "warning:autoGrow mode does not support %d align\n", (int)x);
2480 size_t remain = size_t(getCurr()) % x;
2481 if (remain) {
2482 nop(x - remain, useMultiByteNop);
2483 }
2484 }
2485#endif
2486};
2487
2488namespace util {
2489static const Mmx mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7);
2490static const Xmm xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7);
2491static const Ymm ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7);
2492static const Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7);
2496static const AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512);
2497static const AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true);
2498static const Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7);
2499static const Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7);
2500static const BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3);
2502static const EvexModifierZero T_z;
2503#ifdef XBYAK64
2504static const Reg64 rax(Operand::RAX), rcx(Operand::RCX), rdx(Operand::RDX), rbx(Operand::RBX), rsp(Operand::RSP), rbp(Operand::RBP), rsi(Operand::RSI), rdi(Operand::RDI), r8(Operand::R8), r9(Operand::R9), r10(Operand::R10), r11(Operand::R11), r12(Operand::R12), r13(Operand::R13), r14(Operand::R14), r15(Operand::R15);
2505static const Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15);
2506static const Reg16 r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15);
2507static const Reg8 r8b(8), r9b(9), r10b(10), r11b(11), r12b(12), r13b(13), r14b(14), r15b(15), spl(Operand::SPL, true), bpl(Operand::BPL, true), sil(Operand::SIL, true), dil(Operand::DIL, true);
2508static const Xmm xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15);
2509static const Xmm xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23);
2510static const Xmm xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31);
2511static const Ymm ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15);
2512static const Ymm ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23);
2513static const Ymm ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31);
2514static const Zmm zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15);
2515static const Zmm zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23);
2516static const Zmm zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31);
2517static const RegRip rip;
2518#endif
2519#ifndef XBYAK_DISABLE_SEGMENT
2521#endif
2522} // util
2523
2524#ifdef _MSC_VER
2525 #pragma warning(pop)
2526#endif
2527
2528} // end of namespace
2529
2530#endif // XBYAK_XBYAK_H_
AVXtype
Definition avx_type.hpp:3
@ T_0F
Definition avx_type.hpp:18
const CBigNum operator+(const CBigNum &a, const CBigNum &b)
Definition base58.cpp:429
const CBigNum operator-(const CBigNum &a, const CBigNum &b)
Definition base58.cpp:437
const mie::Vuint & p
Definition bn.cpp:27
const mie::Vuint & r
Definition bn.cpp:28
Operand
Definition calc2.cpp:28
Error
Definition calc.cpp:23
AddressFrame(uint32 bit, bool broadcast=false)
Definition xbyak.h:1062
Address operator[](const void *disp) const
Definition xbyak.h:1067
const uint32 bit_
Definition xbyak.h:1060
Address operator[](const RegExp &e) const
Definition xbyak.h:1063
const bool broadcast_
Definition xbyak.h:1061
size_t getDisp() const
Definition xbyak.h:1020
bool operator==(const Address &rhs) const
Definition xbyak.h:1030
RegExp getRegExp(bool optimize=true) const
Definition xbyak.h:1013
Mode getMode() const
Definition xbyak.h:1017
Address(uint32 sizeBit, bool broadcast, const RegExp &e)
Definition xbyak.h:1001
uint8 getRex() const
Definition xbyak.h:1021
bool isOnlyDisp() const
Definition xbyak.h:1019
void permitVsib() const
Definition xbyak.h:1012
bool isBroadcast() const
Definition xbyak.h:1028
bool is64bitDisp() const
Definition xbyak.h:1027
bool operator!=(const Address &rhs) const
Definition xbyak.h:1034
const Label * getLabel() const
Definition xbyak.h:1029
bool is32bit() const
Definition xbyak.h:1018
void db(uint64 code, size_t codeSize)
Definition xbyak.h:897
size_t size_
Definition xbyak.h:825
void save(size_t offset, size_t val, int size, inner::LabelMode mode)
Definition xbyak.h:953
bool isCalledCalcJmpAddress() const
Definition xbyak.h:958
void setSize(size_t size)
Definition xbyak.h:912
void db(const uint8 *code, size_t codeSize)
Definition xbyak.h:893
const F getCurr() const
Definition xbyak.h:910
bool isAutoGrow() const
Definition xbyak.h:957
void dump() const
Definition xbyak.h:917
size_t getSize() const
Definition xbyak.h:911
void dw(uint32 code)
Definition xbyak.h:902
const F getCode() const
Definition xbyak.h:907
uint8 * top_
Definition xbyak.h:824
void db(int code)
Definition xbyak.h:882
void rewrite(size_t offset, uint64 disp, size_t size)
Definition xbyak.h:944
const uint8 * getCode() const
Definition xbyak.h:905
void growMemory()
Definition xbyak.h:831
size_t maxSize_
Definition xbyak.h:823
virtual ~CodeArray()
Definition xbyak.h:869
static uint8 * getAlignedAddress(uint8 *addr, size_t alignedSize=16)
Definition xbyak.h:987
void dq(uint64 code)
Definition xbyak.h:904
bool isCalledCalcJmpAddress_
Definition xbyak.h:826
CodeArray(size_t maxSize, void *userPtr=0, Allocator *allocator=0)
Definition xbyak.h:855
void resetSize()
Definition xbyak.h:876
void dd(uint32 code)
Definition xbyak.h:903
static bool protect(const void *addr, size_t size, bool canExec)
Definition xbyak.h:966
void calcJmpAddress()
Definition xbyak.h:844
const uint8 * getCurr() const
Definition xbyak.h:908
const Ymm & zm3
Definition xbyak.h:2086
void jmp(std::string label, LabelType type=T_AUTO)
Definition xbyak.h:2145
void call(const Operand &op)
Definition xbyak.h:2150
const AddressFrame zword
Definition xbyak.h:2090
const Xmm & xm1
Definition xbyak.h:2084
const Xmm & xm5
Definition xbyak.h:2084
void call(const Label &label)
Definition xbyak.h:2154
const Opmask k3
Definition xbyak.h:2093
const Ymm & zm2
Definition xbyak.h:2086
void test(const Operand &op, uint32 imm)
Definition xbyak.h:2166
const EvexModifierRounding T_sae
Definition xbyak.h:2095
const Xmm & xm3
Definition xbyak.h:2084
const Opmask k7
Definition xbyak.h:2093
const AddressFrame ptr_b
Definition xbyak.h:2091
CodeGenerator(size_t maxSize=DEFAULT_MAX_CODE_SIZE, void *userPtr=0, Allocator *allocator=0)
Definition xbyak.h:2351
void jmp(const char *label, LabelType type=T_AUTO)
Definition xbyak.h:2146
const EvexModifierRounding T_rd_sae
Definition xbyak.h:2095
const Reg16 sp
Definition xbyak.h:2088
const Xmm & xm6
Definition xbyak.h:2084
void call(const void *addr)
Definition xbyak.h:2160
const AddressFrame xword_b
Definition xbyak.h:2091
const BoundsReg bnd2
Definition xbyak.h:2094
const BoundsReg bnd1
Definition xbyak.h:2094
const Ymm & zm7
Definition xbyak.h:2086
const Xmm & xm2
Definition xbyak.h:2084
const Reg8 cl
Definition xbyak.h:2089
const BoundsReg bnd0
Definition xbyak.h:2094
const AddressFrame xword
Definition xbyak.h:2090
const Reg16 cx
Definition xbyak.h:2088
const Reg8 dh
Definition xbyak.h:2089
const Reg8 al
Definition xbyak.h:2089
const EvexModifierRounding T_rz_sae
Definition xbyak.h:2095
const Opmask k0
Definition xbyak.h:2093
const Xmm & xm7
Definition xbyak.h:2084
void align(size_t x=16, bool useMultiByteNop=true)
Definition xbyak.h:2475
const Ymm & zm0
Definition xbyak.h:2086
void imul(const Reg &reg, const Operand &op)
Definition xbyak.h:2178
void putSeg(const Segment &seg)
Definition xbyak.h:2326
const Reg32 esp
Definition xbyak.h:2087
const Reg32 eax
Definition xbyak.h:2087
const AddressFrame dword
Definition xbyak.h:2090
const Xmm & xm0
Definition xbyak.h:2084
void jmp(const Operand &op)
Definition xbyak.h:2144
void xchg(const Operand &op1, const Operand &op2)
Definition xbyak.h:2281
void call(std::string label)
Definition xbyak.h:2152
const BoundsReg bnd3
Definition xbyak.h:2094
const Reg16 di
Definition xbyak.h:2088
void pop(const Segment &seg)
Definition xbyak.h:2313
void push(uint32 imm)
Definition xbyak.h:2202
const Reg32 ecx
Definition xbyak.h:2087
void mov(const Operand &op, const Segment &seg)
Definition xbyak.h:2339
const AddressFrame byte
Definition xbyak.h:2090
const Segment cs
Definition xbyak.h:2124
void test(const Operand &op, const Reg &reg)
Definition xbyak.h:2162
bool hasUndefinedLabel() const
Definition xbyak.h:2411
const Ymm & zm4
Definition xbyak.h:2086
const Reg32 ebp
Definition xbyak.h:2087
const Ymm & ym4
Definition xbyak.h:2085
const Ymm & ym7
Definition xbyak.h:2085
const Opmask k5
Definition xbyak.h:2093
const EvexModifierRounding T_ru_sae
Definition xbyak.h:2095
void mov(const Operand &op, size_t imm)
Definition xbyak.h:2246
const Reg32 ebx
Definition xbyak.h:2087
const Ymm & ym0
Definition xbyak.h:2085
void mov(const NativeReg &reg, const char *label)
Definition xbyak.h:2267
const EvexModifierRounding T_rn_sae
Definition xbyak.h:2095
void db(int code)
Definition xbyak.h:882
const Segment ss
Definition xbyak.h:2124
void push(const AddressFrame &af, uint32 imm)
Definition xbyak.h:2191
const AddressFrame yword_b
Definition xbyak.h:2091
void call(const char *label)
Definition xbyak.h:2153
const Reg8 ah
Definition xbyak.h:2089
const Reg32 edi
Definition xbyak.h:2087
const Segment ds
Definition xbyak.h:2124
const EvexModifierZero T_z
Definition xbyak.h:2096
void nop(size_t size=1, bool useMultiByteNop=true)
Definition xbyak.h:2436
const Reg16 si
Definition xbyak.h:2088
const Opmask k4
Definition xbyak.h:2093
void mov(const Segment &seg, const Operand &op)
Definition xbyak.h:2343
const Opmask k6
Definition xbyak.h:2093
const Xmm & xm4
Definition xbyak.h:2084
const AddressFrame qword
Definition xbyak.h:2090
void push(const Segment &seg)
Definition xbyak.h:2300
const Reg32 edx
Definition xbyak.h:2087
const Ymm & ym1
Definition xbyak.h:2085
const Ymm & zm1
Definition xbyak.h:2086
const AddressFrame word
Definition xbyak.h:2090
void mov(const Operand &reg1, const Operand &reg2)
Definition xbyak.h:2210
const Segment fs
Definition xbyak.h:2124
const Segment es
Definition xbyak.h:2124
const Opmask k2
Definition xbyak.h:2093
void pop(const Operand &op)
Definition xbyak.h:2190
const Ymm & ym3
Definition xbyak.h:2085
void mov(const NativeReg &reg, const Label &label)
Definition xbyak.h:2276
const Reg16 dx
Definition xbyak.h:2088
const Reg16 bx
Definition xbyak.h:2088
const AddressFrame zword_b
Definition xbyak.h:2091
void assignL(Label &dst, const Label &src)
Definition xbyak.h:2136
const Reg32 esi
Definition xbyak.h:2087
const Ymm & zm5
Definition xbyak.h:2086
const Reg8 ch
Definition xbyak.h:2089
const Segment gs
Definition xbyak.h:2124
void imul(const Reg &reg, const Operand &op, int imm)
Definition xbyak.h:2182
const Ymm & ym5
Definition xbyak.h:2085
const AddressFrame yword
Definition xbyak.h:2090
void L(const std::string &label)
Definition xbyak.h:2126
void putL(const Label &label)
Definition xbyak.h:2142
const Opmask k1
Definition xbyak.h:2093
const Reg8 bl
Definition xbyak.h:2089
void jmp(const Label &label, LabelType type=T_AUTO)
Definition xbyak.h:2147
const Ymm & ym6
Definition xbyak.h:2085
void push(const Operand &op)
Definition xbyak.h:2189
unsigned int getVersion() const
Definition xbyak.h:2078
const Reg8 bh
Definition xbyak.h:2089
void jmp(const void *addr, LabelType type=T_AUTO)
Definition xbyak.h:2148
const Ymm & zm6
Definition xbyak.h:2086
const Reg16 bp
Definition xbyak.h:2088
const Reg16 ax
Definition xbyak.h:2088
void L(const Label &label)
Definition xbyak.h:2127
const Ymm & ym2
Definition xbyak.h:2085
const Reg8 dl
Definition xbyak.h:2089
void putL(std::string label)
Definition xbyak.h:2141
const AddressFrame ptr
Definition xbyak.h:2090
Error(int err)
Definition xbyak.h:187
const char * what() const
Definition xbyak.h:195
int getId() const
Definition xbyak.h:1099
static std::string toStr(int num)
Definition xbyak.h:1103
const uint8 * getAddress() const
Definition xbyak.h:1331
Label & operator=(const Label &rhs)
Definition xbyak.h:1319
void defineSlabel(std::string label)
Definition xbyak.h:1239
bool hasUndefSlabel() const
Definition xbyak.h:1301
bool isReady() const
Definition xbyak.h:1310
void addUndefinedLabel(const std::string &label, const JmpLabel &jmp)
Definition xbyak.h:1292
bool hasUndefClabel() const
Definition xbyak.h:1308
bool getOffset(size_t *offset, std::string &label) const
Definition xbyak.h:1271
void assign(Label &dst, const Label &src)
Definition xbyak.h:1264
void defineClabel(const Label &label)
Definition xbyak.h:1259
bool getOffset(size_t *offset, const Label &label) const
Definition xbyak.h:1288
void set(CodeArray *base)
Definition xbyak.h:1238
const uint8 * getCode() const
Definition xbyak.h:1309
void addUndefinedLabel(const Label &label, const JmpLabel &jmp)
Definition xbyak.h:1297
bool isExtIdx2() const
Definition xbyak.h:414
bool isYMEM() const
Definition xbyak.h:405
bool isExt8bit() const
Definition xbyak.h:412
int getRounding() const
Definition xbyak.h:419
Kind getKind() const
Definition xbyak.h:397
bool isOPMASK() const
Definition xbyak.h:407
bool isREG(int bit=0) const
Definition xbyak.h:409
bool isFPU() const
Definition xbyak.h:411
bool isMMX() const
Definition xbyak.h:400
const Address & getAddress() const
Definition xbyak.h:1044
bool is(int kind, uint32 bit=0) const
Definition xbyak.h:448
void setRounding(int idx)
Definition xbyak.h:433
bool isYMM() const
Definition xbyak.h:402
bool operator==(const Operand &rhs) const
Definition xbyak.h:1050
bool isXMM() const
Definition xbyak.h:401
void setIdx(int idx)
Definition xbyak.h:362
bool isZMM() const
Definition xbyak.h:403
const char * toString() const
Definition xbyak.h:454
int getIdx() const
Definition xbyak.h:398
bool isHigh8bit() const
Definition xbyak.h:440
void setOpmaskIdx(int idx, bool ignore_idx0=false)
Definition xbyak.h:427
int getOpmaskIdx() const
Definition xbyak.h:418
bool isEqualIfNotInherited(const Operand &rhs) const
Definition xbyak.h:502
bool hasEvex() const
Definition xbyak.h:415
bool isXMEM() const
Definition xbyak.h:404
bool isBit(uint32 bit) const
Definition xbyak.h:452
uint32 getBit() const
Definition xbyak.h:453
void setBit(int bit)
Definition xbyak.h:426
bool isMEM(int bit=0) const
Definition xbyak.h:410
bool operator!=(const Operand &rhs) const
Definition xbyak.h:504
unsigned int mask_
Definition xbyak.h:360
bool isBNDREG() const
Definition xbyak.h:408
void setZero()
Definition xbyak.h:438
bool hasZero() const
Definition xbyak.h:417
bool isExtIdx() const
Definition xbyak.h:413
bool isZMEM() const
Definition xbyak.h:406
unsigned int rounding_
Definition xbyak.h:361
void setKind(Kind kind)
Definition xbyak.h:420
const Reg & getReg() const
Definition xbyak.h:540
bool hasRex() const
Definition xbyak.h:416
unsigned int zero_
Definition xbyak.h:359
bool isNone() const
Definition xbyak.h:399
const Reg & getBase() const
Definition xbyak.h:726
friend RegExp operator-(const RegExp &e, size_t disp)
Definition xbyak.h:780
RegExp(size_t disp=0)
Definition xbyak.h:697
int getScale() const
Definition xbyak.h:728
size_t getDisp() const
Definition xbyak.h:729
uint8 getRex() const
Definition xbyak.h:740
RegExp optimize() const
Definition xbyak.h:712
bool operator==(const RegExp &rhs) const
Definition xbyak.h:722
friend RegExp operator+(const RegExp &a, const RegExp &b)
Definition xbyak.h:756
bool isVsib(int bit=128|256|512) const
Definition xbyak.h:711
RegExp(const Reg &r, int scale=1)
Definition xbyak.h:698
void verify() const
Definition xbyak.h:730
const Reg & getIndex() const
Definition xbyak.h:727
Reg8 cvt8() const
Definition xbyak.h:637
Reg changeBit(int bit) const
Definition xbyak.h:521
uint8 getRexX() const
Definition xbyak.h:524
uint8 getRex(const Reg &base=Reg()) const
Definition xbyak.h:526
uint8 getRexW() const
Definition xbyak.h:522
uint8 getRexR() const
Definition xbyak.h:523
Reg16 cvt16() const
Definition xbyak.h:647
uint8 getRexB() const
Definition xbyak.h:525
Reg32 cvt32() const
Definition xbyak.h:654
int getIdx() const
Definition xbyak.h:679
const char * toString() const
Definition xbyak.h:680
Segment(int idx)
Definition xbyak.h:678
uint64_t id
Definition code_cache.cpp:0
const struct Ptn tbl[]
const uint64 ZMM
Definition make_512.cpp:85
const uint64 EAX
Definition make_512.cpp:16
const uint64 AL
Definition make_512.cpp:25
const uint64 AX
Definition make_512.cpp:24
const uint64 CL
Definition make_nm.cpp:33
const uint64 RAX
Definition make_nm.cpp:62
uint32 VerifyInInt32(uint64 x)
Definition xbyak.h:290
bool IsInInt32(uint64 x)
Definition xbyak.h:288
bool IsInDisp8(uint32 x)
Definition xbyak.h:287
static const Zmm zmm6(6)
static const Segment gs(Segment::gs)
static const Zmm zmm1(1)
static const Mmx mm7(7)
static const EvexModifierRounding T_rd_sae(EvexModifierRounding::T_RD_SAE)
static const Reg8 dl(Operand::DL)
static const Mmx mm1(1)
static const Fpu st1(1)
static const Segment fs(Segment::fs)
static const AddressFrame yword(256)
static const Fpu st7(7)
static const Fpu st5(5)
static const Xmm xmm7(7)
static const Ymm ymm2(2)
static const Xmm xmm1(1)
static const AddressFrame zword_b(512, true)
static const Reg32 ebp(Operand::EBP)
static const Reg8 ch(Operand::CH)
static const Opmask k6(6)
static const Ymm ymm1(1)
static const Fpu st6(6)
static const Mmx mm5(5)
static const Opmask k7(7)
static const Fpu st3(3)
static const Xmm xmm6(6)
static const Mmx mm2(2)
static const Reg32 esp(Operand::ESP)
static const Segment ds(Segment::ds)
static const Reg16 dx(Operand::DX)
static const EvexModifierRounding T_rn_sae(EvexModifierRounding::T_RN_SAE)
static const Reg8 ah(Operand::AH)
static const Reg32 ecx(Operand::ECX)
static const EvexModifierRounding T_rz_sae(EvexModifierRounding::T_RZ_SAE)
static const Opmask k3(3)
static const Mmx mm4(4)
static const Reg32 edi(Operand::EDI)
static const Segment ss(Segment::ss)
static const Reg32 edx(Operand::EDX)
static const AddressFrame dword(32)
static const AddressFrame xword_b(128, true)
static const AddressFrame qword(64)
static const Zmm zmm2(2)
static const Reg16 di(Operand::DI)
static const Ymm ymm3(3)
static const Mmx mm6(6)
static const Ymm ymm6(6)
static const Fpu st4(4)
static const BoundsReg bnd2(2)
static const Reg16 si(Operand::SI)
static const Reg8 dh(Operand::DH)
static const Zmm zmm7(7)
static const Xmm xmm5(5)
static const BoundsReg bnd3(3)
static const Reg16 sp(Operand::SP)
static const AddressFrame xword(128)
static const Zmm zmm4(4)
static const Reg8 bh(Operand::BH)
static const Opmask k4(4)
static const AddressFrame byte(8)
static const Reg16 bp(Operand::BP)
static const Reg16 cx(Operand::CX)
static const Ymm ymm7(7)
static const Reg32 ebx(Operand::EBX)
static const Xmm xmm2(2)
static const Reg8 bl(Operand::BL)
static const BoundsReg bnd1(1)
static const Opmask k2(2)
static const Reg8 cl(Operand::CL)
static const EvexModifierRounding T_ru_sae(EvexModifierRounding::T_RU_SAE)
static const Mmx mm3(3)
static const AddressFrame zword(512)
static const Reg16 bx(Operand::BX)
static const Ymm ymm5(5)
static const Xmm xmm3(3)
static const Ymm ymm4(4)
static const Reg32 esi(Operand::ESI)
static const Xmm xmm4(4)
static const AddressFrame yword_b(256, true)
static const Fpu st2(2)
static const Zmm zmm5(5)
static const Opmask k1(1)
static const AddressFrame word(16)
static const Segment cs(Segment::cs)
static const Opmask k5(5)
static const Zmm zmm3(3)
Definition xbyak.h:104
@ ERR_MEM_SIZE_IS_NOT_SPECIFIED
Definition xbyak.h:154
@ ERR_NONE
Definition xbyak.h:137
@ ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW
Definition xbyak.h:160
@ ERR_BAD_PROTECT_MODE
Definition xbyak.h:161
@ ERR_INVALID_BROADCAST
Definition xbyak.h:176
@ ERR_CANT_ALLOC
Definition xbyak.h:159
@ ERR_BAD_LABEL_STR
Definition xbyak.h:168
@ ERR_BAD_SIZE_OF_REGISTER
Definition xbyak.h:143
@ ERR_BAD_SCALE
Definition xbyak.h:140
@ ERR_BAD_VSIB_ADDRESSING
Definition xbyak.h:164
@ ERR_CANT_CONVERT
Definition xbyak.h:165
@ ERR_OPMASK_IS_ALREADY_SET
Definition xbyak.h:170
@ ERR_ROUNDING_IS_ALREADY_SET
Definition xbyak.h:171
@ ERR_INTERNAL
Definition xbyak.h:181
@ ERR_SAE_IS_INVALID
Definition xbyak.h:174
@ ERR_BAD_PNUM
Definition xbyak.h:162
@ ERR_OFFSET_IS_TOO_BIG
Definition xbyak.h:153
@ ERR_BAD_ADDRESSING
Definition xbyak.h:138
@ ERR_LABEL_ISNOT_SET_BY_L
Definition xbyak.h:166
@ ERR_BAD_MEM_SIZE
Definition xbyak.h:155
@ ERR_CODE_ISNOT_COPYABLE
Definition xbyak.h:149
@ ERR_LABEL_IS_REDEFINED
Definition xbyak.h:146
@ ERR_ER_IS_INVALID
Definition xbyak.h:175
@ ERR_LABEL_IS_TOO_FAR
Definition xbyak.h:147
@ ERR_CANT_PROTECT
Definition xbyak.h:151
@ ERR_INVALID_ZERO
Definition xbyak.h:178
@ ERR_CANT_USE_64BIT_DISP
Definition xbyak.h:152
@ ERR_INVALID_MIB_ADDRESS
Definition xbyak.h:180
@ ERR_BAD_ST_COMBINATION
Definition xbyak.h:156
@ ERR_EVEX_IS_INVALID
Definition xbyak.h:173
@ ERR_BAD_ALIGN
Definition xbyak.h:145
@ ERR_LABEL_IS_ALREADY_SET_BY_L
Definition xbyak.h:167
@ ERR_IMM_IS_TOO_BIG
Definition xbyak.h:144
@ ERR_BAD_TNUM
Definition xbyak.h:163
@ ERR_K0_IS_INVALID
Definition xbyak.h:172
@ ERR_OVER_LOCAL_LABEL
Definition xbyak.h:157
@ ERR_BAD_PARAMETER
Definition xbyak.h:150
@ ERR_INVALID_OPMASK_WITH_MEMORY
Definition xbyak.h:177
@ ERR_ESP_CANT_BE_INDEX
Definition xbyak.h:141
@ ERR_MUNMAP
Definition xbyak.h:169
@ ERR_BAD_COMBINATION
Definition xbyak.h:142
@ ERR_CODE_IS_TOO_BIG
Definition xbyak.h:139
@ ERR_LABEL_IS_NOT_FOUND
Definition xbyak.h:148
@ ERR_INVALID_RIP_IN_AUTO_GROW
Definition xbyak.h:179
@ ERR_UNDER_LOCAL_LABEL
Definition xbyak.h:158
const char * ConvertErrorToString(const Error &err)
Definition xbyak.h:249
RegExp operator-(const RegExp &e, size_t disp)
Definition xbyak.h:780
@ VERSION
Definition xbyak.h:108
@ DEFAULT_MAX_CODE_SIZE
Definition xbyak.h:107
RegExp operator*(const Reg &r, int scale)
Definition xbyak.h:776
uint64_t uint64
Definition xbyak.h:117
unsigned short uint16
Definition xbyak.h:121
void AlignedFree(void *p)
Definition xbyak.h:267
unsigned int uint32
Definition xbyak.h:120
int64_t sint64
Definition xbyak.h:118
T operator|(const T &x, const Opmask &k)
Definition xbyak.h:597
void * AlignedMalloc(size_t size, size_t alignment)
Definition xbyak.h:254
RegExp operator+(const RegExp &a, const RegExp &b)
Definition xbyak.h:756
void *const AutoGrow
Definition xbyak.h:788
const To CastTo(From p)
Definition xbyak.h:279
Definition name.hpp:106
void swap(picojson::value &x, picojson::value &y)
unsigned char uint8
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
#define T(meth, val, expected)
Xbyak::uint32 uint32
Definition quantize.cpp:52
_W64 unsigned int uintptr_t
Definition stdint.h:165
signed __int64 int64_t
Definition stdint.h:135
unsigned __int64 uint64_t
Definition stdint.h:136
Definition bench.cpp:18
Definition lib.h:4
Definition lib.h:43
virtual uint8 * alloc(size_t size)
Definition xbyak.h:310
virtual bool useProtect() const
Definition xbyak.h:314
virtual ~Allocator()
Definition xbyak.h:312
virtual void free(uint8 *p)
Definition xbyak.h:311
BoundsReg(int idx=0)
Definition xbyak.h:594
EvexModifierRounding(int rounding)
Definition xbyak.h:566
Fpu(int idx=0)
Definition xbyak.h:602
size_t disp
Definition xbyak.h:1081
size_t endOfJmp
Definition xbyak.h:1078
inner::LabelMode mode
Definition xbyak.h:1080
JmpLabel(size_t endOfJmp=0, int jmpSize=0, inner::LabelMode mode=inner::LasIs, size_t disp=0)
Definition xbyak.h:1082
Mmx(int idx=0, Kind kind=Operand::MMX, int bit=64)
Definition xbyak.h:555
Opmask(int idx=0)
Definition xbyak.h:590
Reg16(int idx=0)
Definition xbyak.h:551
Reg32(int idx=0)
Definition xbyak.h:609
Reg32e(int idx, int bit)
Definition xbyak.h:606
Reg8(int idx=0, bool ext8bit=false)
Definition xbyak.h:547
Xmm(int idx=0, Kind kind=Operand::XMM, int bit=128)
Definition xbyak.h:572
Xmm copyAndSetIdx(int idx) const
Definition xbyak.h:575
Xmm operator|(const EvexModifierRounding &emr) const
Definition xbyak.h:574
Xmm copyAndSetKind(Operand::Kind kind) const
Definition xbyak.h:576
Ymm(int idx=0, Kind kind=Operand::YMM, int bit=256)
Definition xbyak.h:580
Ymm operator|(const EvexModifierRounding &emr) const
Definition xbyak.h:581
Zmm(int idx=0)
Definition xbyak.h:585
Zmm operator|(const EvexModifierRounding &emr) const
Definition xbyak.h:586
#define R
#define XBYAK_STD_UNORDERED_MULTIMAP
Definition xbyak.h:64
#define XBYAK_STD_UNORDERED_MAP
Definition xbyak.h:63
int bit
Definition yubihsm.h:566
char * label
CK_RV ret
char * s
uint16_t j
size_t len
uint8_t buf[2048]
int seq