diff options
| author | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2022-12-08 17:45:55 -0500 |
|---|---|---|
| committer | Hanjie Wu <hanjiew@andrew.cmu.edu> | 2022-12-08 17:45:55 -0500 |
| commit | a054755b62e660d3d8aba42fdb0a992e2d215599 (patch) | |
| tree | 5f2e793527f75240800b31025f4c4c1f58be23ab | |
JIT implementation
729 files changed, 17174 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..767d53a --- /dev/null +++ b/.clang-format @@ -0,0 +1,226 @@ +--- +Language: Cpp +# BasedOnStyle: Chromium +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignArrayOfStructures: None +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: false +BraceWrapping: + AfterCaseLabel: false + AfterClass: false + AfterControlStatement: Never + AfterEnum: false + AfterFunction: false + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Attach +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +QualifierAlignment: Leave +CompactNamespaces: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: false +DisableFormat: false +EmptyLineAfterAccessModifier: Never +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +PackConstructorInitializers: NextLine +BasedOnStyle: '' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +AllowAllConstructorInitializersOnNextLine: true +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IfMacros: + - KJ_IF_MAYBE +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^<ext/.*\.h>' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentAccessModifiers: false +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 2 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +LambdaBodyIndentation: Signature +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakOpenParenthesis: 0 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Left +PPIndentWidth: -1 +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: pb + BasedOnStyle: google +ReferenceAlignment: Pointer +ReflowComments: true +RemoveBracesLLVM: false +SeparateDefinitionBlocks: Leave +ShortNamespaceLines: 1 +SortIncludes: CaseSensitive +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeParensOptions: + AfterControlStatements: true + AfterForeachMacros: true + AfterFunctionDefinitionName: false + AfterFunctionDeclarationName: false + AfterIfMacros: true + AfterOverloadedOperator: false + BeforeNonEmptyParentheses: false +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: Never +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInLineCommentPrefix: + Minimum: 1 + Maximum: -1 +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementAttributeLikeMacros: + - Q_EMIT +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 8 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c36729f --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.o +weerun +.vscode +xbyak_github +.gdb_history diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fa6909a --- /dev/null +++ b/Makefile @@ -0,0 +1,33 @@ +.PHONY: all clean + +CC = gcc +CXX = g++ + +ifdef DEBUG + OPT = -g -O0 +else + OPT = -O3 +endif + +CFLAGS = $(OPT) -Wall +CXXFLAGS = $(OPT) -Wall -std=c++11 -Wno-extern-c-compat -I. + +all: weerun + +clean: + rm -f weerun *.o + +test: weerun + ./weerun -test + +#weerun: vm.h weerun.c common.h common.c ir.c weewasm.h illegal.h weerun.hpp weerun_dis.cpp weerun_inst.cpp weerun_parse.cpp weerun_runtime.cpp +# cc -g -O0 -Wall -c weerun.c common.c ir.c +# c++ -g -O0 -Wall -std=c++11 -Wno-extern-c-compat -o weerun -I. \ +# weerun.o common.o ir.o \ +# weerun_dis.cpp weerun_inst.cpp weerun_parse.cpp weerun_jit.cpp weerun_runtime.cpp +# +weeify: vm.h weeify.c common.h common.c weewasm.h illegal.h + cc -o weeify weeify.c common.c + +weerun: weerun.o common.o ir.o weerun_dis.o weerun_inst.o weerun_jit.o weerun_parse.o weerun_runtime.o + $(CXX) -o $@ $^ diff --git a/common.c b/common.c new file mode 100644 index 0000000..3ed85b0 --- /dev/null +++ b/common.c @@ -0,0 +1,143 @@ +#include <stdlib.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <stdio.h> + +#include "common.h" + +// The global trace flag +int g_trace = 0; +// The global disassembly flag +int g_disassemble = 0; +// The global indentation amount +int g_indent = 0; + +#define MORE(b) (((b) & 0x80) != 0) +#define ERROR (len != NULL ? *len = -(ptr - start) : 0), 0 + +#define BODY(type, mask, legal) \ + const uint8_t* start = ptr; \ + type result = 0, shift = 0; \ + while (ptr < limit) { \ + uint8_t b = *ptr; \ + ptr++; \ + result = result | (((type)b & 0x7F) << shift); \ + shift += 7; \ + if (shift > (8*sizeof(type))) { \ + if (MORE(b) != 0) return ERROR; /* overlong */ \ + uint8_t upper = b & mask; \ + if (upper != 0 && upper != legal) return ERROR; /* out of range */ \ + if (len != NULL) *len = (ptr - start); \ + return result; \ + } \ + if (MORE(b)) continue; \ + type rem = ((8*sizeof(type)) - shift); \ + if (len != NULL) *len = (ptr - start); \ + return ((0x7F & mask) == legal) ? (result << rem) >> rem : result; \ + } \ + return ERROR; + +int32_t decode_i32leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) { + BODY(int32_t, 0xF8, 0x78); +} + +uint32_t decode_u32leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) { + BODY(uint32_t, 0xF8, 0x08); +} + +int64_t decode_i64leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) { + BODY(int64_t, 0xFF, 0x7F); +} + +uint64_t decode_u64leb(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) { + BODY(int64_t, 0xFF, 0x01); +} + +uint32_t decode_u32(const uint8_t* ptr, const uint8_t* limit, ssize_t *len) { + ssize_t remain = limit - ptr; + if (remain < 4) { + if (remain > 0) *len = -remain; + else *len = remain; + return 0; + } + uint32_t b0 = ptr[0]; + uint32_t b1 = ptr[1]; + uint32_t b2 = ptr[2]; + uint32_t b3 = ptr[3]; + *len = 4; + return (b3 << 24) | (b2 << 16) | (b1 << 8) | b0; +} + +ssize_t load_file(const char* path, uint8_t** start, uint8_t** end) { + // Open the file for reading. + int fd = open(path, O_RDONLY); + if (fd < 0) return fd; + + // Query the size of the file in bytes. + struct stat statbuf; + int r = fstat(fd, &statbuf); + if (r < 0) { // stat call failed. + close(fd); + return r; + } + + // Reject overly large files. + off_t size = statbuf.st_size; + if (size > MAX_FILE_SIZE) { // too large. + close(fd); + return -1; + } + + // Allocate memory to store the bytes. + *start = (uint8_t*)malloc(size); + *end = *start + size; + off_t remain = size; + // Read the bytes from the file until done. + for (uint8_t* p = *start; remain > 0; ) { + r = read(fd, p, remain); + if (r < 0) { // reading failed. + close(fd); + return -2; + } + remain -= r; + p += r; + } + return (int)size; +} + +// Read an unsigned 32-bit LEB, advancing the buffer. +uint32_t read_u32leb(buffer_t* buf) { + ssize_t leblen = 0; + if (buf->ptr >= buf->end) return 0; + uint32_t val = decode_u32leb(buf->ptr, buf->end, &leblen); + if (leblen <= 0) buf->ptr = buf->end; // force failure + else buf->ptr += leblen; + return val; +} + +// Read a signed 32-bit LEB, advancing the buffer. +int32_t read_i32leb(buffer_t* buf) { + ssize_t leblen = 0; + if (buf->ptr >= buf->end) return 0; + int32_t val = decode_i32leb(buf->ptr, buf->end, &leblen); + if (leblen <= 0) buf->ptr = buf->end; // force failure + else buf->ptr += leblen; + return val; +} + +// Read an unsigned 8-bit byte, advancing the buffer. +uint32_t read_u8(buffer_t* buf) { + if (buf->ptr >= buf->end) return 0; + byte val = *buf->ptr; + buf->ptr++; + return val; +} + + +ssize_t unload_file(uint8_t** start, uint8_t** end) { + free(*start); + *start = NULL; + *end = NULL; + return 0; +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..7616b67 --- /dev/null +++ b/common.h @@ -0,0 +1,54 @@ +#pragma once +#include <stdint.h> + +typedef uint8_t byte; + +// Limit file size to something reasonable. +#define MAX_FILE_SIZE 2000000000 + +// Decode LEB128 values, enforcing the specified signedness and maximum range. +// The argument {ptr} will be advanced to point after the decoded value. +// If an error occurs (e.g. unterminated LEB, invalid value), {ptr} will be set to +// NULL. +int32_t decode_i32leb(const byte* ptr, const byte* limit, ssize_t* len); +uint32_t decode_u32leb(const byte* ptr, const byte* limit, ssize_t* len); +int64_t decode_i64leb(const byte* ptr, const byte* limit, ssize_t* len); +uint64_t decode_u64leb(const byte* ptr, const byte* limit, ssize_t* len); + +// Decode fixed-size integer values. +uint32_t decode_u32(const byte* ptr, const byte* limit, ssize_t* len); + +// Load a file into memory, initializing pointers to the start and end of +// the memory range containing the data. Returns < 0 on failure. +ssize_t load_file(const char* path, byte** start, byte** end); + +// Unload a file previously loaded into memory using {load_file}. +ssize_t unload_file(byte** start, byte** end); + +// The global trace flag. +extern int g_trace; +extern int g_disassemble; +extern int g_indent; + +// Helper macros to trace and to print errors. +#define TRACE(...) do { if(g_trace) fprintf(stderr, __VA_ARGS__); } while(0) +#define TRACE_INDENT(...) do { for (int i = 0; i < g_indent; i++) fprintf(stderr, " "); TRACE(__VA_ARGS__); } while(0) +#define DISASS(...) do { if(g_disassemble) fprintf(stderr, __VA_ARGS__); } while(0) +#define ERR(...) fprintf(stderr, __VA_ARGS__) + +// A helper struct that keeps track of the start and the current pointer of +// a buffer. +typedef struct { + const byte* start; + const byte* ptr; + const byte* end; +} buffer_t; + +// Read an unsigned 32-bit LEB, advancing the {ptr} in the buffer. +uint32_t read_u32leb(buffer_t* buf); + +// Read a signed 32-bit LEB, advancing the {ptr} in the buffer. +int32_t read_i32leb(buffer_t* buf); + +// Read an unsigned 8-bit byte, advancing the {ptr} in the buffer. +uint32_t read_u8(buffer_t* buf); diff --git a/disass.c b/disass.c new file mode 100644 index 0000000..cc65495 --- /dev/null +++ b/disass.c @@ -0,0 +1,431 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#include "common.h" +#include "vm.h" +#include "test.h" +#include "weewasm.h" +#include "illegal.h" +#include "ir.h" +#include "disass.h" + +#define OUT(...) fprintf(stdout, __VA_ARGS__) + +// Returns the string name of a section code. +const char* section_name(byte code) { + switch (code) { + case WASM_SECT_TYPE: return "type"; + case WASM_SECT_IMPORT: return "import"; + case WASM_SECT_FUNCTION: return "function"; + case WASM_SECT_TABLE: return "table"; + case WASM_SECT_MEMORY: return "memory"; + case WASM_SECT_GLOBAL: return "global"; + case WASM_SECT_EXPORT: return "export"; + case WASM_SECT_START: return "start"; + case WASM_SECT_ELEMENT: return "element"; + case WASM_SECT_CODE: return "code"; + case WASM_SECT_DATA: return "data"; + case 0: return "custom"; + default: + return "unknown"; + } +} + +// Returns a constant that represents the type code. +const char* type_name(uint32_t code) { + switch (code) { + case WASM_TYPE_I32: return "i32"; + case WASM_TYPE_I64: return "<!illegal i64>"; + case WASM_TYPE_F32: return "<!illegal f32>"; + case WASM_TYPE_F64: return "f64"; + case WASM_TYPE_V128: return "<!illegal v128>"; + case WASM_TYPE_EXTERNREF: return "externref"; + case WASM_TYPE_FUNCREF: return "funcref"; + default: return "<!unknown type>"; + } +} + +// Returns a constant that represents a type declaration code. +const char* type_decl_name(uint32_t code) { + if (code == 0x60) return "sig"; + else return "<!unknown type decl>"; +} + +// Returns the name of an import kind. +const char* import_kind_name(uint32_t code) { + switch (code) { + case WASM_IMPORT_FUNC: return "func"; + case WASM_IMPORT_TABLE: return "table"; + case WASM_IMPORT_MEMORY: return "memory"; + case WASM_IMPORT_GLOBAL: return "global"; + default: return "<!unknown import kind>"; + } +} + +// Prints data as hexadecimal. +void print_data(buffer_t* buf, uint32_t count) { + OUT("\n"); + for (uint32_t i = 0; i < count && buf->ptr < buf->end; i++) { + byte b = read_u8(buf); + OUT(" %02X", b); + if (i % 16 == 15) OUT("\n"); + } + OUT("\n"); +} + +// Metadata for disassembling bytecode. +typedef struct { + const char* mnemonic; + int immkind; + int illegal; +} opcode_imm_t; + +#define IMM_NONE 0 +#define IMM_BLOCKT 1 +#define IMM_LABEL 2 +#define IMM_LABELS 3 +#define IMM_FUNC 4 +#define IMM_SIG_TABLE 5 +#define IMM_LOCAL 6 +#define IMM_GLOBAL 7 +#define IMM_TABLE 8 +#define IMM_MEMARG 9 +#define IMM_I32 10 +#define IMM_F64 11 +#define IMM_MEMORY 12 +#define IMM_TAG 13 +#define IMM_I64 14 +#define IMM_F32 15 +#define IMM_REFNULLT 16 +#define IMM_VALTS 17 +#define IMM_PCDELTA 18 +#define IMM_PCDELTAS 19 + +opcode_imm_t opcode_imm_table[256] = { + [WASM_OP_UNREACHABLE] = {"unreachable" }, + [WASM_OP_NOP] = {"nop" }, + [WASM_OP_BLOCK] = {"block", IMM_BLOCKT }, + [WASM_OP_LOOP] = {"loop", IMM_BLOCKT }, + [WASM_OP_IF] = {"if", IMM_BLOCKT }, + [WASM_OP_ELSE] = {"else" }, + [WASM_OP_END] = {"end" }, + [WASM_OP_BR] = {"br", IMM_LABEL }, + [WASM_OP_BR_IF] = {"br_if", IMM_LABEL }, + [WASM_OP_BR_TABLE] = {"br_table", IMM_LABELS }, + [WASM_OP_RETURN] = {"return" }, + [WASM_OP_CALL] = {"call", IMM_FUNC }, + [WASM_OP_CALL_INDIRECT] = {"call_indirect", IMM_SIG_TABLE }, + [WASM_OP_DROP] = {"drop" }, + [WASM_OP_SELECT] = {"select" }, + [WASM_OP_LOCAL_GET] = {"local.get", IMM_LOCAL }, + [WASM_OP_LOCAL_SET] = {"local.set", IMM_LOCAL }, + [WASM_OP_LOCAL_TEE] = {"local.tee", IMM_LOCAL }, + [WASM_OP_GLOBAL_GET] = {"global.get", IMM_GLOBAL }, + [WASM_OP_GLOBAL_SET] = {"global.set", IMM_GLOBAL }, + [WASM_OP_TABLE_GET] = {"table.get", IMM_TABLE }, + [WASM_OP_TABLE_SET] = {"table.set", IMM_TABLE }, + [WASM_OP_I32_LOAD] = {"i32.load", IMM_MEMARG }, + [WASM_OP_F64_LOAD] = {"f64.load", IMM_MEMARG }, + [WASM_OP_I32_LOAD8_S] = {"i32.load8_s", IMM_MEMARG }, + [WASM_OP_I32_LOAD8_U] = {"i32.load8_u", IMM_MEMARG }, + [WASM_OP_I32_LOAD16_S] = {"i32.load16_s", IMM_MEMARG }, + [WASM_OP_I32_LOAD16_U] = {"i32.load16_u", IMM_MEMARG }, + [WASM_OP_I32_STORE] = {"i32.store", IMM_MEMARG }, + [WASM_OP_F64_STORE] = {"f64.store", IMM_MEMARG }, + [WASM_OP_I32_STORE8] = {"i32.store8", IMM_MEMARG }, + [WASM_OP_I32_STORE16] = {"i32.store16", IMM_MEMARG }, + [WASM_OP_I32_CONST] = {"i32.const", IMM_I32 }, + [WASM_OP_F64_CONST] = {"f64.const", IMM_F64 }, + [WASM_OP_I32_EQZ] = {"i32.eqz" }, + [WASM_OP_I32_EQ] = {"i32.eq" }, + [WASM_OP_I32_NE] = {"i32.ne" }, + [WASM_OP_I32_LT_S] = {"i32.lt_s" }, + [WASM_OP_I32_LT_U] = {"i32.lt_u" }, + [WASM_OP_I32_GT_S] = {"i32.gt_s" }, + [WASM_OP_I32_GT_U] = {"i32.gt_u" }, + [WASM_OP_I32_LE_S] = {"i32.le_s" }, + [WASM_OP_I32_LE_U] = {"i32.le_u" }, + [WASM_OP_I32_GE_S] = {"i32.ge_s" }, + [WASM_OP_I32_GE_U] = {"i32.ge_u" }, + [WASM_OP_F64_EQ] = {"f64.eq" }, + [WASM_OP_F64_NE] = {"f64.ne" }, + [WASM_OP_F64_LT] = {"f64.lt" }, + [WASM_OP_F64_GT] = {"f64.gt" }, + [WASM_OP_F64_LE] = {"f64.le" }, + [WASM_OP_F64_GE] = {"f64.ge" }, + [WASM_OP_I32_CLZ] = {"i32.clz" }, + [WASM_OP_I32_CTZ] = {"i32.ctz" }, + [WASM_OP_I32_POPCNT] = {"i32.popcnt" }, + [WASM_OP_I32_ADD] = {"i32.add" }, + [WASM_OP_I32_SUB] = {"i32.sub" }, + [WASM_OP_I32_MUL] = {"i32.mul" }, + [WASM_OP_I32_DIV_S] = {"i32.div_s" }, + [WASM_OP_I32_DIV_U] = {"i32.div_u" }, + [WASM_OP_I32_REM_S] = {"i32.rem_s" }, + [WASM_OP_I32_REM_U] = {"i32.rem_u" }, + [WASM_OP_I32_AND] = {"i32.and" }, + [WASM_OP_I32_OR] = {"i32.or" }, + [WASM_OP_I32_XOR] = {"i32.xor" }, + [WASM_OP_I32_SHL] = {"i32.shl" }, + [WASM_OP_I32_SHR_S] = {"i32.shr_s" }, + [WASM_OP_I32_SHR_U] = {"i32.shr_u" }, + [WASM_OP_I32_ROTL] = {"i32.rotl" }, + [WASM_OP_I32_ROTR] = {"i32.rotr" }, + [WASM_OP_F64_ADD] = {"f64.add" }, + [WASM_OP_F64_SUB] = {"f64.sub" }, + [WASM_OP_F64_MUL] = {"f64.mul" }, + [WASM_OP_F64_DIV] = {"f64.div" }, + [WASM_OP_I32_TRUNC_F64_S] = {"i32.trunc_f64_s" }, + [WASM_OP_I32_TRUNC_F64_U] = {"i32.trunc_f64_u" }, + [WASM_OP_F64_CONVERT_I32_S] = {"f64.convert_i32_s" }, + [WASM_OP_F64_CONVERT_I32_U] = {"f64.convert_i32_u" }, + [WASM_OP_I32_EXTEND8_S] = {"i32.extend8_s" }, + [WASM_OP_I32_EXTEND16_S] = {"i32.extend16_s" }, + [WASM_OP_JMP] = {"jmp", IMM_PCDELTA }, + [WASM_OP_JMP_IF] = {"jmp_if", IMM_PCDELTA }, + [WASM_OP_JMP_TABLE] = {"jmp_table", IMM_PCDELTAS }, + // illegal bytecodes + [WASM_OP_TRY] = {"try", IMM_BLOCKT, -1}, + [WASM_OP_CATCH] = {"catch", IMM_TAG, -1}, + [WASM_OP_THROW] = {"throw", IMM_TAG, -1}, + [WASM_OP_RETHROW] = {"rethrow", IMM_NONE, -1}, + [WASM_OP_RETURN_CALL] = {"return_call", IMM_FUNC, -1}, + [WASM_OP_RETURN_CALL_INDIRECT]= {"return_call_indirect", IMM_SIG_TABLE, -1}, + [WASM_OP_CALL_REF] = {"call_ref", IMM_NONE, -1}, + [WASM_OP_RETURN_CALL_REF] = {"return_call_ref", IMM_NONE, -1}, + [WASM_OP_DELEGATE] = {"delegate", IMM_NONE, -1}, + [WASM_OP_CATCH_ALL] = {"catch_all", IMM_NONE, -1}, + [WASM_OP_SELECT_T] = {"select", IMM_VALTS, -1}, + [WASM_OP_I64_LOAD] = {"i64.load", IMM_MEMARG, -1}, + [WASM_OP_F32_LOAD] = {"f32.load", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD8_S] = {"i64.load8_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD8_U] = {"i64.load8_u", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD16_S] = {"i64.load16_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD16_U] = {"i64.load16_u", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD32_S] = {"i64.load32_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD32_U] = {"i64.load32_u", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE] = {"i64.store", IMM_MEMARG, -1}, + [WASM_OP_F32_STORE] = {"f32.store", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE8] = {"i64.store8", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE16] = {"i64.store16", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE32] = {"i64.store32", IMM_MEMARG, -1}, + [WASM_OP_MEMORY_SIZE] = {"memory.size", IMM_MEMORY, -1}, + [WASM_OP_MEMORY_GROW] = {"memory.grow", IMM_MEMORY, -1}, + [WASM_OP_I64_CONST] = {"i64.const", IMM_I64, -1}, + [WASM_OP_F32_CONST] = {"f32.const", IMM_F32, -1}, + [WASM_OP_I64_EQZ] = {"i64.eqz", IMM_NONE, -1}, + [WASM_OP_I64_EQ] = {"i64.eq", IMM_NONE, -1}, + [WASM_OP_I64_NE] = {"i64.ne", IMM_NONE, -1}, + [WASM_OP_I64_LT_S] = {"i64.lt_s", IMM_NONE, -1}, + [WASM_OP_I64_LT_U] = {"i64.lt_u", IMM_NONE, -1}, + [WASM_OP_I64_GT_S] = {"i64.gt_s", IMM_NONE, -1}, + [WASM_OP_I64_GT_U] = {"i64.gt_u", IMM_NONE, -1}, + [WASM_OP_I64_LE_S] = {"i64.le_s", IMM_NONE, -1}, + [WASM_OP_I64_LE_U] = {"i64.le_u", IMM_NONE, -1}, + [WASM_OP_I64_GE_S] = {"i64.ge_s", IMM_NONE, -1}, + [WASM_OP_I64_GE_U] = {"i64.ge_u", IMM_NONE, -1}, + [WASM_OP_F32_EQ] = {"f32.eq", IMM_NONE, -1}, + [WASM_OP_F32_NE] = {"f32.ne", IMM_NONE, -1}, + [WASM_OP_F32_LT] = {"f32.lt", IMM_NONE, -1}, + [WASM_OP_F32_GT] = {"f32.gt", IMM_NONE, -1}, + [WASM_OP_F32_LE] = {"f32.le", IMM_NONE, -1}, + [WASM_OP_F32_GE] = {"f32.ge", IMM_NONE, -1}, + [WASM_OP_I64_CLZ] = {"i64.clz", IMM_NONE, -1}, + [WASM_OP_I64_CTZ] = {"i64.ctz", IMM_NONE, -1}, + [WASM_OP_I64_POPCNT] = {"i64.popcnt", IMM_NONE, -1}, + [WASM_OP_I64_ADD] = {"i64.add", IMM_NONE, -1}, + [WASM_OP_I64_SUB] = {"i64.sub", IMM_NONE, -1}, + [WASM_OP_I64_MUL] = {"i64.mul", IMM_NONE, -1}, + [WASM_OP_I64_DIV_S] = {"i64.div_s", IMM_NONE, -1}, + [WASM_OP_I64_DIV_U] = {"i64.div_u", IMM_NONE, -1}, + [WASM_OP_I64_REM_S] = {"i64.rem_s", IMM_NONE, -1}, + [WASM_OP_I64_REM_U] = {"i64.rem_u", IMM_NONE, -1}, + [WASM_OP_I64_AND] = {"i64.and", IMM_NONE, -1}, + [WASM_OP_I64_OR] = {"i64.or", IMM_NONE, -1}, + [WASM_OP_I64_XOR] = {"i64.xor", IMM_NONE, -1}, + [WASM_OP_I64_SHL] = {"i64.shl", IMM_NONE, -1}, + [WASM_OP_I64_SHR_S] = {"i64.shr_s", IMM_NONE, -1}, + [WASM_OP_I64_SHR_U] = {"i64.shr_u", IMM_NONE, -1}, + [WASM_OP_I64_ROTL] = {"i64.rotl", IMM_NONE, -1}, + [WASM_OP_I64_ROTR] = {"i64.rotr", IMM_NONE, -1}, + [WASM_OP_F32_ABS] = {"f32.abs", IMM_NONE, -1}, + [WASM_OP_F32_NEG] = {"f32.neg", IMM_NONE, -1}, + [WASM_OP_F32_CEIL] = {"f32.ceil", IMM_NONE, -1}, + [WASM_OP_F32_FLOOR] = {"f32.floor", IMM_NONE, -1}, + [WASM_OP_F32_TRUNC] = {"f32.trunc", IMM_NONE, -1}, + [WASM_OP_F32_NEAREST] = {"f32.nearest", IMM_NONE, -1}, + [WASM_OP_F32_SQRT] = {"f32.sqrt", IMM_NONE, -1}, + [WASM_OP_F32_ADD] = {"f32.add", IMM_NONE, -1}, + [WASM_OP_F32_SUB] = {"f32.sub", IMM_NONE, -1}, + [WASM_OP_F32_MUL] = {"f32.mul", IMM_NONE, -1}, + [WASM_OP_F32_DIV] = {"f32.div", IMM_NONE, -1}, + [WASM_OP_F32_MIN] = {"f32.min", IMM_NONE, -1}, + [WASM_OP_F32_MAX] = {"f32.max", IMM_NONE, -1}, + [WASM_OP_F32_COPYSIGN] = {"f32.copysign", IMM_NONE, -1}, + [WASM_OP_F64_ABS] = {"f64.abs", IMM_NONE, -1}, + [WASM_OP_F64_NEG] = {"f64.neg", IMM_NONE, -1}, + [WASM_OP_F64_CEIL] = {"f64.ceil", IMM_NONE, -1}, + [WASM_OP_F64_FLOOR] = {"f64.floor", IMM_NONE, -1}, + [WASM_OP_F64_TRUNC] = {"f64.trunc", IMM_NONE, -1}, + [WASM_OP_F64_NEAREST] = {"f64.nearest", IMM_NONE, -1}, + [WASM_OP_F64_SQRT] = {"f64.sqrt", IMM_NONE, -1}, + [WASM_OP_F64_MIN] = {"f64.min", IMM_NONE, -1}, + [WASM_OP_F64_MAX] = {"f64.max", IMM_NONE, -1}, + [WASM_OP_F64_COPYSIGN] = {"f64.copysign", IMM_NONE, -1}, + [WASM_OP_I32_WRAP_I64] = {"i32.wrap_i64", IMM_NONE, -1}, + [WASM_OP_I32_TRUNC_F32_S] = {"i32.trunc_f32_s", IMM_NONE, -1}, + [WASM_OP_I32_TRUNC_F32_U] = {"i32.trunc_f32_u", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND_I32_S] = {"i64.extend_i32_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND_I32_U] = {"i64.extend_i32_u", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F32_S] = {"i64.trunc_f32_s", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F32_U] = {"i64.trunc_f32_u", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F64_S] = {"i64.trunc_f64_s", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F64_U] = {"i64.trunc_f64_u", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I32_S] = {"f32.convert_i32_s", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I32_U] = {"f32.convert_i32_u", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I64_S] = {"f32.convert_i64_s", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I64_U] = {"f32.convert_i64_u", IMM_NONE, -1}, + [WASM_OP_F64_CONVERT_I64_S] = {"f64.convert_i64_s" , IMM_NONE, -1}, + [WASM_OP_F64_CONVERT_I64_U] = {"f64.convert_i64_u" , IMM_NONE, -1}, + [WASM_OP_F32_DEMOTE_F64] = {"f32.demote_f64", IMM_NONE, -1}, + [WASM_OP_F64_PROMOTE_F32] = {"f64.promote_f32", IMM_NONE, -1}, + [WASM_OP_I32_REINTERPRET_F32] = {"i32.reinterpret_f32", IMM_NONE, -1}, + [WASM_OP_I64_REINTERPRET_F64] = {"i64.reinterpret_f64", IMM_NONE, -1}, + [WASM_OP_F32_REINTERPRET_I32] = {"f32.reinterpret_i32", IMM_NONE, -1}, + [WASM_OP_F64_REINTERPRET_I64] = {"f64.reinterpret_i64", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND8_S] = {"i64.extend8_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND16_S] = {"i64.extend16_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND32_S] = {"i64.extend32_s", IMM_NONE, -1}, + [WASM_OP_REF_NULL] = {"ref.null", IMM_REFNULLT, -1}, + [WASM_OP_REF_IS_NULL] = {"ref.is_null", IMM_NONE, -1}, + [WASM_OP_REF_FUNC] = {"ref.func", IMM_FUNC, -1}, + [WASM_OP_REF_AS_NON_NULL] = {"ref.as_non_null", IMM_NONE, -1}, + [WASM_OP_BR_ON_NULL] = {"br_on_null", IMM_LABEL, -1}, + [WASM_OP_REF_EQ] = {"ref.eq", IMM_NONE, -1}, + [WASM_OP_BR_ON_NON_NULL] = {"br_on_non_null", IMM_LABEL, -1}, +}; + +#define PRINT(...) do { if(print) fprintf(stdout, __VA_ARGS__); } while(0) + +const char* bytecode_name(byte code) { + opcode_imm_t* entry = &opcode_imm_table[code]; + if (entry->mnemonic == NULL) return "<unknown>"; + return entry->mnemonic; +} + +void do_bytecode(int print, buffer_t* buf) { + for (int i = 0; i < g_indent; i++) PRINT(" "); + byte code = read_u8(buf); + opcode_imm_t* entry = &opcode_imm_table[code]; + if (entry->mnemonic == NULL) { + PRINT("<!illegal bytecode %02X>", code); + } else if (entry->illegal) { + PRINT("<!illegal %s>", entry->mnemonic); + } else { + PRINT("%s", entry->mnemonic); + } + switch (entry->immkind) { + case IMM_LABEL: // fallthru + case IMM_FUNC: // fallthru + case IMM_LOCAL: // fallthru + case IMM_GLOBAL: // fallthru + case IMM_MEMORY: // fallthru + case IMM_TAG: // fallthru + case IMM_REFNULLT: + case IMM_TABLE: { + uint32_t imm = read_u32leb(buf); + PRINT(" %u", imm); + break; + } + + case IMM_NONE: break; + case IMM_BLOCKT: { + int32_t imm = read_i32leb(buf); + if (imm != -64) { + PRINT(" <!illegal blocktype %d>", imm); + } + break; + } + case IMM_LABELS: { + uint32_t count = read_u32leb(buf); + PRINT(" %u", count); + for (uint32_t i = 0; i <= count && buf->ptr < buf->end; i++) { + uint32_t lbl = read_u32leb(buf); + PRINT(" %u", lbl); + } + break; + } + case IMM_SIG_TABLE: { + uint32_t sig = read_u32leb(buf); + PRINT(" %d", sig); + uint32_t tbl = read_u32leb(buf); + if (tbl != 0) { + PRINT(" <!illegal table %d>", tbl); + } + break; + } + case IMM_MEMARG: { + byte b = read_u8(buf); + uint32_t offset = read_u32leb(buf); + PRINT(" %u", offset); + break; + } + case IMM_I32: { + int32_t imm = read_i32leb(buf); + PRINT(" %d", imm); + break; + } + case IMM_F64: { + if (buf->end - buf->ptr >= 8) { + uint64_t val = *((uint64_t*)buf->ptr); + PRINT(" %016" PRIx64, val); + buf->ptr += 8; + } else { + PRINT(" <!invalid f64>"); + } + break; + } + case IMM_I64: { + ssize_t leblen = 0; + if (buf->ptr >= buf->end) break; + int64_t imm = decode_i64leb(buf->ptr, buf->end, &leblen); + if (leblen <= 0) buf->ptr = buf->end; // force failure + else buf->ptr += leblen; + PRINT(" %" PRId64 "", imm); + break; + } + case IMM_F32: { + for (int i = 0; i < 4; i++) { + byte b = read_u8(buf); + PRINT(" %02X", b); + } + break; + } + case IMM_VALTS: { + int32_t tcode = read_i32leb(buf); + PRINT(" %s", type_name(tcode)); + break; + } + default: break; + } + PRINT("\n"); +} + +void skip_bytecode(buffer_t* buf) { + do_bytecode(0, buf); +} + +void print_bytecode(buffer_t* buf) { + do_bytecode(1, buf); +} + +void skip_local_decls(buffer_t* buf) { + uint32_t cnt = read_u32leb(buf); + for (uint32_t i = 0; i < cnt; i++) { + uint32_t cnt = read_u32leb(buf); + int32_t type = read_i32leb(buf); + } +} diff --git a/disass.h b/disass.h new file mode 100644 index 0000000..4de8d25 --- /dev/null +++ b/disass.h @@ -0,0 +1,41 @@ +#pragma once + +#define WASM_TYPE_I32 -1 +#define WASM_TYPE_I64 -2 +#define WASM_TYPE_F32 -3 +#define WASM_TYPE_F64 -4 +#define WASM_TYPE_V128 -5 +#define WASM_TYPE_EXTERNREF -17 +#define WASM_TYPE_FUNCREF -16 + +#define WASM_IMPORT_FUNC 0 +#define WASM_IMPORT_TABLE 1 +#define WASM_IMPORT_MEMORY 2 +#define WASM_IMPORT_GLOBAL 3 + +// Returns the string name of a section code. +const char* section_name(byte code); + +// Returns the string name of a type code. +const char* type_name(uint32_t code); + +// Returns the string name of a type declaration code. +const char* type_decl_name(uint32_t code); + +// Returns the name of an import kind. +const char* import_kind_name(uint32_t code); + +// Returns the mnemonic name of a bytecode. +const char* bytecode_name(byte b); + +// Prints a bytecode to standard out. +void print_bytecode(buffer_t* buf); + +// Skips to the next bytecode. +void skip_bytecode(buffer_t* buf); + +// Skips over local declarations. +void skip_local_decls(buffer_t* buf); + +// Prints data as hexadecimal. +void print_data(buffer_t* buf, uint32_t count); diff --git a/grade.sh b/grade.sh new file mode 100755 index 0000000..5378138 --- /dev/null +++ b/grade.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +if [ $# = 0 ]; then + WEERUN='./weerun' +else + WEERUN=$1 + shift +fi + +T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/} +mkdir -p $T + + +if [ ! -x "$WEERUN" ]; then + printf "##+weerun\n" + printf "##-fail, weerun not found: %s\n" $WEERUN + exit 1 +fi + +if [ $# = 0 ]; then + TESTS=$(ls tests/*.wee.wasm) +else + TESTS=$@ +fi + +# substitute for the "timeout" command on MacOS +function xtimeout { + timeout=$1 + shift + command=("$@") + ( + "${command[@]}" & + runnerpid=$! + trap -- '' SIGTERM + ( # killer job + sleep $timeout + if ps -p $runnerpid > /dev/null; then + echo "Timed out, killing" + kill -SIGKILL $runnerpid 2>/dev/null + fi + ) & + killerpid=$! + wait $runnerpid + kill -SIGKILL $killerpid + ) +} + +function run_one() { + echo $WEERUN $f $ARGS + xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR + # ignore case + diff --strip-trailing-cr -i $EXP $OUT > $DIFF + OK=$? + if [ ! -s $DIFF ]; then + # remove empty diffs + rm $DIFF + else + cat $DIFF + fi + + if [ $OK = 0 ]; then + return 0 + else + echo diff $EXP $OUT + printf "##-fail: $ARGS\n" + return 1 + fi + +} + +for f in $TESTS; do + # replace slashes with _ + t=${f//\//_} + # replace .wasm with .runs + runs=${f/%.wee.wasm/.runs} + + printf "##+%s\n" $t + + OUT=$T/$t.out + ERR=$T/$t.err + EXP=$T/$t.expect + DIFF=$T/$t.diff + + if [ -f $runs ]; then + # do multiple runs for this test + ok=1 + while IFS= read -r line + do + ARGS=$(echo $line | cut -d= -f1) + EXPECT=$(echo $line | cut -d= -f2) + echo $EXPECT > $EXP + + run_one + + if [ $? != 0 ]; then + ok=0 + break; + fi + done < $runs + if [ $ok = 1 ]; then + printf "##-ok\n" + fi + else + # do one run + e=${f/%.wee.wasm/.expect} + args=${f/%.wee.wasm/.args} + cp $e $EXP + + if [ -f $args ]; then + ARGS=$(cat $args) + else + ARGS="" + fi + + run_one + + if [ $? = 0 ]; then + printf "##-ok\n" + fi + fi +done diff --git a/illegal.h b/illegal.h new file mode 100644 index 0000000..1f9c135 --- /dev/null +++ b/illegal.h @@ -0,0 +1,124 @@ +#pragma once + +#define WASM_OP_IF 0x04 /* "if" BLOCKT */ +#define WASM_OP_ELSE 0x05 /* "else" */ +#define WASM_OP_TRY 0x06 /* "try", ImmSigs.BLOCKT */ +#define WASM_OP_CATCH 0x07 /* "catch", ImmSigs.TAG */ +#define WASM_OP_THROW 0x08 /* "throw", ImmSigs.TAG */ +#define WASM_OP_RETHROW 0x09 /* "rethrow", ImmSigs.NONE */ +#define WASM_OP_RETURN_CALL 0x12 /* "return_call", ImmSigs.FUNC */ +#define WASM_OP_RETURN_CALL_INDIRECT 0x13 /* "return_call_indirect", ImmSigs.SIG_TABLE */ +#define WASM_OP_CALL_REF 0x14 /* "call_ref", ImmSigs.NONE */ +#define WASM_OP_RETURN_CALL_REF 0x15 /* "return_call_ref", ImmSigs.NONE */ +#define WASM_OP_DELEGATE 0x18 /* "delegate", ImmSigs.NONE */ +#define WASM_OP_CATCH_ALL 0x19 /* "catch_all", ImmSigs.NONE */ +#define WASM_OP_SELECT_T 0x1C /* "select", ImmSigs.VALTS */ +#define WASM_OP_TABLE_GET 0x25 /* "table.get" TABLE */ +#define WASM_OP_TABLE_SET 0x26 /* "table.set" TABLE */ +#define WASM_OP_I64_LOAD 0x29 /* "i64.load", ImmSigs.MEMARG */ +#define WASM_OP_F32_LOAD 0x2A /* "f32.load", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD8_S 0x30 /* "i64.load8_s", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD8_U 0x31 /* "i64.load8_u", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD16_S 0x32 /* "i64.load16_s", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD16_U 0x33 /* "i64.load16_u", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD32_S 0x34 /* "i64.load32_s", ImmSigs.MEMARG */ +#define WASM_OP_I64_LOAD32_U 0x35 /* "i64.load32_u", ImmSigs.MEMARG */ +#define WASM_OP_I64_STORE 0x37 /* "i64.store", ImmSigs.MEMARG */ +#define WASM_OP_F32_STORE 0x38 /* "f32.store", ImmSigs.MEMARG */ +#define WASM_OP_I64_STORE8 0x3C /* "i64.store8", ImmSigs.MEMARG */ +#define WASM_OP_I64_STORE16 0x3D /* "i64.store16", ImmSigs.MEMARG */ +#define WASM_OP_I64_STORE32 0x3E /* "i64.store32", ImmSigs.MEMARG */ +#define WASM_OP_MEMORY_SIZE 0x3F /* "memory.size", ImmSigs.MEMORY */ +#define WASM_OP_MEMORY_GROW 0x40 /* "memory.grow", ImmSigs.MEMORY */ +#define WASM_OP_I64_CONST 0x42 /* "i64.const", ImmSigs.I64 */ +#define WASM_OP_F32_CONST 0x43 /* "f32.const", ImmSigs.F32 */ +#define WASM_OP_I64_EQZ 0x50 /* "i64.eqz", ImmSigs.NONE */ +#define WASM_OP_I64_EQ 0x51 /* "i64.eq", ImmSigs.NONE */ +#define WASM_OP_I64_NE 0x52 /* "i64.ne", ImmSigs.NONE */ +#define WASM_OP_I64_LT_S 0x53 /* "i64.lt_s", ImmSigs.NONE */ +#define WASM_OP_I64_LT_U 0x54 /* "i64.lt_u", ImmSigs.NONE */ +#define WASM_OP_I64_GT_S 0x55 /* "i64.gt_s", ImmSigs.NONE */ +#define WASM_OP_I64_GT_U 0x56 /* "i64.gt_u", ImmSigs.NONE */ +#define WASM_OP_I64_LE_S 0x57 /* "i64.le_s", ImmSigs.NONE */ +#define WASM_OP_I64_LE_U 0x58 /* "i64.le_u", ImmSigs.NONE */ +#define WASM_OP_I64_GE_S 0x59 /* "i64.ge_s", ImmSigs.NONE */ +#define WASM_OP_I64_GE_U 0x5A /* "i64.ge_u", ImmSigs.NONE */ +#define WASM_OP_F32_EQ 0x5B /* "f32.eq", ImmSigs.NONE */ +#define WASM_OP_F32_NE 0x5C /* "f32.ne", ImmSigs.NONE */ +#define WASM_OP_F32_LT 0x5D /* "f32.lt", ImmSigs.NONE */ +#define WASM_OP_F32_GT 0x5E /* "f32.gt", ImmSigs.NONE */ +#define WASM_OP_F32_LE 0x5F /* "f32.le", ImmSigs.NONE */ +#define WASM_OP_F32_GE 0x60 /* "f32.ge", ImmSigs.NONE */ +#define WASM_OP_I64_CLZ 0x79 /* "i64.clz", ImmSigs.NONE */ +#define WASM_OP_I64_CTZ 0x7A /* "i64.ctz", ImmSigs.NONE */ +#define WASM_OP_I64_POPCNT 0x7B /* "i64.popcnt", ImmSigs.NONE */ +#define WASM_OP_I64_ADD 0x7C /* "i64.add", ImmSigs.NONE */ +#define WASM_OP_I64_SUB 0x7D /* "i64.sub", ImmSigs.NONE */ +#define WASM_OP_I64_MUL 0x7E /* "i64.mul", ImmSigs.NONE */ +#define WASM_OP_I64_DIV_S 0x7F /* "i64.div_s", ImmSigs.NONE */ +#define WASM_OP_I64_DIV_U 0x80 /* "i64.div_u", ImmSigs.NONE */ +#define WASM_OP_I64_REM_S 0x81 /* "i64.rem_s", ImmSigs.NONE */ +#define WASM_OP_I64_REM_U 0x82 /* "i64.rem_u", ImmSigs.NONE */ +#define WASM_OP_I64_AND 0x83 /* "i64.and", ImmSigs.NONE */ +#define WASM_OP_I64_OR 0x84 /* "i64.or", ImmSigs.NONE */ +#define WASM_OP_I64_XOR 0x85 /* "i64.xor", ImmSigs.NONE */ +#define WASM_OP_I64_SHL 0x86 /* "i64.shl", ImmSigs.NONE */ +#define WASM_OP_I64_SHR_S 0x87 /* "i64.shr_s", ImmSigs.NONE */ +#define WASM_OP_I64_SHR_U 0x88 /* "i64.shr_u", ImmSigs.NONE */ +#define WASM_OP_I64_ROTL 0x89 /* "i64.rotl", ImmSigs.NONE */ +#define WASM_OP_I64_ROTR 0x8A /* "i64.rotr", ImmSigs.NONE */ +#define WASM_OP_F32_ABS 0x8B /* "f32.abs", ImmSigs.NONE */ +#define WASM_OP_F32_NEG 0x8C /* "f32.neg", ImmSigs.NONE */ +#define WASM_OP_F32_CEIL 0x8D /* "f32.ceil", ImmSigs.NONE */ +#define WASM_OP_F32_FLOOR 0x8E /* "f32.floor", ImmSigs.NONE */ +#define WASM_OP_F32_TRUNC 0x8F /* "f32.trunc", ImmSigs.NONE */ +#define WASM_OP_F32_NEAREST 0x90 /* "f32.nearest", ImmSigs.NONE */ +#define WASM_OP_F32_SQRT 0x91 /* "f32.sqrt", ImmSigs.NONE */ +#define WASM_OP_F32_ADD 0x92 /* "f32.add", ImmSigs.NONE */ +#define WASM_OP_F32_SUB 0x93 /* "f32.sub", ImmSigs.NONE */ +#define WASM_OP_F32_MUL 0x94 /* "f32.mul", ImmSigs.NONE */ +#define WASM_OP_F32_DIV 0x95 /* "f32.div", ImmSigs.NONE */ +#define WASM_OP_F32_MIN 0x96 /* "f32.min", ImmSigs.NONE */ +#define WASM_OP_F32_MAX 0x97 /* "f32.max", ImmSigs.NONE */ +#define WASM_OP_F32_COPYSIGN 0x98 /* "f32.copysign", ImmSigs.NONE */ +#define WASM_OP_F64_ABS 0x99 /* "f64.abs", ImmSigs.NONE */ +#define WASM_OP_F64_NEG 0x9A /* "f64.neg", ImmSigs.NONE */ +#define WASM_OP_F64_CEIL 0x9B /* "f64.ceil", ImmSigs.NONE */ +#define WASM_OP_F64_FLOOR 0x9C /* "f64.floor", ImmSigs.NONE */ +#define WASM_OP_F64_TRUNC 0x9D /* "f64.trunc", ImmSigs.NONE */ +#define WASM_OP_F64_NEAREST 0x9E /* "f64.nearest", ImmSigs.NONE */ +#define WASM_OP_F64_SQRT 0x9F /* "f64.sqrt", ImmSigs.NONE */ +#define WASM_OP_F64_MIN 0xA4 /* "f64.min", ImmSigs.NONE */ +#define WASM_OP_F64_MAX 0xA5 /* "f64.max", ImmSigs.NONE */ +#define WASM_OP_F64_COPYSIGN 0xA6 /* "f64.copysign", ImmSigs.NONE */ +#define WASM_OP_I32_WRAP_I64 0xA7 /* "i32.wrap_i64", ImmSigs.NONE */ +#define WASM_OP_I32_TRUNC_F32_S 0xA8 /* "i32.trunc_f32_s", ImmSigs.NONE */ +#define WASM_OP_I32_TRUNC_F32_U 0xA9 /* "i32.trunc_f32_u", ImmSigs.NONE */ +#define WASM_OP_I64_EXTEND_I32_S 0xAC /* "i64.extend_i32_s", ImmSigs.NONE */ +#define WASM_OP_I64_EXTEND_I32_U 0xAD /* "i64.extend_i32_u", ImmSigs.NONE */ +#define WASM_OP_I64_TRUNC_F32_S 0xAE /* "i64.trunc_f32_s", ImmSigs.NONE */ +#define WASM_OP_I64_TRUNC_F32_U 0xAF /* "i64.trunc_f32_u", ImmSigs.NONE */ +#define WASM_OP_I64_TRUNC_F64_S 0xB0 /* "i64.trunc_f64_s", ImmSigs.NONE */ +#define WASM_OP_I64_TRUNC_F64_U 0xB1 /* "i64.trunc_f64_u", ImmSigs.NONE */ +#define WASM_OP_F32_CONVERT_I32_S 0xB2 /* "f32.convert_i32_s", ImmSigs.NONE */ +#define WASM_OP_F32_CONVERT_I32_U 0xB3 /* "f32.convert_i32_u", ImmSigs.NONE */ +#define WASM_OP_F32_CONVERT_I64_S 0xB4 /* "f32.convert_i64_s", ImmSigs.NONE */ +#define WASM_OP_F32_CONVERT_I64_U 0xB5 /* "f32.convert_i64_u", ImmSigs.NONE */ +#define WASM_OP_F32_DEMOTE_F64 0xB6 /* "f32.demote_f64", ImmSigs.NONE */ +#define WASM_OP_F64_CONVERT_I64_S 0xB9 /* "f64.convert_i64_s" */ +#define WASM_OP_F64_CONVERT_I64_U 0xBA /* "f64.convert_i64_u" */ +#define WASM_OP_F64_PROMOTE_F32 0xBB /* "f64.promote_f32", ImmSigs.NONE */ +#define WASM_OP_I32_REINTERPRET_F32 0xBC /* "i32.reinterpret_f32", ImmSigs.NONE */ +#define WASM_OP_I64_REINTERPRET_F64 0xBD /* "i64.reinterpret_f64", ImmSigs.NONE */ +#define WASM_OP_F32_REINTERPRET_I32 0xBE /* "f32.reinterpret_i32", ImmSigs.NONE */ +#define WASM_OP_F64_REINTERPRET_I64 0xBF /* "f64.reinterpret_i64", ImmSigs.NONE */ +#define WASM_OP_I64_EXTEND8_S 0xC2 /* "i64.extend8_s", ImmSigs.NONE */ +#define WASM_OP_I64_EXTEND16_S 0xC3 /* "i64.extend16_s", ImmSigs.NONE */ +#define WASM_OP_I64_EXTEND32_S 0xC4 /* "i64.extend32_s", ImmSigs.NONE */ +#define WASM_OP_REF_NULL 0xD0 /* "ref.null", ImmSigs.REFNULLT */ +#define WASM_OP_REF_IS_NULL 0xD1 /* "ref.is_null", ImmSigs.NONE */ +#define WASM_OP_REF_FUNC 0xD2 /* "ref.func", ImmSigs.FUNC */ +#define WASM_OP_REF_AS_NON_NULL 0xD3 /* "ref.as_non_null", ImmSigs.NONE */ +#define WASM_OP_BR_ON_NULL 0xD4 /* "br_on_null", ImmSigs.LABEL */ +#define WASM_OP_REF_EQ 0xD5 /* "ref.eq", ImmSigs.NONE */ +#define WASM_OP_BR_ON_NON_NULL 0xD6 /* "br_on_non_null", ImmSigs.LABEL */ @@ -0,0 +1,88 @@ +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "common.h" +#include "ir.h" + +wasm_value_t parse_wasm_value(char* str) { + int len = strlen(str); + if (len > 0) { + if (str[len - 1] == 'd' || str[len - 1] == 'D') { + // treat the input as a double + char* end = NULL; + double result = strtod(str, &end); + if (end == (str + len - 1)) + return wasm_f64_value(result); + } else { + // treat the input as an integer + char* end = NULL; + int base = 10; + if (len >= 2 && (str[1] == 'x' || str[1] == 'X')) + base = 16; + long result = strtol(str, &end, base); + if (end == (str + len)) + return wasm_i32_value(result); + } + } + wasm_value_t orig_string = { + .val.ref = str, + }; + return orig_string; +} + +void print_wasm_value(wasm_typed_value_t val) { + switch (val.tag) { + case I32: + printf("%d", val.val.val.i32); + break; + case F64: + printf("%lf", val.val.val.f64); + break; + case EXTERNREF: + if (val.val.val.ref == NULL) + printf("null"); + else + printf("%p", val.val.val.ref); + break; + } +} + +void trace_wasm_value(wasm_typed_value_t val) { + switch (val.tag) { + case I32: + TRACE("%d", val.val.val.i32); + break; + case F64: + TRACE("%lf", val.val.val.f64); + break; + case EXTERNREF: + if (val.val.val.ref == NULL) + printf("null"); + else + TRACE("%p", val.val.val.ref); + break; + } +} + +wasm_value_t wasm_i32_value(int32_t val) { + wasm_value_t r = { + .val.i32 = val, + }; + return r; +} + +wasm_value_t wasm_f64_value(double val) { + wasm_value_t r = { + .val.f64 = val, + }; + return r; +} + +wasm_value_t wasm_ref_value(void* val) { + wasm_value_t r = { + .val.ref = val, + }; + return r; +} @@ -0,0 +1,41 @@ +#pragma once + +#include <stdint.h> + +typedef uint8_t byte; + +typedef enum { + I32 = 0x7f, + F64 = 0x7c, + EXTERNREF = 0x6f, + FUNCREF = 0x70 +} wasm_type_t; + +typedef enum { FUNC, GLOBAL, TABLE, MEMORY } wasm_import_kind_t; + +typedef struct { + union { + uint32_t i32; + double f64; + void* ref; + uint64_t i64; + } val; +} wasm_value_t; + +typedef struct { + uint64_t tag; + wasm_value_t val; +} wasm_typed_value_t; + +typedef struct { + int32_t length; // < 0 indicates a trap or error + wasm_value_t* vals; +} wasm_values; + +wasm_value_t parse_wasm_value(char* string); +void print_wasm_value(wasm_typed_value_t val); +void trace_wasm_value(wasm_typed_value_t val); + +wasm_value_t wasm_i32_value(int32_t val); +wasm_value_t wasm_f64_value(double val); +wasm_value_t wasm_ref_value(void* val); diff --git a/noderun.js b/noderun.js new file mode 100644 index 0000000..8e5ab75 --- /dev/null +++ b/noderun.js @@ -0,0 +1,106 @@ +const fs = require("fs"); + +var args = process.argv.slice(3); +const filename = process.argv[2]; +const bytes = fs.readFileSync(filename); +const wasm = new WebAssembly.Module(bytes); + +function log(s) { +// process.stdout.write(s + "\n"); +} + +// The imports for Wee-O-Wasm, implemented in JavaScript. +const imports = {weewasm: { + puti: v => process.stdout.write("" + (v | 0)), + putd: v => process.stdout.write("" + (+v)), + // TODO: puts requires the module to export its memory, which is currently disallowed in WeeWasm. + + // Allocates a new WeeWasm object. + "obj.new": () => new WeakMap(), + // Gets a property from a WeeWasm object, given the key. + "obj.get": function(ref, key) { + var obj = toWeeObject(ref); + log("obj.get(" + obj + ", " + key + ")"); + if (key == null) throw new Error("null key"); + var v; + if ((typeof key) == "number") { + v = obj[key]; + } else if (key instanceof F64Box) { // F64s must be unboxed and stored separately + v = getF64s(obj)[key.val]; + } else { + v = obj.get(key); + } + return v == undefined ? null : v; + }, + // Sets a property from a WeeWasm object, given the key and the value + "obj.set": function(ref, key, val) { + var obj = toWeeObject(ref); + log("obj.set(" + obj + ", " + key + ", " + val + ")"); + if (key == null) throw new Error("null key"); + if ((typeof key) == "number") { + obj[key] = val; + } else if (key instanceof F64Box) { // F64s must be unboxed and stored separately + getF64s(obj)[key.val] = val; + } else { + obj.set(key, val); + } + }, + // Converts an i32 into a WeeWasm reference. + "obj.box_i32": v => v | 0, // ints are represented as regular JS numbers + // Converts an f64 into a WeeWasm reference. + "obj.box_f64": v => new F64Box(+v), // floats are boxed to distinguish from ints + // Converts a reference back to an i32. + "i32.unbox": function(v) { + if (typeof v == "number") return v | 0; + throw new Error("not an i32"); + }, + // Converts a reference back to an f64. + "f64.unbox": function(v) { + if (v instanceof F64Box) return +v.val; + throw new Error("not an f64"); + }, + // Compare two references for equality. + "obj.eq": (a, b) => { + if (a instanceof F64Box) return (b instanceof F64Box) && a.val == b.val; + return a === b; + } +}}; + +function toWeeObject(obj) { + if (obj == null) throw new Error("null reference"); + if (!(obj instanceof WeakMap)) throw new Error("not a wee object"); + return obj; +} + +function getF64s(obj) { + var elems = obj.f64s; + if (elems == undefined) elems = obj.f64s = new Object(); + return elems; +} + +// F64s represented boxed floats, to distinguish from int +function F64Box(v) { + this.val = v; +} + +const instance = new WebAssembly.Instance(wasm, imports); + +var main = instance.exports["main"]; + +for (var i = 0; i < args.length; i++) { + var a = args[i]; + if (a.endsWith("d")) { // double + args[i] = +(a.substring(0, a.length - 1)); + } else { // integer + args[i] = a | 0; + } +} + +try { + var result = main(...args); + if (filename.search("_d.wee.wasm") >= 0) console.log(result.toFixed(6)); // to match C's printf + else console.log(result); +} catch (e) { + console.log("!trap"); + process.stderr.write("" + e + "\n"); +} diff --git a/noderun.sh b/noderun.sh new file mode 100755 index 0000000..3f474b3 --- /dev/null +++ b/noderun.sh @@ -0,0 +1,3 @@ +#!/bin/bash +NODE=${NODE:=$(which node)} +exec $NODE --experimental-wasm-reftypes noderun.js "$@" @@ -0,0 +1,449 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#include "common.h" +#include "vm.h" +#include "test.h" +#include "weewasm.h" +#include "illegal.h" +#include "ir.h" +#include "disass.h" + +#define CHECK(x) do { if(!(x)) return -2; } while(0) + +// Read a string and print its length and UTF-8 chars. +int read_and_copy_string(buffer_t* buf, const char** nameptr, const byte* sectend) { + uint32_t namelen = read_u32leb(buf); + DISASS("%u ", namelen); + if (nameptr != NULL) *nameptr = strndup((const char*)buf->ptr, namelen); + CHECK((sectend - buf->ptr) >= namelen); + DISASS("\"%.*s\"", namelen, buf->ptr); + buf->ptr += namelen; + return 0; +} + +wasm_type_t read_value_type(buffer_t* buf) { + int32_t type = read_i32leb(buf); + DISASS(" %s", type_name(type)); + switch (type) { + case WASM_TYPE_I32: return I32; + case WASM_TYPE_F64: return F64; + case WASM_TYPE_EXTERNREF: return EXTERNREF; + default: + ERR("!illegal type (%s)", type_name(type)); + return EXTERNREF; + } +} + +wasm_value_t read_init_expr(buffer_t* buf) { + wasm_value_t val = wasm_i32_value(0); + byte b = read_u8(buf); + switch (b) { + case WASM_OP_I32_CONST: { + val = wasm_i32_value(read_i32leb(buf)); + break; + } + case WASM_OP_F64_CONST: { + double* p = (double*)buf->ptr; + buf->ptr += 8; + val = wasm_f64_value(*p); + break; + } + default: { + ERR("!illegal init expr bytecode 0x%02X (%s)", b, bytecode_name(b)); + break; + } + } + b = read_u8(buf); + if (b != WASM_OP_END) ERR("!illegal init expr bytecode 0x%02X", b); + return val; +} + +// Read minimimum and optional maximum. +void read_limits(buffer_t* buf, wasm_limits_t* dest) { + byte val = read_u8(buf); + dest->initial = read_u32leb(buf); + if ((val & 1) == 1) { + dest->max = read_u32leb(buf); + dest->has_max = 1; + DISASS(" %u %u \t\t\t; initial and max\n", dest->initial, dest->max); + } else { + dest->max = 0xFFFFFFFFu; + dest->has_max = 0; + DISASS(" %u \t\t\t; initial\n", dest->initial); + } +} + +// Reads a section code, skipping custom sections. +int read_section_code(buffer_t* buf, wasm_module_t* module, uint32_t* sectlen) { + while (buf->ptr < buf->end) { + byte code = read_u8(buf); + if (code != 0) { + DISASS("%s ", section_name(code)); + // read a normal section + *sectlen = read_u32leb(buf); + CHECK((buf->end - buf->ptr) >= *sectlen); + return code; + } + // print custom section + DISASS("custom "); + uint32_t sectlen = read_u32leb(buf); + DISASS("%u ", sectlen); + CHECK((buf->end - buf->ptr) >= sectlen); + const byte* sectend = buf->ptr + sectlen; + read_and_copy_string(buf, NULL, sectend); + DISASS("\n"); + buf->ptr = sectend; + } + // reached the end of the file, or there was a nested error + return -1; +} + +void read_type_decl(buffer_t* buf, wasm_sig_decl_t* dest, const byte* sectend) { + byte code = read_u8(buf); + DISASS(" %s", type_decl_name(code)); + if (code != 0x60) ERR("!expected signature declaration (0x60), got 0x%02X", code); + uint32_t pcount = read_u32leb(buf); + DISASS(" %u", pcount); + dest->num_params = pcount; + dest->params = (wasm_type_t*)malloc(pcount * sizeof(wasm_type_t)); + for (uint32_t i = 0; i < pcount && (buf->ptr < buf->end); i++) { + wasm_type_t t = read_value_type(buf); + dest->params[i] = t; + } + uint32_t rcount = read_u32leb(buf); + dest->num_results = rcount; + dest->results = (wasm_type_t*)malloc(rcount * sizeof(wasm_type_t)); + DISASS(" %u", rcount); + if (rcount > 1) ERR("!expected result count <= 1, got %d", rcount); + for (uint32_t i = 0; i < rcount && (buf->ptr < buf->end); i++) { + wasm_type_t t = read_value_type(buf); + dest->results[i] = t; + } + DISASS("\n"); +} + +uint8_t bind_import(wasm_module_t* module, wasm_import_decl_t* decl) { + if (strcmp(decl->mod_name, "weewasm") != 0) ERR("!unrecognized import module: %s", decl->mod_name); + if (strcmp(decl->member_name, "puti") == 0) return WEEWASM_INTRINSIC_PUTI; // TODO: check signature + if (strcmp(decl->member_name, "putd") == 0) return WEEWASM_INTRINSIC_PUTD; + if (strcmp(decl->member_name, "puts") == 0) return WEEWASM_INTRINSIC_PUTS; + ERR("!unrecognized weewasm import: %s", decl->member_name); + return 0; +} + +void read_import_decl(buffer_t* buf, wasm_module_t* module, uint32_t import_index, uint32_t func_index, const byte* sectend) { + DISASS(" "); + wasm_import_decl_t* dest = &module->imports[import_index]; + read_and_copy_string(buf, &dest->mod_name, sectend); + DISASS(" "); + read_and_copy_string(buf, &dest->member_name, sectend); + uint32_t code = read_u8(buf); + DISASS(" %s", import_kind_name(code)); + switch (code) { + case WASM_IMPORT_FUNC: { + uint32_t sig = read_u32leb(buf); + DISASS(" %u", sig); + dest->kind = FUNC; + dest->index = func_index; + wasm_func_decl_t* func = &module->funcs[func_index]; + func->sig_index = sig; + func->intrinsic = bind_import(module, dest); + break; + } + case WASM_IMPORT_TABLE: { + ERR("!illegal table import"); + break; + } + case WASM_IMPORT_MEMORY: { + ERR("!illegal memory import"); + break; + } + case WASM_IMPORT_GLOBAL: { + ERR("!illegal global import"); + break; + } + } + DISASS("\n"); +} + +void read_func_decl(buffer_t* buf, wasm_func_decl_t* dest, const byte* sectend) { + uint32_t index = read_u32leb(buf); + dest->sig_index = index; + DISASS(" %u \t\t\t; signature index\n", index); +} + +void read_table_decl(buffer_t* buf, wasm_table_decl_t* dest, const byte* sectend) { + int32_t type = read_i32leb(buf); + DISASS(" %s", type_name(type)); + if (type != WASM_TYPE_FUNCREF) ERR("!invalid table type %s", type_name(type)); + read_limits(buf, &dest->limits); + DISASS("\n"); +} + +void read_memory_decl(buffer_t* buf, wasm_limits_t* limits, const byte* sectend) { + read_limits(buf, limits); + DISASS("\n"); +} + +void read_global_decl(buffer_t* buf, wasm_global_decl_t* dest, const byte* sectend) { + dest->type = read_value_type(buf); + byte mut = read_u8(buf); + dest->mutable = mut != 0; + if (mut != 0) DISASS(" mutable"); + DISASS("\n"); + dest->init = read_init_expr(buf); +} + +void read_export_decl(buffer_t* buf, wasm_module_t* module, const byte* sectend) { + DISASS(" "); + uint32_t namelen = 0; + const char* name = NULL; + read_and_copy_string(buf, &name, sectend); + if (strcmp(name, "main") != 0) ERR("!expected export name \"main\", got %s", name); + free((char*)name); // XXX: avoid copy? + + uint32_t code = read_u8(buf); + DISASS(" %s", import_kind_name(code)); + uint32_t index = read_u32leb(buf); + DISASS(" %u \t\t\t; export index\n", index); + switch (code) { + case WASM_IMPORT_FUNC: { + module->main_func = (int32_t)index; + break; + } + case WASM_IMPORT_TABLE: { + ERR("!illegal table export"); + break; + } + case WASM_IMPORT_MEMORY: { + ERR("!illegal memory export"); + break; + } + case WASM_IMPORT_GLOBAL: { + ERR("!illegal global export"); + break; + } + } +} + +uint32_t read_offset_expr(buffer_t* buf) { + uint32_t val = 0; + while (buf->ptr < buf->end) { + byte b = read_u8(buf); + if (b == WASM_OP_I32_CONST) { + val = (uint32_t)read_i32leb(buf); + DISASS(" %u \t\t\t; offset\n", val); + } else if (b == WASM_OP_END) { + break; + } else { + DISASS("<!unexpected bytecode %02X>", b); + break; + } + } + return val; +} + +void read_elems_decl(buffer_t* buf, wasm_elems_decl_t* dest, const byte* sectend) { + byte b = read_u32leb(buf); + if (b != 0) { + DISASS(" <!invalid elem flags %d>", b); + } else { + DISASS(" "); + dest->table_offset = read_offset_expr(buf); + uint32_t count = read_u32leb(buf); + dest->length = count; + dest->func_indexes = (uint32_t*)malloc(dest->length * sizeof(uint32_t)); + DISASS(" %u \t\t\t; count\n ", count); + for (uint32_t i = 0; i < count && buf->ptr < buf->end; i++) { + uint32_t f = read_u32leb(buf); + DISASS(" %u", f); + dest->func_indexes[i] = f; + } + } + DISASS("\n"); +} + +void read_code_decl(buffer_t* buf, wasm_func_decl_t* dest, const byte* sectend) { + uint32_t len = read_u32leb(buf); + dest->code_start = (uint32_t)(buf->ptr - buf->start); + const byte* codeend = buf->ptr + len; + DISASS("body %u \t\t\t; length\n", len); + uint32_t cnt = read_u32leb(buf); + DISASS(" %u \t\t\t; locals count\n", cnt); + for (uint32_t i = 0; i < cnt; i++) { + uint32_t cnt = read_u32leb(buf); + DISASS(" %u", cnt); + int32_t type = read_i32leb(buf); + DISASS(" %s\n", type_name(type)); + } + if (g_disassemble) { + // disassemble code + while (buf->ptr < codeend && buf->ptr < buf->end) { + print_bytecode(buf); + } + } + buf->ptr = codeend; + dest->code_end = (uint32_t)(buf->ptr - buf->start); +} + +void read_data_decl(buffer_t* buf, wasm_data_decl_t* dest, const byte* sectend) { + byte b = read_u32leb(buf); + if (b != 0) { + DISASS(" <!invalid data flags %d>", b); + } else { + dest->mem_offset = read_offset_expr(buf); + uint32_t count = read_u32leb(buf); + DISASS(" %u \t\t\t; bytes count\n", count); + dest->bytes_start = (uint32_t)(buf->ptr - buf->start); + if (g_disassemble) { + print_data(buf, count); + } else { + buf->ptr += count; + if (buf->ptr > buf->end) { + ERR("!too much data, %d bytes", count); + buf->ptr = buf->end; + } + } + dest->bytes_end = (uint32_t)(buf->ptr - buf->start); + } + DISASS("\n"); +} + +void allocMoreItems(void** ptr, uint32_t* nptr, size_t item_size, uint32_t add) { + byte* curbuf = *ptr; + uint32_t curcnt = *nptr; + size_t cursize = curcnt * item_size; + uint32_t newcnt = curcnt + add; + size_t newsize = newcnt * item_size; + byte* newbuf = (byte*)realloc(curbuf, newsize); + memset(newbuf + cursize, 0, newsize - cursize); + *ptr = newbuf; + *nptr = newcnt; +} + +uint32_t read_count(buffer_t* buf, uint32_t max, byte sectcode) { + uint32_t count = read_u32leb(buf); + DISASS("%u \t\t\t; count\n", count); + if (count > max) ERR("!expected count <= %d for %s section, got %d", max, section_name(sectcode), count); + return count; +} + +// A macro to read the count of entries, expand internal storage, and call {read_func} in a loop. +#define READ_ENTRIES(count_field, ptr_field, entry_type, read_func) do { \ + uint32_t count = read_count(buf, 100000, sectcode); \ + uint32_t j = module->count_field; \ + allocMoreItems((void**)&module->ptr_field, &module->count_field, sizeof(entry_type), count); \ + for (uint32_t i = 0; i < count; i++, j++) { \ + read_func(buf, &module->ptr_field[j], sectend); \ + } \ + } while (0) + + +// The main parsing routine. +int parse_wasm_module(buffer_t* buf, wasm_module_t* module) { + ssize_t len = 0; + + //==== Check magic word ============================================= + uint32_t magic = decode_u32(buf->ptr, buf->end, &len); + DISASS("read_magic = %x\n", magic); + if (len != 4 || magic != WASM_MAGIC) { + ERR("!invalid magic word, expected %x\n", WASM_MAGIC); + return -1; + } + buf->ptr += 4; + + //==== Check Wasm Version =========================================== + uint32_t version = decode_u32(buf->ptr, buf->end, &len); + DISASS("read_version = %x\n", version); + if (len != 4 || version != WASM_VERSION) { + ERR("!invalid Wasm version, expected %x\n", WASM_VERSION); + return -2; + } + buf->ptr += 4; + + //==== Read Wasm sections =========================================== + while (buf->ptr < buf->end) { + uint32_t sectlen = 0; + int sectcode = read_section_code(buf, module, §len); + if (sectcode < 0) return -3; + const byte* sectend = buf->ptr + sectlen; + + switch (sectcode) { + case WASM_SECT_TYPE: { + READ_ENTRIES(num_sigs, sigs, wasm_sig_decl_t, read_type_decl); + break; + } + case WASM_SECT_IMPORT: { + uint32_t count = read_count(buf, 1000, sectcode); + uint32_t import_index = module->num_imports; + uint32_t func_index = module->num_funcs; + // all imports must be functions. + allocMoreItems((void**)&module->imports, &module->num_imports, sizeof(wasm_import_decl_t), count); + allocMoreItems((void**)&module->funcs, &module->num_funcs, sizeof(wasm_func_decl_t), count); + for (uint32_t i = 0; i < count; i++, import_index++, func_index++) { + read_import_decl(buf, module, import_index, func_index, sectend); + } + break; + } + case WASM_SECT_FUNCTION: { + READ_ENTRIES(num_funcs, funcs, wasm_func_decl_t, read_func_decl); + break; + } + case WASM_SECT_TABLE: { + read_count(buf, 1, sectcode); + if (module->table != NULL) ERR("!repeated table section"); + module->table = (wasm_table_decl_t*)malloc(sizeof(wasm_table_decl_t)); + read_table_decl(buf, module->table, sectend); + break; + } + case WASM_SECT_MEMORY: { + read_count(buf, 1, sectcode); + read_memory_decl(buf, &module->mem_limits, sectend); + break; + } + case WASM_SECT_GLOBAL: { + READ_ENTRIES(num_globals, globals, wasm_global_decl_t, read_global_decl); + break; + } + case WASM_SECT_EXPORT: { + read_count(buf, 1, sectcode); + read_export_decl(buf, module, sectend); + break; + } + case WASM_SECT_START: { + uint32_t entry = read_u32leb(buf); + module->start_func = (int32_t)entry; + DISASS("%u\n", entry); + break; + } + case WASM_SECT_ELEMENT: { + READ_ENTRIES(num_elems, elems, wasm_elems_decl_t, read_elems_decl); + break; + } + case WASM_SECT_CODE: { + uint32_t num_bodies = module->num_funcs - module->num_imports; + uint32_t count = read_count(buf, num_bodies, sectcode); + if (count != num_bodies) ERR("!expected %d function bodies, got %d", num_bodies, count); + uint32_t func_index = module->num_imports; + for (uint32_t i = 0; i < count; i++, func_index++) { + read_code_decl(buf, &module->funcs[func_index], sectend); + } + break; + } + case WASM_SECT_DATA: { + READ_ENTRIES(num_data, data, wasm_data_decl_t, read_data_decl); + break; + } + default: + ERR("!unknown section constant 0x%02x\n", sectcode); + return -4; + } + CHECK(buf->ptr == sectend); // internal check + } + return 0; +} + diff --git a/rewrite.c b/rewrite.c new file mode 100644 index 0000000..21cf9ef --- /dev/null +++ b/rewrite.c @@ -0,0 +1,141 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> + +#include "common.h" +#include "vm.h" +#include "test.h" +#include "weewasm.h" +#include "illegal.h" +#include "ir.h" +#include "disass.h" + +typedef struct { + unsigned is_loop: 1; + uint32_t start_pc; + uint32_t num_refs; + uint32_t capacity; + int32_t** refs; +} control_entry_t; + +void ref_entry(control_entry_t* entry, byte* pcdelta) { + if (entry->num_refs >= entry->capacity) { + uint32_t ncapacity = 4 + entry->capacity * 2; + TRACE("ncapacity = %u\n", ncapacity); + entry->refs = (int32_t**)realloc(entry->refs, sizeof(int32_t*) * ncapacity); + entry->capacity = ncapacity; + } + entry->refs[entry->num_refs++] = (int32_t*)pcdelta; +} + +// Reads what should be a 4-byte LEB indicating a depth. +uint32_t read_label(buffer_t* buf) { + const byte* before = buf->ptr; + uint32_t result = read_u32leb(buf); + uint32_t size = (uint32_t)(buf->ptr - before); + if (size != 4) ERR("invalid weewasm @+%d: expected 4 byte label, got %u bytes", (int)(before - buf->start), size); + return result; +} + +// Rewrites "br*" to "jmp*" +void rewrite_brs(byte* start, byte* end) { + buffer_t onstack_buf = { start, start, end }; + buffer_t* buf = &onstack_buf; + + uint32_t control_sp = 0; + uint32_t capacity = 16; + control_entry_t* control_stack = calloc(sizeof(control_entry_t), 16); + + { + // push the initial control entry + control_entry_t* entry = &control_stack[control_sp++]; + entry->start_pc = (uint32_t)(buf->ptr - buf->start); + entry->num_refs = 0; + } + + // process all bytecodes, ignoring all but control flow + while (buf->ptr < buf->end) { + int pc = (int)(buf->ptr - buf->start); + byte b = *buf->ptr; + switch (b) { + case WASM_OP_BLOCK: // fall through + case WASM_OP_LOOP: { + TRACE("-> +%3d rewrite: control_block, depth=%d\n", pc, control_sp); + if (control_sp >= capacity) { + uint32_t ncapacity = capacity * 2; + control_stack = (control_entry_t*)realloc(control_stack, sizeof(control_entry_t) * ncapacity); + memset(&control_stack[control_sp], 0, sizeof(control_entry_t) * (ncapacity - control_sp)); + } + control_entry_t* entry = &control_stack[control_sp++]; + entry->is_loop = b == WASM_OP_LOOP; + entry->start_pc = (uint32_t)(buf->ptr - buf->start); + entry->num_refs = 0; + buf->ptr++; + read_i32leb(buf); // skip block type + break; + } + case WASM_OP_END: { + TRACE("-> +%-3d rewrite: end, depth=%d\n", pc, control_sp); + control_entry_t* entry = &control_stack[control_sp - 1]; + int32_t target_pc = entry->is_loop ? (int32_t)entry->start_pc : (int32_t)(buf->ptr - buf->start); + for (uint32_t i = 0; i < entry->num_refs; i++) { + int32_t ref_pc = (int32_t)((const byte*)entry->refs[i] - buf->start); + TRACE("-> +%-3d rewrite: patch => %d\n", ref_pc, (target_pc - ref_pc)); + *(entry->refs[i]) = target_pc - ref_pc; + } + buf->ptr++; + control_sp--; + break; + } + case WASM_OP_BR: { + *(byte*)buf->ptr = WASM_OP_JMP; + buf->ptr++; + byte* pcdelta = (byte*)buf->ptr; + uint32_t depth = read_label(buf); + TRACE("-> +%-3d rewrite: br %u\n", (int)(pcdelta - buf->start), depth); + if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br"); + control_entry_t* entry = &control_stack[control_sp - depth - 1]; + ref_entry(entry, pcdelta); + break; + } + case WASM_OP_BR_IF: { + *(byte*)buf->ptr = WASM_OP_JMP_IF; + buf->ptr++; + byte* pcdelta = (byte*)buf->ptr; + uint32_t depth = read_label(buf); + TRACE("-> +%-3d rewrite: br_if %u\n", (int)(pcdelta - buf->start), depth); + if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br_if"); + control_entry_t* entry = &control_stack[control_sp - depth - 1]; + ref_entry(entry, pcdelta); + break; + } + case WASM_OP_BR_TABLE: { + *(byte*)buf->ptr = WASM_OP_JMP_TABLE; + buf->ptr++; + uint32_t count = read_u32leb(buf); + for (uint32_t i = 0; i < count + 1; i++) { + byte* pcdelta = (byte*)buf->ptr; + uint32_t depth = read_label(buf); + TRACE("-> +%-3d rewrite: br_table[%u] %u\n", (int)(pcdelta - buf->start), i, depth); + if ((buf->ptr - pcdelta) < 4) ERR("!unpadded br_table"); + control_entry_t* entry = &control_stack[control_sp - depth - 1]; + ref_entry(entry, pcdelta); + } + break; + } + default: { + TRACE("-> +%-3d rewrite: ...\n", pc); + skip_bytecode(buf); + break; + } + } + } + + // free control stack memory + for (uint32_t i = 0; i < capacity; i++) { + free(control_stack[i].refs); + } + free(control_stack); +} diff --git a/tests/proj2/grade.sh b/tests/proj2/grade.sh new file mode 100755 index 0000000..66359e7 --- /dev/null +++ b/tests/proj2/grade.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +if [ $# = 0 ]; then + WEERUN='../../weerun' +else + WEERUN=$1 + shift +fi + +T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/} +mkdir -p $T + + +if [ ! -x "$WEERUN" ]; then + printf "##+weerun\n" + printf "##-fail, weerun not found: %s\n" $WEERUN + exit 1 +fi + +if [ $# = 0 ]; then + TESTS=$(ls tests/*.wee.wasm) +else + TESTS=$@ +fi + +# substitute for the "timeout" command on MacOS +function xtimeout { + timeout=$1 + shift + command=("$@") + ( + "${command[@]}" & + runnerpid=$! + trap -- '' SIGTERM + ( # killer job + sleep $timeout + if ps -p $runnerpid > /dev/null; then + echo "Timed out, killing" + kill -SIGKILL $runnerpid 2>/dev/null + fi + ) & + killerpid=$! + wait $runnerpid + kill -SIGKILL $killerpid + ) +} + +function run_one() { + echo $WEERUN $f $ARGS + xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR + # ignore case + diff -i $EXP $OUT > $DIFF + OK=$? + if [ ! -s $DIFF ]; then + # remove empty diffs + rm $DIFF + else + cat $DIFF + fi + + if [ $OK = 0 ]; then + return 0 + else + echo diff $EXP $OUT + printf "##-fail: $ARGS\n" + return 1 + fi + +} + +for f in $TESTS; do + # replace slashes with _ + t=${f//\//_} + # replace .wasm with .runs + runs=${f/%.wee.wasm/.runs} + + printf "##+%s\n" $t + + OUT=$T/$t.out + ERR=$T/$t.err + EXP=$T/$t.expect + DIFF=$T/$t.diff + + if [ -f $runs ]; then + # do multiple runs for this test + ok=1 + while IFS= read -r line + do + ARGS=$(echo $line | cut -d= -f1) + EXPECT=$(echo $line | cut -d= -f2) + echo $EXPECT > $EXP + + run_one + + if [ $? != 0 ]; then + ok=0 + break; + fi + done < $runs + if [ $ok = 1 ]; then + printf "##-ok\n" + fi + else + # do one run + e=${f/%.wee.wasm/.expect} + args=${f/%.wee.wasm/.args} + cp $e $EXP + + if [ -f $args ]; then + ARGS=$(cat $args) + else + ARGS="" + fi + + run_one + + if [ $? = 0 ]; then + printf "##-ok\n" + fi + fi +done diff --git a/tests/proj2/tests/add0.runs b/tests/proj2/tests/add0.runs new file mode 100644 index 0000000..e1a7ce1 --- /dev/null +++ b/tests/proj2/tests/add0.runs @@ -0,0 +1,7 @@ +8 9 = 17 +33 44 = 77 +111 222 = 333 +2222 3333 = 5555 +111111111 666666666 = 777777777 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = 71582788 diff --git a/tests/proj2/tests/add0.wasm b/tests/proj2/tests/add0.wasm Binary files differnew file mode 100644 index 0000000..cca89af --- /dev/null +++ b/tests/proj2/tests/add0.wasm diff --git a/tests/proj2/tests/add0.wat b/tests/proj2/tests/add0.wat new file mode 100644 index 0000000..cb46d02 --- /dev/null +++ b/tests/proj2/tests/add0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.add (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/add0.wee.wasm b/tests/proj2/tests/add0.wee.wasm Binary files differnew file mode 100644 index 0000000..d8ed0f6 --- /dev/null +++ b/tests/proj2/tests/add0.wee.wasm diff --git a/tests/proj2/tests/br0.expect b/tests/proj2/tests/br0.expect new file mode 100644 index 0000000..920a139 --- /dev/null +++ b/tests/proj2/tests/br0.expect @@ -0,0 +1 @@ +43 diff --git a/tests/proj2/tests/br0.wasm b/tests/proj2/tests/br0.wasm Binary files differnew file mode 100644 index 0000000..c71f1fb --- /dev/null +++ b/tests/proj2/tests/br0.wasm diff --git a/tests/proj2/tests/br0.wat b/tests/proj2/tests/br0.wat new file mode 100644 index 0000000..d4607f2 --- /dev/null +++ b/tests/proj2/tests/br0.wat @@ -0,0 +1,8 @@ +(module + (func (export "main") (result i32) + (block + (br 0) + ) + (i32.const 43) + ) +) diff --git a/tests/proj2/tests/br0.wee.wasm b/tests/proj2/tests/br0.wee.wasm Binary files differnew file mode 100644 index 0000000..83ec9f9 --- /dev/null +++ b/tests/proj2/tests/br0.wee.wasm diff --git a/tests/proj2/tests/br1.expect b/tests/proj2/tests/br1.expect new file mode 100644 index 0000000..abac1ea --- /dev/null +++ b/tests/proj2/tests/br1.expect @@ -0,0 +1 @@ +47 diff --git a/tests/proj2/tests/br1.wasm b/tests/proj2/tests/br1.wasm Binary files differnew file mode 100644 index 0000000..bb64ae0 --- /dev/null +++ b/tests/proj2/tests/br1.wasm diff --git a/tests/proj2/tests/br1.wat b/tests/proj2/tests/br1.wat new file mode 100644 index 0000000..0e6e1f6 --- /dev/null +++ b/tests/proj2/tests/br1.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (result i32) + (i32.const 47) + (br 0) + ) +) diff --git a/tests/proj2/tests/br1.wee.wasm b/tests/proj2/tests/br1.wee.wasm Binary files differnew file mode 100644 index 0000000..75de416 --- /dev/null +++ b/tests/proj2/tests/br1.wee.wasm diff --git a/tests/proj2/tests/br2.expect b/tests/proj2/tests/br2.expect new file mode 100644 index 0000000..95f9650 --- /dev/null +++ b/tests/proj2/tests/br2.expect @@ -0,0 +1 @@ +49 diff --git a/tests/proj2/tests/br2.wasm b/tests/proj2/tests/br2.wasm Binary files differnew file mode 100644 index 0000000..49568d1 --- /dev/null +++ b/tests/proj2/tests/br2.wasm diff --git a/tests/proj2/tests/br2.wat b/tests/proj2/tests/br2.wat new file mode 100644 index 0000000..05c1ad8 --- /dev/null +++ b/tests/proj2/tests/br2.wat @@ -0,0 +1,9 @@ +(module + (func (export "main") (result i32) + (block + (i32.const 49) + (br 1) + drop) + (i32.const 67) + ) +) diff --git a/tests/proj2/tests/br2.wee.wasm b/tests/proj2/tests/br2.wee.wasm Binary files differnew file mode 100644 index 0000000..cd769c4 --- /dev/null +++ b/tests/proj2/tests/br2.wee.wasm diff --git a/tests/proj2/tests/br3.expect b/tests/proj2/tests/br3.expect new file mode 100644 index 0000000..59343b0 --- /dev/null +++ b/tests/proj2/tests/br3.expect @@ -0,0 +1 @@ +53 diff --git a/tests/proj2/tests/br3.wasm b/tests/proj2/tests/br3.wasm Binary files differnew file mode 100644 index 0000000..22be754 --- /dev/null +++ b/tests/proj2/tests/br3.wasm diff --git a/tests/proj2/tests/br3.wat b/tests/proj2/tests/br3.wat new file mode 100644 index 0000000..b5872ab --- /dev/null +++ b/tests/proj2/tests/br3.wat @@ -0,0 +1,11 @@ +(module + (func (export "main") (result i32) + (block + (block + (i32.const 53) + (br 2) + drop) + ) + (i32.const 67) + ) +) diff --git a/tests/proj2/tests/br3.wee.wasm b/tests/proj2/tests/br3.wee.wasm Binary files differnew file mode 100644 index 0000000..17ab547 --- /dev/null +++ b/tests/proj2/tests/br3.wee.wasm diff --git a/tests/proj2/tests/br_if0.runs b/tests/proj2/tests/br_if0.runs new file mode 100644 index 0000000..cf65396 --- /dev/null +++ b/tests/proj2/tests/br_if0.runs @@ -0,0 +1,3 @@ +0 = 57 +1 = 46 +87234 = 46 diff --git a/tests/proj2/tests/br_if0.wasm b/tests/proj2/tests/br_if0.wasm Binary files differnew file mode 100644 index 0000000..4e6e06a --- /dev/null +++ b/tests/proj2/tests/br_if0.wasm diff --git a/tests/proj2/tests/br_if0.wat b/tests/proj2/tests/br_if0.wat new file mode 100644 index 0000000..a07f636 --- /dev/null +++ b/tests/proj2/tests/br_if0.wat @@ -0,0 +1,8 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.const 46) + (br_if 0 (local.get 0)) + (drop) + (i32.const 57) + ) +)
\ No newline at end of file diff --git a/tests/proj2/tests/br_if0.wee.wasm b/tests/proj2/tests/br_if0.wee.wasm Binary files differnew file mode 100644 index 0000000..552356f --- /dev/null +++ b/tests/proj2/tests/br_if0.wee.wasm diff --git a/tests/proj2/tests/br_if1.runs b/tests/proj2/tests/br_if1.runs new file mode 100644 index 0000000..a47419c --- /dev/null +++ b/tests/proj2/tests/br_if1.runs @@ -0,0 +1,7 @@ +0 0 = 66 +1 0 = 44 +0 1 = 55 +-1 0 = 44 +0 -1 = 55 +98237 55 = 44 +0 982345 = 55 diff --git a/tests/proj2/tests/br_if1.wasm b/tests/proj2/tests/br_if1.wasm Binary files differnew file mode 100644 index 0000000..e1df9fa --- /dev/null +++ b/tests/proj2/tests/br_if1.wasm diff --git a/tests/proj2/tests/br_if1.wat b/tests/proj2/tests/br_if1.wat new file mode 100644 index 0000000..82d9c07 --- /dev/null +++ b/tests/proj2/tests/br_if1.wat @@ -0,0 +1,11 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.const 44) + (br_if 0 (local.get 0)) + (drop) + (i32.const 55) + (br_if 0 (local.get 1)) + (drop) + (i32.const 66) + ) +)
\ No newline at end of file diff --git a/tests/proj2/tests/br_if1.wee.wasm b/tests/proj2/tests/br_if1.wee.wasm Binary files differnew file mode 100644 index 0000000..5db77d6 --- /dev/null +++ b/tests/proj2/tests/br_if1.wee.wasm diff --git a/tests/proj2/tests/br_if2.runs b/tests/proj2/tests/br_if2.runs new file mode 100644 index 0000000..581af19 --- /dev/null +++ b/tests/proj2/tests/br_if2.runs @@ -0,0 +1,8 @@ +0 0 0 = 44 +1 0 0 = 11 +0 1 0 = 22 +0 0 1 = 33 +1 0 0 = 11 +1 1 0 = 11 +1 1 1 = 11 +0 1 1 = 22 diff --git a/tests/proj2/tests/br_if2.wasm b/tests/proj2/tests/br_if2.wasm Binary files differnew file mode 100644 index 0000000..08e61b5 --- /dev/null +++ b/tests/proj2/tests/br_if2.wasm diff --git a/tests/proj2/tests/br_if2.wat b/tests/proj2/tests/br_if2.wat new file mode 100644 index 0000000..bd2d810 --- /dev/null +++ b/tests/proj2/tests/br_if2.wat @@ -0,0 +1,16 @@ +(module + (func (export "main") (param i32 i32 i32) (result i32) + (block + (i32.const 11) + (br_if 1 (local.get 0)) + (drop) + (i32.const 22) + (br_if 1 (local.get 1)) + (drop) + (i32.const 33) + (br_if 1 (local.get 2)) + (drop) + ) + (i32.const 44) + ) +) diff --git a/tests/proj2/tests/br_if2.wee.wasm b/tests/proj2/tests/br_if2.wee.wasm Binary files differnew file mode 100644 index 0000000..db48ae7 --- /dev/null +++ b/tests/proj2/tests/br_if2.wee.wasm diff --git a/tests/proj2/tests/br_table0.runs b/tests/proj2/tests/br_table0.runs new file mode 100644 index 0000000..deffe69 --- /dev/null +++ b/tests/proj2/tests/br_table0.runs @@ -0,0 +1,3 @@ +0 = 94 +-1 = 94 +23434 = 94 diff --git a/tests/proj2/tests/br_table0.wasm b/tests/proj2/tests/br_table0.wasm Binary files differnew file mode 100644 index 0000000..660eb49 --- /dev/null +++ b/tests/proj2/tests/br_table0.wasm diff --git a/tests/proj2/tests/br_table0.wat b/tests/proj2/tests/br_table0.wat new file mode 100644 index 0000000..7aa020f --- /dev/null +++ b/tests/proj2/tests/br_table0.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.const 94) + (br_table 0 (local.get 0) ) + ) +) diff --git a/tests/proj2/tests/br_table0.wee.wasm b/tests/proj2/tests/br_table0.wee.wasm Binary files differnew file mode 100644 index 0000000..7cf29af --- /dev/null +++ b/tests/proj2/tests/br_table0.wee.wasm diff --git a/tests/proj2/tests/br_table1.runs b/tests/proj2/tests/br_table1.runs new file mode 100644 index 0000000..11d1cc5 --- /dev/null +++ b/tests/proj2/tests/br_table1.runs @@ -0,0 +1,6 @@ +0 = 93 +1 = 93 +2 = 93 +3 = 93 +-1 = 93 +23434 = 93 diff --git a/tests/proj2/tests/br_table1.wasm b/tests/proj2/tests/br_table1.wasm Binary files differnew file mode 100644 index 0000000..dc8ae2a --- /dev/null +++ b/tests/proj2/tests/br_table1.wasm diff --git a/tests/proj2/tests/br_table1.wat b/tests/proj2/tests/br_table1.wat new file mode 100644 index 0000000..31bd3c5 --- /dev/null +++ b/tests/proj2/tests/br_table1.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.const 93) + (br_table 0 0 (local.get 0) ) + ) +) diff --git a/tests/proj2/tests/br_table1.wee.wasm b/tests/proj2/tests/br_table1.wee.wasm Binary files differnew file mode 100644 index 0000000..90f6628 --- /dev/null +++ b/tests/proj2/tests/br_table1.wee.wasm diff --git a/tests/proj2/tests/br_table2.runs b/tests/proj2/tests/br_table2.runs new file mode 100644 index 0000000..8524df6 --- /dev/null +++ b/tests/proj2/tests/br_table2.runs @@ -0,0 +1,12 @@ +0 = 92 +1 = 92 +2 = 92 +3 = 92 +4 = 92 +5 = 92 +5 = 92 +6 = 92 +7 = 92 +8 = 92 +-1 = 92 +23434 = 92 diff --git a/tests/proj2/tests/br_table2.wasm b/tests/proj2/tests/br_table2.wasm Binary files differnew file mode 100644 index 0000000..2912524 --- /dev/null +++ b/tests/proj2/tests/br_table2.wasm diff --git a/tests/proj2/tests/br_table2.wat b/tests/proj2/tests/br_table2.wat new file mode 100644 index 0000000..eb73907 --- /dev/null +++ b/tests/proj2/tests/br_table2.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.const 92) + (br_table 0 0 0 0 0 0 0 0 0 0 0 (local.get 0) ) + ) +) diff --git a/tests/proj2/tests/br_table2.wee.wasm b/tests/proj2/tests/br_table2.wee.wasm Binary files differnew file mode 100644 index 0000000..f6c9b55 --- /dev/null +++ b/tests/proj2/tests/br_table2.wee.wasm diff --git a/tests/proj2/tests/br_table3.runs b/tests/proj2/tests/br_table3.runs new file mode 100644 index 0000000..2bcccc4 --- /dev/null +++ b/tests/proj2/tests/br_table3.runs @@ -0,0 +1,6 @@ +0 = 22 +1 = 20 +11 = 20 +-1 = 20 +-100 = 20 +-1 = 20 diff --git a/tests/proj2/tests/br_table3.wasm b/tests/proj2/tests/br_table3.wasm Binary files differnew file mode 100644 index 0000000..c2d8b97 --- /dev/null +++ b/tests/proj2/tests/br_table3.wasm diff --git a/tests/proj2/tests/br_table3.wat b/tests/proj2/tests/br_table3.wat new file mode 100644 index 0000000..e6e71a6 --- /dev/null +++ b/tests/proj2/tests/br_table3.wat @@ -0,0 +1,12 @@ +(module + (func (export "main") (param i32) (result i32) + (block + (block + (br_table 1 0 (local.get 0)) + (return (i32.const 21)) + ) + (return (i32.const 20)) + ) + (i32.const 22) + ) +)
\ No newline at end of file diff --git a/tests/proj2/tests/br_table3.wee.wasm b/tests/proj2/tests/br_table3.wee.wasm Binary files differnew file mode 100644 index 0000000..423cbdc --- /dev/null +++ b/tests/proj2/tests/br_table3.wee.wasm diff --git a/tests/proj2/tests/br_table4.runs b/tests/proj2/tests/br_table4.runs new file mode 100644 index 0000000..9c5bf64 --- /dev/null +++ b/tests/proj2/tests/br_table4.runs @@ -0,0 +1,24 @@ +0 = 45 +1 = 46 +2 = 47 +3 = 48 +4 = 49 +5 = 56 +6 = 56 +7 = 49 +8 = 48 +9 = 47 +10 = 46 +11 = 45 +12 = 45 +13 = 45 +14 = 46 +15 = 46 +16 = 47 +17 = 47 +18 = 47 +19 = 47 +20 = 47 +21 = 47 +22 = 47 +23 = 47 diff --git a/tests/proj2/tests/br_table4.wasm b/tests/proj2/tests/br_table4.wasm Binary files differnew file mode 100644 index 0000000..5ed1ddf --- /dev/null +++ b/tests/proj2/tests/br_table4.wasm diff --git a/tests/proj2/tests/br_table4.wat b/tests/proj2/tests/br_table4.wat new file mode 100644 index 0000000..6b1d0b0 --- /dev/null +++ b/tests/proj2/tests/br_table4.wat @@ -0,0 +1,19 @@ +(module + (func (export "main") (param i32) (result i32) + (block + (block + (block + (block + (block + (block + (br_table 0 1 2 3 4 5 5 4 3 2 1 0 0 0 1 1 2 2 (local.get 0) + ) (return (i32.const 44)) + ) (return (i32.const 45)) + ) (return (i32.const 46)) + ) (return (i32.const 47)) + ) (return (i32.const 48)) + ) (return (i32.const 49)) + ) + (i32.const 56) + ) +) diff --git a/tests/proj2/tests/br_table4.wee.wasm b/tests/proj2/tests/br_table4.wee.wasm Binary files differnew file mode 100644 index 0000000..3357ef9 --- /dev/null +++ b/tests/proj2/tests/br_table4.wee.wasm diff --git a/tests/proj2/tests/build.sh b/tests/proj2/tests/build.sh new file mode 100755 index 0000000..a319aba --- /dev/null +++ b/tests/proj2/tests/build.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" +done +DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + +PROJ2=$(cd $DIR/.. && pwd) +WEEIFY=$PROJ2/weeify + +WAT2WASM=$(which wat2wasm) + +if [[ ! -x $WAT2WASM ]]; then + echo Error: wat2asm not found in PATH + exit 1 +fi + +if [[ ! -x $WEEIFY ]]; then + echo Error: weeify not found $DIR + exit 1 +fi + +if [ $# = 0 ]; then + FILES="*.wat" +else + FILES="$@" +fi + +for f in $FILES; do + wat2wasm $f + $WEEIFY -o ${f/%.wat/.wee.wasm} ${f/%.wat/.wasm} +done diff --git a/tests/proj2/tests/call0.expect b/tests/proj2/tests/call0.expect new file mode 100644 index 0000000..8643cf6 --- /dev/null +++ b/tests/proj2/tests/call0.expect @@ -0,0 +1 @@ +89 diff --git a/tests/proj2/tests/call0.wasm b/tests/proj2/tests/call0.wasm Binary files differnew file mode 100644 index 0000000..6113dd9 --- /dev/null +++ b/tests/proj2/tests/call0.wasm diff --git a/tests/proj2/tests/call0.wat b/tests/proj2/tests/call0.wat new file mode 100644 index 0000000..89e4b50 --- /dev/null +++ b/tests/proj2/tests/call0.wat @@ -0,0 +1,6 @@ +(module + (func $k (result i32) (i32.const 89)) + (func (export "main") (result i32) + (call $k) + ) +) diff --git a/tests/proj2/tests/call0.wee.wasm b/tests/proj2/tests/call0.wee.wasm Binary files differnew file mode 100644 index 0000000..1918f0e --- /dev/null +++ b/tests/proj2/tests/call0.wee.wasm diff --git a/tests/proj2/tests/call1.runs b/tests/proj2/tests/call1.runs new file mode 100644 index 0000000..ba9f624 --- /dev/null +++ b/tests/proj2/tests/call1.runs @@ -0,0 +1,2 @@ +7 = 7 +-999 = -999 diff --git a/tests/proj2/tests/call1.wasm b/tests/proj2/tests/call1.wasm Binary files differnew file mode 100644 index 0000000..3b36b7f --- /dev/null +++ b/tests/proj2/tests/call1.wasm diff --git a/tests/proj2/tests/call1.wat b/tests/proj2/tests/call1.wat new file mode 100644 index 0000000..8720016 --- /dev/null +++ b/tests/proj2/tests/call1.wat @@ -0,0 +1,6 @@ +(module + (func $id (param i32) (result i32) (local.get 0)) + (func (export "main") (param i32) (result i32) + (call $id (local.get 0)) + ) +) diff --git a/tests/proj2/tests/call1.wee.wasm b/tests/proj2/tests/call1.wee.wasm Binary files differnew file mode 100644 index 0000000..e4375ef --- /dev/null +++ b/tests/proj2/tests/call1.wee.wasm diff --git a/tests/proj2/tests/call2.runs b/tests/proj2/tests/call2.runs new file mode 100644 index 0000000..822ea93 --- /dev/null +++ b/tests/proj2/tests/call2.runs @@ -0,0 +1,2 @@ +7 6 = 13 +-999 -222222 = -223221 diff --git a/tests/proj2/tests/call2.wasm b/tests/proj2/tests/call2.wasm Binary files differnew file mode 100644 index 0000000..78280f6 --- /dev/null +++ b/tests/proj2/tests/call2.wasm diff --git a/tests/proj2/tests/call2.wat b/tests/proj2/tests/call2.wat new file mode 100644 index 0000000..e7408eb --- /dev/null +++ b/tests/proj2/tests/call2.wat @@ -0,0 +1,8 @@ +(module + (func $add (param i32 i32) (result i32) + (i32.add (local.get 0) (local.get 1)) + ) + (func (export "main") (param i32 i32) (result i32) + (call $add (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/call2.wee.wasm b/tests/proj2/tests/call2.wee.wasm Binary files differnew file mode 100644 index 0000000..ba64251 --- /dev/null +++ b/tests/proj2/tests/call2.wee.wasm diff --git a/tests/proj2/tests/call3.runs b/tests/proj2/tests/call3.runs new file mode 100644 index 0000000..b6462f5 --- /dev/null +++ b/tests/proj2/tests/call3.runs @@ -0,0 +1,2 @@ +7678 = 7678 +-999333 = -999333 diff --git a/tests/proj2/tests/call3.wasm b/tests/proj2/tests/call3.wasm Binary files differnew file mode 100644 index 0000000..9feb093 --- /dev/null +++ b/tests/proj2/tests/call3.wasm diff --git a/tests/proj2/tests/call3.wat b/tests/proj2/tests/call3.wat new file mode 100644 index 0000000..2a48f27 --- /dev/null +++ b/tests/proj2/tests/call3.wat @@ -0,0 +1,15 @@ +(module + (func $id (param i32 i32 i32 i32 i32 i32 i32 i32) (result i32) (local.get 3)) + (func (export "main") (param i32) (result i32) + (call $id + (i32.const 122) + (i32.const 223) + (i32.const 3424) + (local.get 0) + (i32.const 5525) + (i32.const 6626) + (i32.const 777727) + (i32.const 99928) + ) + ) +) diff --git a/tests/proj2/tests/call3.wee.wasm b/tests/proj2/tests/call3.wee.wasm Binary files differnew file mode 100644 index 0000000..4f48e99 --- /dev/null +++ b/tests/proj2/tests/call3.wee.wasm diff --git a/tests/proj2/tests/call4.expect b/tests/proj2/tests/call4.expect new file mode 100644 index 0000000..8124ca2 --- /dev/null +++ b/tests/proj2/tests/call4.expect @@ -0,0 +1 @@ +2079 diff --git a/tests/proj2/tests/call4.wasm b/tests/proj2/tests/call4.wasm Binary files differnew file mode 100644 index 0000000..6513cf2 --- /dev/null +++ b/tests/proj2/tests/call4.wasm diff --git a/tests/proj2/tests/call4.wat b/tests/proj2/tests/call4.wat new file mode 100644 index 0000000..158966f --- /dev/null +++ b/tests/proj2/tests/call4.wat @@ -0,0 +1,8 @@ +(module + (func $f1 (result i32) (i32.const 31)) + (func $f2 (result i32) (i32.const 32)) + (func $f3 (result i32) (i32.const 33)) + (func (export "main") (result i32) + (i32.mul (i32.add (call $f1) (call $f2)) (call $f3)) + ) +) diff --git a/tests/proj2/tests/call4.wee.wasm b/tests/proj2/tests/call4.wee.wasm Binary files differnew file mode 100644 index 0000000..bb9cd03 --- /dev/null +++ b/tests/proj2/tests/call4.wee.wasm diff --git a/tests/proj2/tests/call_indirect0.runs b/tests/proj2/tests/call_indirect0.runs new file mode 100644 index 0000000..9b03289 --- /dev/null +++ b/tests/proj2/tests/call_indirect0.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj2/tests/call_indirect0.wasm b/tests/proj2/tests/call_indirect0.wasm Binary files differnew file mode 100644 index 0000000..d7c7c67 --- /dev/null +++ b/tests/proj2/tests/call_indirect0.wasm diff --git a/tests/proj2/tests/call_indirect0.wat b/tests/proj2/tests/call_indirect0.wat new file mode 100644 index 0000000..37edb31 --- /dev/null +++ b/tests/proj2/tests/call_indirect0.wat @@ -0,0 +1,7 @@ +(module + (table 5 funcref) + (type $v_i (func (result i32))) + (func (export "main") (param i32) (result i32) + (call_indirect (type $v_i) (local.get 0)) + ) +) diff --git a/tests/proj2/tests/call_indirect0.wee.wasm b/tests/proj2/tests/call_indirect0.wee.wasm Binary files differnew file mode 100644 index 0000000..48e45ef --- /dev/null +++ b/tests/proj2/tests/call_indirect0.wee.wasm diff --git a/tests/proj2/tests/call_indirect1.runs b/tests/proj2/tests/call_indirect1.runs new file mode 100644 index 0000000..9b03289 --- /dev/null +++ b/tests/proj2/tests/call_indirect1.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj2/tests/call_indirect1.wasm b/tests/proj2/tests/call_indirect1.wasm Binary files differnew file mode 100644 index 0000000..3b19b42 --- /dev/null +++ b/tests/proj2/tests/call_indirect1.wasm diff --git a/tests/proj2/tests/call_indirect1.wat b/tests/proj2/tests/call_indirect1.wat new file mode 100644 index 0000000..2a4fd5a --- /dev/null +++ b/tests/proj2/tests/call_indirect1.wat @@ -0,0 +1,7 @@ +(module + (table funcref (elem $main)) + (type $v_i (func (result i32))) + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_i) (local.get 0)) + ) +) diff --git a/tests/proj2/tests/call_indirect1.wee.wasm b/tests/proj2/tests/call_indirect1.wee.wasm Binary files differnew file mode 100644 index 0000000..086c0d5 --- /dev/null +++ b/tests/proj2/tests/call_indirect1.wee.wasm diff --git a/tests/proj2/tests/call_indirect2.runs b/tests/proj2/tests/call_indirect2.runs new file mode 100644 index 0000000..555bc01 --- /dev/null +++ b/tests/proj2/tests/call_indirect2.runs @@ -0,0 +1,8 @@ +0 = 11 +1 = 22 +2 = 33 +3 = 44 +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj2/tests/call_indirect2.wasm b/tests/proj2/tests/call_indirect2.wasm Binary files differnew file mode 100644 index 0000000..d422ab0 --- /dev/null +++ b/tests/proj2/tests/call_indirect2.wasm diff --git a/tests/proj2/tests/call_indirect2.wat b/tests/proj2/tests/call_indirect2.wat new file mode 100644 index 0000000..a803113 --- /dev/null +++ b/tests/proj2/tests/call_indirect2.wat @@ -0,0 +1,13 @@ +(module + (table funcref (elem $f11 $f22 $f33 $f44 $main)) + (type $v_i (func (result i32))) + + (func $f11 (result i32) (i32.const 11)) + (func $f22 (result i32) (i32.const 22)) + (func $f33 (result i32) (i32.const 33)) + (func $f44 (result i32) (i32.const 44)) + + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_i) (local.get 0)) + ) +) diff --git a/tests/proj2/tests/call_indirect2.wee.wasm b/tests/proj2/tests/call_indirect2.wee.wasm Binary files differnew file mode 100644 index 0000000..892331a --- /dev/null +++ b/tests/proj2/tests/call_indirect2.wee.wasm diff --git a/tests/proj2/tests/call_indirect3.runs b/tests/proj2/tests/call_indirect3.runs new file mode 100644 index 0000000..c9c03d9 --- /dev/null +++ b/tests/proj2/tests/call_indirect3.runs @@ -0,0 +1,5 @@ +22 33 0 = 55 +11 44 1 = -33 +-5 -5 2 = 25 +-5 -5 3 = !trap +-9 0 4 = !trap diff --git a/tests/proj2/tests/call_indirect3.wasm b/tests/proj2/tests/call_indirect3.wasm Binary files differnew file mode 100644 index 0000000..2085d03 --- /dev/null +++ b/tests/proj2/tests/call_indirect3.wasm diff --git a/tests/proj2/tests/call_indirect3.wat b/tests/proj2/tests/call_indirect3.wat new file mode 100644 index 0000000..c94152b --- /dev/null +++ b/tests/proj2/tests/call_indirect3.wat @@ -0,0 +1,13 @@ +(module + (table funcref (elem $fadd $fsub $fmul $fnone)) + (type $ii_i (func (param i32 i32) (result i32))) + + (func $fadd (param i32 i32) (result i32) (i32.add (local.get 0) (local.get 1))) + (func $fsub (param i32 i32) (result i32) (i32.sub (local.get 0) (local.get 1))) + (func $fmul (param i32 i32) (result i32) (i32.mul (local.get 0) (local.get 1))) + (func $fnone (result i32) unreachable) + + (func $main (export "main") (param i32 i32 i32) (result i32) + (call_indirect (type $ii_i) (local.get 0) (local.get 1) (local.get 2)) + ) +) diff --git a/tests/proj2/tests/call_indirect3.wee.wasm b/tests/proj2/tests/call_indirect3.wee.wasm Binary files differnew file mode 100644 index 0000000..c48139b --- /dev/null +++ b/tests/proj2/tests/call_indirect3.wee.wasm diff --git a/tests/proj2/tests/const0.expect b/tests/proj2/tests/const0.expect new file mode 100644 index 0000000..d81cc07 --- /dev/null +++ b/tests/proj2/tests/const0.expect @@ -0,0 +1 @@ +42 diff --git a/tests/proj2/tests/const0.wasm b/tests/proj2/tests/const0.wasm Binary files differnew file mode 100644 index 0000000..cf66851 --- /dev/null +++ b/tests/proj2/tests/const0.wasm diff --git a/tests/proj2/tests/const0.wat b/tests/proj2/tests/const0.wat new file mode 100644 index 0000000..017c6ad --- /dev/null +++ b/tests/proj2/tests/const0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (result i32) + (i32.const 42) + ) +) diff --git a/tests/proj2/tests/const0.wee.wasm b/tests/proj2/tests/const0.wee.wasm Binary files differnew file mode 100644 index 0000000..e104207 --- /dev/null +++ b/tests/proj2/tests/const0.wee.wasm diff --git a/tests/proj2/tests/const1.expect b/tests/proj2/tests/const1.expect new file mode 100644 index 0000000..16eac31 --- /dev/null +++ b/tests/proj2/tests/const1.expect @@ -0,0 +1 @@ +-993423 diff --git a/tests/proj2/tests/const1.wasm b/tests/proj2/tests/const1.wasm Binary files differnew file mode 100644 index 0000000..8dae0b9 --- /dev/null +++ b/tests/proj2/tests/const1.wasm diff --git a/tests/proj2/tests/const1.wat b/tests/proj2/tests/const1.wat new file mode 100644 index 0000000..946e5e3 --- /dev/null +++ b/tests/proj2/tests/const1.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (result i32) + (i32.const -993423) + ) +) diff --git a/tests/proj2/tests/const1.wee.wasm b/tests/proj2/tests/const1.wee.wasm Binary files differnew file mode 100644 index 0000000..59d36e6 --- /dev/null +++ b/tests/proj2/tests/const1.wee.wasm diff --git a/tests/proj2/tests/const2_d.expect b/tests/proj2/tests/const2_d.expect new file mode 100644 index 0000000..2a68415 --- /dev/null +++ b/tests/proj2/tests/const2_d.expect @@ -0,0 +1 @@ +-99.750000 diff --git a/tests/proj2/tests/const2_d.wasm b/tests/proj2/tests/const2_d.wasm Binary files differnew file mode 100644 index 0000000..56b1adb --- /dev/null +++ b/tests/proj2/tests/const2_d.wasm diff --git a/tests/proj2/tests/const2_d.wat b/tests/proj2/tests/const2_d.wat new file mode 100644 index 0000000..49ee329 --- /dev/null +++ b/tests/proj2/tests/const2_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (result f64) + (f64.const -99.75) + ) +) diff --git a/tests/proj2/tests/const2_d.wee.wasm b/tests/proj2/tests/const2_d.wee.wasm Binary files differnew file mode 100644 index 0000000..329e5c6 --- /dev/null +++ b/tests/proj2/tests/const2_d.wee.wasm diff --git a/tests/proj2/tests/div0.runs b/tests/proj2/tests/div0.runs new file mode 100644 index 0000000..931ca6c --- /dev/null +++ b/tests/proj2/tests/div0.runs @@ -0,0 +1,5 @@ +5555 1111 = 5 +-77777777 11111111 = -7 +-77777777 11111 = -7000 +-2147483648 -1 = !trap +333 0 = !trap diff --git a/tests/proj2/tests/div0.wasm b/tests/proj2/tests/div0.wasm Binary files differnew file mode 100644 index 0000000..1800629 --- /dev/null +++ b/tests/proj2/tests/div0.wasm diff --git a/tests/proj2/tests/div0.wat b/tests/proj2/tests/div0.wat new file mode 100644 index 0000000..98288d7 --- /dev/null +++ b/tests/proj2/tests/div0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.div_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/div0.wee.wasm b/tests/proj2/tests/div0.wee.wasm Binary files differnew file mode 100644 index 0000000..95dc30b --- /dev/null +++ b/tests/proj2/tests/div0.wee.wasm diff --git a/tests/proj2/tests/ec_putd0.expect b/tests/proj2/tests/ec_putd0.expect new file mode 100644 index 0000000..53060c2 --- /dev/null +++ b/tests/proj2/tests/ec_putd0.expect @@ -0,0 +1 @@ +1.0987656677 diff --git a/tests/proj2/tests/ec_putd0.wasm b/tests/proj2/tests/ec_putd0.wasm Binary files differnew file mode 100644 index 0000000..7ad02fa --- /dev/null +++ b/tests/proj2/tests/ec_putd0.wasm diff --git a/tests/proj2/tests/ec_putd0.wat b/tests/proj2/tests/ec_putd0.wat new file mode 100644 index 0000000..7ac255d --- /dev/null +++ b/tests/proj2/tests/ec_putd0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "putd" (func $putd (param f64))) + (func (export "main") (result i32) + (call $putd (f64.const 1.098765)) + (i32.const 6677) + ) +) diff --git a/tests/proj2/tests/ec_putd0.wee.wasm b/tests/proj2/tests/ec_putd0.wee.wasm Binary files differnew file mode 100644 index 0000000..fb170b1 --- /dev/null +++ b/tests/proj2/tests/ec_putd0.wee.wasm diff --git a/tests/proj2/tests/ec_putd1.expect b/tests/proj2/tests/ec_putd1.expect new file mode 100644 index 0000000..97c54c2 --- /dev/null +++ b/tests/proj2/tests/ec_putd1.expect @@ -0,0 +1 @@ +1.098765-1.333333-333.4444441122 diff --git a/tests/proj2/tests/ec_putd1.wasm b/tests/proj2/tests/ec_putd1.wasm Binary files differnew file mode 100644 index 0000000..b19378f --- /dev/null +++ b/tests/proj2/tests/ec_putd1.wasm diff --git a/tests/proj2/tests/ec_putd1.wat b/tests/proj2/tests/ec_putd1.wat new file mode 100644 index 0000000..1c75d87 --- /dev/null +++ b/tests/proj2/tests/ec_putd1.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "putd" (func $putd (param f64))) + (func (export "main") (result i32) + (call $putd (f64.const 1.098765)) + (call $putd (f64.const -1.333333)) + (call $putd (f64.const -333.444444)) + (i32.const 1122) + ) +) diff --git a/tests/proj2/tests/ec_putd1.wee.wasm b/tests/proj2/tests/ec_putd1.wee.wasm Binary files differnew file mode 100644 index 0000000..d137705 --- /dev/null +++ b/tests/proj2/tests/ec_putd1.wee.wasm diff --git a/tests/proj2/tests/ec_puti0.expect b/tests/proj2/tests/ec_puti0.expect new file mode 100644 index 0000000..209cee3 --- /dev/null +++ b/tests/proj2/tests/ec_puti0.expect @@ -0,0 +1 @@ +4647 diff --git a/tests/proj2/tests/ec_puti0.wasm b/tests/proj2/tests/ec_puti0.wasm Binary files differnew file mode 100644 index 0000000..8c67c22 --- /dev/null +++ b/tests/proj2/tests/ec_puti0.wasm diff --git a/tests/proj2/tests/ec_puti0.wat b/tests/proj2/tests/ec_puti0.wat new file mode 100644 index 0000000..a42fc37 --- /dev/null +++ b/tests/proj2/tests/ec_puti0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "puti" (func $puti (param i32))) + (func (export "main") (result i32) + (call $puti (i32.const 46)) + (i32.const 47) + ) +) diff --git a/tests/proj2/tests/ec_puti0.wee.wasm b/tests/proj2/tests/ec_puti0.wee.wasm Binary files differnew file mode 100644 index 0000000..8b87e4b --- /dev/null +++ b/tests/proj2/tests/ec_puti0.wee.wasm diff --git a/tests/proj2/tests/ec_puti1.expect b/tests/proj2/tests/ec_puti1.expect new file mode 100644 index 0000000..f45c7ba --- /dev/null +++ b/tests/proj2/tests/ec_puti1.expect @@ -0,0 +1 @@ +46931111666 diff --git a/tests/proj2/tests/ec_puti1.wasm b/tests/proj2/tests/ec_puti1.wasm Binary files differnew file mode 100644 index 0000000..ec0001d --- /dev/null +++ b/tests/proj2/tests/ec_puti1.wasm diff --git a/tests/proj2/tests/ec_puti1.wat b/tests/proj2/tests/ec_puti1.wat new file mode 100644 index 0000000..a9288c2 --- /dev/null +++ b/tests/proj2/tests/ec_puti1.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "puti" (func $puti (param i32))) + (func (export "main") (result i32) + (call $puti (i32.const 46)) + (call $puti (i32.const 93)) + (call $puti (i32.const 1111)) + (i32.const 666) + ) +) diff --git a/tests/proj2/tests/ec_puti1.wee.wasm b/tests/proj2/tests/ec_puti1.wee.wasm Binary files differnew file mode 100644 index 0000000..84cbec1 --- /dev/null +++ b/tests/proj2/tests/ec_puti1.wee.wasm diff --git a/tests/proj2/tests/ec_puts0.expect b/tests/proj2/tests/ec_puts0.expect new file mode 100644 index 0000000..b0325db --- /dev/null +++ b/tests/proj2/tests/ec_puts0.expect @@ -0,0 +1,2 @@ +Hello World! +57 diff --git a/tests/proj2/tests/ec_puts0.wasm b/tests/proj2/tests/ec_puts0.wasm Binary files differnew file mode 100644 index 0000000..5d22328 --- /dev/null +++ b/tests/proj2/tests/ec_puts0.wasm diff --git a/tests/proj2/tests/ec_puts0.wat b/tests/proj2/tests/ec_puts0.wat new file mode 100644 index 0000000..9c318b0 --- /dev/null +++ b/tests/proj2/tests/ec_puts0.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "puts" (func $puts (param i32 i32))) + (memory 1) + (data (i32.const 1024) "Hello World!\n") + (func (export "main") (result i32) + (call $puts (i32.const 1024) (i32.const 13)) + (i32.const 57) + ) +) diff --git a/tests/proj2/tests/ec_puts0.wee.wasm b/tests/proj2/tests/ec_puts0.wee.wasm Binary files differnew file mode 100644 index 0000000..bdcb32d --- /dev/null +++ b/tests/proj2/tests/ec_puts0.wee.wasm diff --git a/tests/proj2/tests/f64.add0_d.runs b/tests/proj2/tests/f64.add0_d.runs new file mode 100644 index 0000000..51f77e8 --- /dev/null +++ b/tests/proj2/tests/f64.add0_d.runs @@ -0,0 +1,3 @@ +0d 1d = 1.000000 +0.25d -1.75d = -1.500000 +489728.83423d -782374.47d = -292645.635770 diff --git a/tests/proj2/tests/f64.add0_d.wasm b/tests/proj2/tests/f64.add0_d.wasm Binary files differnew file mode 100644 index 0000000..b1f7bb1 --- /dev/null +++ b/tests/proj2/tests/f64.add0_d.wasm diff --git a/tests/proj2/tests/f64.add0_d.wat b/tests/proj2/tests/f64.add0_d.wat new file mode 100644 index 0000000..ca0535e --- /dev/null +++ b/tests/proj2/tests/f64.add0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result f64) + (f64.add (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.add0_d.wee.wasm b/tests/proj2/tests/f64.add0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..7f05025 --- /dev/null +++ b/tests/proj2/tests/f64.add0_d.wee.wasm diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.runs b/tests/proj2/tests/f64.convert_i32_s0_d.runs new file mode 100644 index 0000000..4994fdd --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_s0_d.runs @@ -0,0 +1,4 @@ +0 = 0.000000 +1 = 1.000000 +-87234 = -87234.000000 +-2147483648 = -2147483648.000000 diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wasm b/tests/proj2/tests/f64.convert_i32_s0_d.wasm Binary files differnew file mode 100644 index 0000000..a95064a --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_s0_d.wasm diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wat b/tests/proj2/tests/f64.convert_i32_s0_d.wat new file mode 100644 index 0000000..b9d01ce --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_s0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result f64) + (f64.convert_i32_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm b/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..db6257d --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_s0_d.wee.wasm diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.runs b/tests/proj2/tests/f64.convert_i32_u0_d.runs new file mode 100644 index 0000000..575f92d --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_u0_d.runs @@ -0,0 +1,4 @@ +0 = 0.000000 +1 = 1.000000 +-87234 = 4294880062.000000 +-2147483648 = 2147483648.000000 diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wasm b/tests/proj2/tests/f64.convert_i32_u0_d.wasm Binary files differnew file mode 100644 index 0000000..1b9cb15 --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_u0_d.wasm diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wat b/tests/proj2/tests/f64.convert_i32_u0_d.wat new file mode 100644 index 0000000..931ea45 --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_u0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result f64) + (f64.convert_i32_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm b/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..4aa04da --- /dev/null +++ b/tests/proj2/tests/f64.convert_i32_u0_d.wee.wasm diff --git a/tests/proj2/tests/f64.div0_d.runs b/tests/proj2/tests/f64.div0_d.runs new file mode 100644 index 0000000..d4581da --- /dev/null +++ b/tests/proj2/tests/f64.div0_d.runs @@ -0,0 +1,2 @@ +489728.83423d -782374.47d = -0.625952 +7000000000000d 800000000000d = 8.750000 diff --git a/tests/proj2/tests/f64.div0_d.wasm b/tests/proj2/tests/f64.div0_d.wasm Binary files differnew file mode 100644 index 0000000..9dab40a --- /dev/null +++ b/tests/proj2/tests/f64.div0_d.wasm diff --git a/tests/proj2/tests/f64.div0_d.wat b/tests/proj2/tests/f64.div0_d.wat new file mode 100644 index 0000000..3fcd399 --- /dev/null +++ b/tests/proj2/tests/f64.div0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result f64) + (f64.div (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.div0_d.wee.wasm b/tests/proj2/tests/f64.div0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..3fb0352 --- /dev/null +++ b/tests/proj2/tests/f64.div0_d.wee.wasm diff --git a/tests/proj2/tests/f64.eq0.runs b/tests/proj2/tests/f64.eq0.runs new file mode 100644 index 0000000..ad7ffa5 --- /dev/null +++ b/tests/proj2/tests/f64.eq0.runs @@ -0,0 +1,3 @@ +0d 1d = 0 +1.25d -1.25d = 0 +55.55d 55.5d = 0 diff --git a/tests/proj2/tests/f64.eq0.wasm b/tests/proj2/tests/f64.eq0.wasm Binary files differnew file mode 100644 index 0000000..d910cc1 --- /dev/null +++ b/tests/proj2/tests/f64.eq0.wasm diff --git a/tests/proj2/tests/f64.eq0.wat b/tests/proj2/tests/f64.eq0.wat new file mode 100644 index 0000000..33f3e71 --- /dev/null +++ b/tests/proj2/tests/f64.eq0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.eq (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.eq0.wee.wasm b/tests/proj2/tests/f64.eq0.wee.wasm Binary files differnew file mode 100644 index 0000000..283172f --- /dev/null +++ b/tests/proj2/tests/f64.eq0.wee.wasm diff --git a/tests/proj2/tests/f64.ge0.runs b/tests/proj2/tests/f64.ge0.runs new file mode 100644 index 0000000..d1f7c09 --- /dev/null +++ b/tests/proj2/tests/f64.ge0.runs @@ -0,0 +1,4 @@ +0d 1d = 0 +0d -1d = 1 +0.25d 0.5d = 0 +333.5d 333.5d = 1 diff --git a/tests/proj2/tests/f64.ge0.wasm b/tests/proj2/tests/f64.ge0.wasm Binary files differnew file mode 100644 index 0000000..4c99a91 --- /dev/null +++ b/tests/proj2/tests/f64.ge0.wasm diff --git a/tests/proj2/tests/f64.ge0.wat b/tests/proj2/tests/f64.ge0.wat new file mode 100644 index 0000000..c164325 --- /dev/null +++ b/tests/proj2/tests/f64.ge0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.ge (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.ge0.wee.wasm b/tests/proj2/tests/f64.ge0.wee.wasm Binary files differnew file mode 100644 index 0000000..c01d07d --- /dev/null +++ b/tests/proj2/tests/f64.ge0.wee.wasm diff --git a/tests/proj2/tests/f64.gt0.runs b/tests/proj2/tests/f64.gt0.runs new file mode 100644 index 0000000..3e821d9 --- /dev/null +++ b/tests/proj2/tests/f64.gt0.runs @@ -0,0 +1,4 @@ +0d 1d = 0 +0d -1d = 1 +0.25d 0.5d = 0 +333.5d 333.5d = 0 diff --git a/tests/proj2/tests/f64.gt0.wasm b/tests/proj2/tests/f64.gt0.wasm Binary files differnew file mode 100644 index 0000000..a63d96c --- /dev/null +++ b/tests/proj2/tests/f64.gt0.wasm diff --git a/tests/proj2/tests/f64.gt0.wat b/tests/proj2/tests/f64.gt0.wat new file mode 100644 index 0000000..81e23f8 --- /dev/null +++ b/tests/proj2/tests/f64.gt0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.gt (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.gt0.wee.wasm b/tests/proj2/tests/f64.gt0.wee.wasm Binary files differnew file mode 100644 index 0000000..d58886d --- /dev/null +++ b/tests/proj2/tests/f64.gt0.wee.wasm diff --git a/tests/proj2/tests/f64.le0.runs b/tests/proj2/tests/f64.le0.runs new file mode 100644 index 0000000..31a2b21 --- /dev/null +++ b/tests/proj2/tests/f64.le0.runs @@ -0,0 +1,4 @@ +0d 1d = 1 +0d -1d = 0 +0.25d 0.5d = 1 +333.5d 333.5d = 1 diff --git a/tests/proj2/tests/f64.le0.wasm b/tests/proj2/tests/f64.le0.wasm Binary files differnew file mode 100644 index 0000000..1ad8dd6 --- /dev/null +++ b/tests/proj2/tests/f64.le0.wasm diff --git a/tests/proj2/tests/f64.le0.wat b/tests/proj2/tests/f64.le0.wat new file mode 100644 index 0000000..5d46020 --- /dev/null +++ b/tests/proj2/tests/f64.le0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.le (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.le0.wee.wasm b/tests/proj2/tests/f64.le0.wee.wasm Binary files differnew file mode 100644 index 0000000..a687a26 --- /dev/null +++ b/tests/proj2/tests/f64.le0.wee.wasm diff --git a/tests/proj2/tests/f64.lt0.runs b/tests/proj2/tests/f64.lt0.runs new file mode 100644 index 0000000..56b5c96 --- /dev/null +++ b/tests/proj2/tests/f64.lt0.runs @@ -0,0 +1,4 @@ +0d 1d = 1 +0d -1d = 0 +0.25d 0.5d = 1 +333.5d 333.5d = 0 diff --git a/tests/proj2/tests/f64.lt0.wasm b/tests/proj2/tests/f64.lt0.wasm Binary files differnew file mode 100644 index 0000000..b1dbac7 --- /dev/null +++ b/tests/proj2/tests/f64.lt0.wasm diff --git a/tests/proj2/tests/f64.lt0.wat b/tests/proj2/tests/f64.lt0.wat new file mode 100644 index 0000000..171c39f --- /dev/null +++ b/tests/proj2/tests/f64.lt0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.lt (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.lt0.wee.wasm b/tests/proj2/tests/f64.lt0.wee.wasm Binary files differnew file mode 100644 index 0000000..7253f33 --- /dev/null +++ b/tests/proj2/tests/f64.lt0.wee.wasm diff --git a/tests/proj2/tests/f64.mul0_d.runs b/tests/proj2/tests/f64.mul0_d.runs new file mode 100644 index 0000000..0df48ca --- /dev/null +++ b/tests/proj2/tests/f64.mul0_d.runs @@ -0,0 +1,3 @@ +0d 1d = 0.000000 +0.25d -1.75d = -0.437500 +3000d -70000d = -210000000.000000 diff --git a/tests/proj2/tests/f64.mul0_d.wasm b/tests/proj2/tests/f64.mul0_d.wasm Binary files differnew file mode 100644 index 0000000..f02193b --- /dev/null +++ b/tests/proj2/tests/f64.mul0_d.wasm diff --git a/tests/proj2/tests/f64.mul0_d.wat b/tests/proj2/tests/f64.mul0_d.wat new file mode 100644 index 0000000..26ddb45 --- /dev/null +++ b/tests/proj2/tests/f64.mul0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result f64) + (f64.mul (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.mul0_d.wee.wasm b/tests/proj2/tests/f64.mul0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..952853e --- /dev/null +++ b/tests/proj2/tests/f64.mul0_d.wee.wasm diff --git a/tests/proj2/tests/f64.ne0.runs b/tests/proj2/tests/f64.ne0.runs new file mode 100644 index 0000000..0e4dc93 --- /dev/null +++ b/tests/proj2/tests/f64.ne0.runs @@ -0,0 +1,3 @@ +0d 1d = 1 +1.25d -1.25d = 1 +55.55d 55.5d = 1 diff --git a/tests/proj2/tests/f64.ne0.wasm b/tests/proj2/tests/f64.ne0.wasm Binary files differnew file mode 100644 index 0000000..7b0ce0a --- /dev/null +++ b/tests/proj2/tests/f64.ne0.wasm diff --git a/tests/proj2/tests/f64.ne0.wat b/tests/proj2/tests/f64.ne0.wat new file mode 100644 index 0000000..6df7443 --- /dev/null +++ b/tests/proj2/tests/f64.ne0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result i32) + (f64.ne (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.ne0.wee.wasm b/tests/proj2/tests/f64.ne0.wee.wasm Binary files differnew file mode 100644 index 0000000..4705ee2 --- /dev/null +++ b/tests/proj2/tests/f64.ne0.wee.wasm diff --git a/tests/proj2/tests/f64.store0.runs b/tests/proj2/tests/f64.store0.runs new file mode 100644 index 0000000..f1b5c80 --- /dev/null +++ b/tests/proj2/tests/f64.store0.runs @@ -0,0 +1,16 @@ +0 = 0 +100 = 0 +4000 = 0 +4001 = 0 +4002 = 81 +4003 = 73 +4004 = 28 +4005 = 0 +4006 = 17 +4007 = 25 +4008 = 3 +4009 = 64 +4010 = 0 +4011 = 0 +4012 = 0 +4013 = 0 diff --git a/tests/proj2/tests/f64.store0.wasm b/tests/proj2/tests/f64.store0.wasm Binary files differnew file mode 100644 index 0000000..bc0b048 --- /dev/null +++ b/tests/proj2/tests/f64.store0.wasm diff --git a/tests/proj2/tests/f64.store0.wat b/tests/proj2/tests/f64.store0.wat new file mode 100644 index 0000000..9a19625 --- /dev/null +++ b/tests/proj2/tests/f64.store0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (f64.store (i32.const 4002) (f64.const 2.387239457)) + (i32.load8_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/f64.store0.wee.wasm b/tests/proj2/tests/f64.store0.wee.wasm Binary files differnew file mode 100644 index 0000000..1ba02d6 --- /dev/null +++ b/tests/proj2/tests/f64.store0.wee.wasm diff --git a/tests/proj2/tests/f64.sub0_d.runs b/tests/proj2/tests/f64.sub0_d.runs new file mode 100644 index 0000000..27a6c6a --- /dev/null +++ b/tests/proj2/tests/f64.sub0_d.runs @@ -0,0 +1,3 @@ +0d 1d = -1.000000 +0.25d -1.75d = 2.000000 +489728.83423d -782374.47d = 1272103.304230 diff --git a/tests/proj2/tests/f64.sub0_d.wasm b/tests/proj2/tests/f64.sub0_d.wasm Binary files differnew file mode 100644 index 0000000..0e25291 --- /dev/null +++ b/tests/proj2/tests/f64.sub0_d.wasm diff --git a/tests/proj2/tests/f64.sub0_d.wat b/tests/proj2/tests/f64.sub0_d.wat new file mode 100644 index 0000000..3db96f3 --- /dev/null +++ b/tests/proj2/tests/f64.sub0_d.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64 f64) (result f64) + (f64.sub (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/f64.sub0_d.wee.wasm b/tests/proj2/tests/f64.sub0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..77ad9bd --- /dev/null +++ b/tests/proj2/tests/f64.sub0_d.wee.wasm diff --git a/tests/proj2/tests/fib.runs b/tests/proj2/tests/fib.runs new file mode 100644 index 0000000..fba1687 --- /dev/null +++ b/tests/proj2/tests/fib.runs @@ -0,0 +1,9 @@ +0 = 1 +1 = 1 +2 = 2 +3 = 3 +4 = 5 +5 = 8 +6 = 13 +7 = 21 +8 = 34 diff --git a/tests/proj2/tests/fib.wasm b/tests/proj2/tests/fib.wasm Binary files differnew file mode 100644 index 0000000..e329719 --- /dev/null +++ b/tests/proj2/tests/fib.wasm diff --git a/tests/proj2/tests/fib.wat b/tests/proj2/tests/fib.wat new file mode 100644 index 0000000..920f2e5 --- /dev/null +++ b/tests/proj2/tests/fib.wat @@ -0,0 +1,29 @@ +(module + (export "main" (func $fib)) + (func $fib (param $n i32) (result i32) + (block + (br_if 0 (i32.ge_s + (local.get $n) + (i32.const 2) + )) + (return + (i32.const 1) + )) + (return + (i32.add + (call $fib + (i32.sub + (local.get $n) + (i32.const 2) + ) + ) + (call $fib + (i32.sub + (local.get $n) + (i32.const 1) + ) + ) + ) + ) + ) +)
\ No newline at end of file diff --git a/tests/proj2/tests/fib.wee.wasm b/tests/proj2/tests/fib.wee.wasm Binary files differnew file mode 100644 index 0000000..23afd9e --- /dev/null +++ b/tests/proj2/tests/fib.wee.wasm diff --git a/tests/proj2/tests/gen.sh b/tests/proj2/tests/gen.sh new file mode 100755 index 0000000..c6daf7f --- /dev/null +++ b/tests/proj2/tests/gen.sh @@ -0,0 +1,436 @@ +#!/bin/bash + +function gen1() { + echo "(module" + echo " (func (export \"main\") (param $1) (result $2)" + echo " ($3 (local.get 0))" + echo " )" + echo ")" +} + +function gen2() { + echo "(module" + echo " (func (export \"main\") (param $1 $2) (result $3)" + echo " ($4 (local.get 0) (local.get 1))" + echo " )" + echo ")" +} + +i32_min=-2147483648 +i32_max=2147483647 +pt_zero=".000000" + +function BEGIN() { + export INSTR=$1 + SUFFIX="" + for s in $SIG; do + if [ "$s" = "f64" ]; then + SUFFIX="_d" + else + SUFFIX="" + fi + done + export NAME=${1}0${SUFFIX} + $SIG $INSTR > $NAME.wat + rm -f $NAME.runs +} + +function t() { + echo "$@" >> $NAME.runs +} + +function END() { + # do nothing + NOTHING=0 +} + +############################################################################## +SIG="gen1 i32 i32" + +BEGIN i32.eqz +t 0 = 1 +t 1 = 0 +t $i32_min = 0 +t 897234987 = 0 + +BEGIN i32.clz +t 0 = 32 +t 1 = 31 +t $i32_min = 0 +t 897234987 = 2 +t 65000 = 16 + +BEGIN i32.ctz +t 0 = 32 +t 1 = 0 +t $i32_min = 31 +t 897234987 = 0 +t 65536 = 16 + +BEGIN i32.popcnt +t 0 = 0 +t 1 = 1 +t 2 = 1 +t 89721348 = 9 +t -8934345 = 23 +t $i32_min = 1 + +BEGIN i32.extend8_s +t 0 = 0 +t 1 = 1 +t $i32_min = 0 +t 897234987 = 43 +t 128 = -128 + +BEGIN i32.extend16_s +t 0 = 0 +t 1 = 1 +t $i32_min = 0 +t 897234987 = -18389 +t 128 = 128 +t 32768 = -32768 + + +############################################################################## +SIG="gen2 i32 i32 i32" +BEGIN i32.eq +t 0 0 = 1 +t 1 0 = 0 +t 0 1 = 0 +t 5555 5555 = 1 +t -87239487 -8723487 = 0 + +BEGIN i32.ne +t 0 0 = 0 +t 1 0 = 1 +t 0 1 = 1 +t 5555 5555 = 0 +t -87239487 -8723487 = 1 + +BEGIN i32.lt_s +t -1 0 = 1 +t -1 -2 = 0 +t -55 -55 = 0 +t 30000000 40000000 = 1 +t -30000000 -40000000 = 0 +t $i32_min -1 = 1 +t $i32_min -2147483647 = 1 +t 55 54 = 0 +t 55 55 = 0 +t 55 56 = 1 +t -56 -55 = 1 +t -55 56 = 1 + +BEGIN i32.lt_u +t -1 0 = 0 +t -1 -2 = 0 +t -55 -55 = 0 +t 30000000 40000000 = 1 +t -30000000 -40000000 = 0 +t $i32_min -1 = 1 +t $i32_min -2147483647 = 1 +t 55 54 = 0 +t 55 55 = 0 +t 55 56 = 1 +t -56 -55 = 1 +t -55 56 = 0 + +BEGIN i32.gt_s +t -1 0 = 0 +t -1 -2 = 1 +t -55 -55 = 0 +t 30000000 40000000 = 0 +t -30000000 -40000000 = 1 +t $i32_min -1 = 0 +t $i32_min -2147483647 = 0 +t 55 54 = 1 +t 55 55 = 0 +t 55 56 = 0 +t -56 -55 = 0 +t -55 56 = 0 + +BEGIN i32.gt_u +t -1 0 = 1 +t -1 -2 = 1 +t -55 -55 = 0 +t 30000000 40000000 = 0 +t -30000000 -40000000 = 1 +t $i32_min -1 = 0 +t $i32_min -2147483647 = 0 +t 55 54 = 1 +t 55 55 = 0 +t 55 56 = 0 +t -56 -55 = 0 +t -55 56 = 1 + +BEGIN i32.le_s +t -1 0 = 1 +t -2 -3 = 0 +t -55 -55 = 1 +t 50000000 60000000 = 1 +t -50000000 -60000000 = 0 +t $i32_min -1 = 1 +t $i32_min -2147483647 = 1 +t 55 54 = 0 +t 55 55 = 1 +t 55 56 = 1 +t -56 -55 = 1 +t -55 56 = 1 + +BEGIN i32.le_u +t -1 0 = 0 +t -3 -4 = 0 +t -55 -55 = 1 +t 50000000 60000000 = 1 +t -50000000 -60000000 = 0 +t $i32_min -1 = 1 +t $i32_min -2147483647 = 1 +t 55 54 = 0 +t 55 55 = 1 +t 55 56 = 1 +t -56 -55 = 1 +t -55 56 = 0 + +BEGIN i32.ge_s +t -1 0 = 0 +t -1 -2 = 1 +t -55 -55 = 1 +t 30000000 40000000 = 0 +t -30000000 -40000000 = 1 +t $i32_min -1 = 0 +t $i32_min -2147483647 = 0 +t 55 54 = 1 +t 55 55 = 1 +t 55 56 = 0 +t -56 -55 = 0 +t -55 56 = 0 + +BEGIN i32.ge_u +t -1 0 = 1 +t -5 -6 = 1 +t -55 -55 = 1 +t 30000000 40000000 = 0 +t -20000000 -40000000 = 1 +t $i32_min -1 = 0 +t $i32_min -2147483647 = 0 +t 55 54 = 1 +t 55 55 = 1 +t 55 56 = 0 +t -56 -55 = 0 +t -55 56 = 1 + +BEGIN i32.add +t 8 9 = 17 +t 33 44 = 77 +t 111 222 = 333 +t 2222 3333 = 5555 +t 111111111 666666666 = 777777777 +t $i32_min $i32_min = 0 +t -2129587951 -2093796557 = 71582788 + +BEGIN i32.sub +t 8 9 = -1 +t 33 44 = -11 +t 111 222 = -111 +t 2222 3333 = -1111 +t 111111111 666666666 = -555555555 +t $i32_min $i32_min = 0 +t -2129587951 -2093796557 = -35791394 +t 2000000000 1 = 1999999999 + +BEGIN i32.mul +t 8 9 = 72 +t 33 44 = 1452 +t 111 222 = 24642 +t 2222 3333 = 7405926 +t 111111111 666666666 = 1332460582 +t $i32_min $i32_min = 0 +t -2129587951 -2093796557 = 909101411 +t 2000000000 1 = 2000000000 +t 2000000000 3 = 1705032704 + +BEGIN i32.div_s +t 5555 1111 = 5 +t -77777777 11111111 = -7 +t -77777777 11111 = -7000 +t $i32_min -1 = !trap +t 333 0 = !trap + +BEGIN i32.div_u +t 5555 1111 = 5 +t -77777777 11111111 = 379 +t -77777777 11111 = 379550 +t $i32_min -1 = 0 +t 3553 0 = !trap + +BEGIN i32.rem_s +t 99 10 = 9 +t 107 -10 = 7 +t -107 -10 = -7 +t -107 10 = -7 +t 1 0 = !trap +t 5559823 1 = 0 +t $i32_min -1 = 0 +t 876345 -1 = 0 + +BEGIN i32.rem_u +t 13338 10 = 8 +t 99 -3 = 99 +t 1 0 = !trap +t 555 1 = 0 +t $i32_min -1 = $i32_min + +BEGIN i32.and +t 876234 982134 = 810050 +t 897234 0 = 0 +t 89273498 -1 = 89273498 +t -555 $i32_min = $i32_min + +BEGIN i32.or +t 876234 982134 = 1048318 +t 897234 0 = 897234 +t 89273498 -1 = -1 +t -555 $i32_min = -555 + +BEGIN i32.xor +t 876234 982134 = 238268 +t 897234 0 = 897234 +t 89273498 -1 = -89273499 +t -555 $i32_min = 2147483093 + +BEGIN i32.shl +t 1044480 0 = 1044480 +t 1044480 32 = 1044480 +t 8972134 23 = -1291845632 +t -1 31 = $i32_min +t 1044480 36 = 16711680 + +BEGIN i32.shr_s +t 1044480 0 = 1044480 +t 1044480 32 = 1044480 +t 8972134 13 = 1095 +t -8972134 13 = -1096 +t 268435455 27 = 1 +t -256 4 = -16 +t 1044480 36 = 65280 + +BEGIN i32.shr_u +t 1044480 0 = 1044480 +t 1044480 32 = 1044480 +t 8972134 13 = 1095 +t -8972134 13 = 523192 +t -1 31 = 1 +t 1044480 36 = 65280 + +BEGIN i32.rotl +t 1044480 0 = 1044480 +t 1044480 32 = 1044480 +t 8972134 13 = 485277713 +t -8972134 13 = -485269522 +t -1412628189 36 = -1127214534 + +BEGIN i32.rotr +t 1044480 0 = 1044480 +t 1044480 32 = 1044480 +t 8972134 13 = 993002567 +t -8972134 13 = -992478280 +t -1412628189 36 = 985452562 + +END + +############################################################################## +SIG="gen2 f64 f64 i32" +BEGIN f64.eq +t 0d 1d = 0 +t 1.25d -1.25d = 0 +t 55.55d 55.5d = 0 +# TODO: nans and infinities + +BEGIN f64.ne +t 0d 1d = 1 +t 1.25d -1.25d = 1 +t 55.55d 55.5d = 1 + +BEGIN f64.lt +t 0d 1d = 1 +t 0d -1d = 0 +t 0.25d 0.5d = 1 +t 333.5d 333.5d = 0 + +BEGIN f64.gt +t 0d 1d = 0 +t 0d -1d = 1 +t 0.25d 0.5d = 0 +t 333.5d 333.5d = 0 + +BEGIN f64.le +t 0d 1d = 1 +t 0d -1d = 0 +t 0.25d 0.5d = 1 +t 333.5d 333.5d = 1 + +BEGIN f64.ge +t 0d 1d = 0 +t 0d -1d = 1 +t 0.25d 0.5d = 0 +t 333.5d 333.5d = 1 + +############################################################################## +SIG="gen2 f64 f64 f64" +BEGIN f64.add +t 0d 1d = 1.000000 +t 0.25d -1.75d = -1.500000 +t 489728.83423d -782374.47d = -292645.635770 +# TODO: nans and infinities + +BEGIN f64.sub +t 0d 1d = -1$pt_zero +t 0.25d -1.75d = 2$pt_zero +t 489728.83423d -782374.47d = 1272103.304230 + +BEGIN f64.mul +t 0d 1d = 0$pt_zero +t 0.25d -1.75d = -0.437500 +t 3000d -70000d = -210000000.000000 + +BEGIN f64.div +#TODO: nans and infinities t 0d 0d = nan +t 489728.83423d -782374.47d = -0.625952 +t 7000000000000d 800000000000d = 8.750000 + +############################################################################## +SIG="gen1 f64 i32" +BEGIN i32.trunc_f64_s +t 0d = 0 +t 0.9d = 0 +t -0.9d = 0 +t 1d = 1 +t -87234d = -87234 +t ${i32_min}d = $i32_min +t -3000000000d = !trap +t 3000000000d = !trap + +BEGIN i32.trunc_f64_u +t 0d = 0 +t 1d = 1 +t 0.9d = 0 +t -0.9d = 0 +t -87234d = !trap +t $i32_min = !trap +t 3000000000d = -1294967296 + +############################################################################## +SIG="gen1 i32 f64" +BEGIN f64.convert_i32_s +t 0 = 0$pt_zero +t 1 = 1$pt_zero +t -87234 = -87234$pt_zero +t $i32_min = $i32_min$pt_zero + +BEGIN f64.convert_i32_u +t 0 = 0$pt_zero +t 1 = 1$pt_zero +t -87234 = 4294880062$pt_zero +t $i32_min = 2147483648$pt_zero + +END diff --git a/tests/proj2/tests/global0.expect b/tests/proj2/tests/global0.expect new file mode 100644 index 0000000..a8fa06e --- /dev/null +++ b/tests/proj2/tests/global0.expect @@ -0,0 +1 @@ +62 diff --git a/tests/proj2/tests/global0.wasm b/tests/proj2/tests/global0.wasm Binary files differnew file mode 100644 index 0000000..4b642b1 --- /dev/null +++ b/tests/proj2/tests/global0.wasm diff --git a/tests/proj2/tests/global0.wat b/tests/proj2/tests/global0.wat new file mode 100644 index 0000000..06ceaab --- /dev/null +++ b/tests/proj2/tests/global0.wat @@ -0,0 +1,6 @@ +(module + (global $g i32 (i32.const 62)) + (func (export "main") (result i32) + (global.get $g) + ) +) diff --git a/tests/proj2/tests/global0.wee.wasm b/tests/proj2/tests/global0.wee.wasm Binary files differnew file mode 100644 index 0000000..2580fd3 --- /dev/null +++ b/tests/proj2/tests/global0.wee.wasm diff --git a/tests/proj2/tests/global1_d.expect b/tests/proj2/tests/global1_d.expect new file mode 100644 index 0000000..69771c6 --- /dev/null +++ b/tests/proj2/tests/global1_d.expect @@ -0,0 +1 @@ +-77.500000 diff --git a/tests/proj2/tests/global1_d.wasm b/tests/proj2/tests/global1_d.wasm Binary files differnew file mode 100644 index 0000000..c5d121b --- /dev/null +++ b/tests/proj2/tests/global1_d.wasm diff --git a/tests/proj2/tests/global1_d.wat b/tests/proj2/tests/global1_d.wat new file mode 100644 index 0000000..0b1313b --- /dev/null +++ b/tests/proj2/tests/global1_d.wat @@ -0,0 +1,6 @@ +(module + (global $g f64 (f64.const -77.5)) + (func (export "main") (result f64) + (global.get $g) + ) +) diff --git a/tests/proj2/tests/global1_d.wee.wasm b/tests/proj2/tests/global1_d.wee.wasm Binary files differnew file mode 100644 index 0000000..7ab6207 --- /dev/null +++ b/tests/proj2/tests/global1_d.wee.wasm diff --git a/tests/proj2/tests/global2.runs b/tests/proj2/tests/global2.runs new file mode 100644 index 0000000..899178b --- /dev/null +++ b/tests/proj2/tests/global2.runs @@ -0,0 +1,2 @@ +22 = 22 +-999888777 = -999888777 diff --git a/tests/proj2/tests/global2.wasm b/tests/proj2/tests/global2.wasm Binary files differnew file mode 100644 index 0000000..27d3f58 --- /dev/null +++ b/tests/proj2/tests/global2.wasm diff --git a/tests/proj2/tests/global2.wat b/tests/proj2/tests/global2.wat new file mode 100644 index 0000000..944d857 --- /dev/null +++ b/tests/proj2/tests/global2.wat @@ -0,0 +1,7 @@ +(module + (global $g (mut i32) (i32.const 62)) + (func (export "main") (param i32) (result i32) + (global.set $g (local.get 0)) + (global.get $g) + ) +) diff --git a/tests/proj2/tests/global2.wee.wasm b/tests/proj2/tests/global2.wee.wasm Binary files differnew file mode 100644 index 0000000..e74c151 --- /dev/null +++ b/tests/proj2/tests/global2.wee.wasm diff --git a/tests/proj2/tests/global3_d.runs b/tests/proj2/tests/global3_d.runs new file mode 100644 index 0000000..ff9d6b9 --- /dev/null +++ b/tests/proj2/tests/global3_d.runs @@ -0,0 +1,2 @@ +22.88d = 22.880000 +-999888777.1d = -999888777.100000 diff --git a/tests/proj2/tests/global3_d.wasm b/tests/proj2/tests/global3_d.wasm Binary files differnew file mode 100644 index 0000000..5422a0e --- /dev/null +++ b/tests/proj2/tests/global3_d.wasm diff --git a/tests/proj2/tests/global3_d.wat b/tests/proj2/tests/global3_d.wat new file mode 100644 index 0000000..56f0f57 --- /dev/null +++ b/tests/proj2/tests/global3_d.wat @@ -0,0 +1,7 @@ +(module + (global $g (mut f64) (f64.const 62)) + (func (export "main") (param f64) (result f64) + (global.set $g (local.get 0)) + (global.get $g) + ) +) diff --git a/tests/proj2/tests/global3_d.wee.wasm b/tests/proj2/tests/global3_d.wee.wasm Binary files differnew file mode 100644 index 0000000..b4d43a7 --- /dev/null +++ b/tests/proj2/tests/global3_d.wee.wasm diff --git a/tests/proj2/tests/i32.add0.runs b/tests/proj2/tests/i32.add0.runs new file mode 100644 index 0000000..e1a7ce1 --- /dev/null +++ b/tests/proj2/tests/i32.add0.runs @@ -0,0 +1,7 @@ +8 9 = 17 +33 44 = 77 +111 222 = 333 +2222 3333 = 5555 +111111111 666666666 = 777777777 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = 71582788 diff --git a/tests/proj2/tests/i32.add0.wasm b/tests/proj2/tests/i32.add0.wasm Binary files differnew file mode 100644 index 0000000..cca89af --- /dev/null +++ b/tests/proj2/tests/i32.add0.wasm diff --git a/tests/proj2/tests/i32.add0.wat b/tests/proj2/tests/i32.add0.wat new file mode 100644 index 0000000..cb46d02 --- /dev/null +++ b/tests/proj2/tests/i32.add0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.add (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.add0.wee.wasm b/tests/proj2/tests/i32.add0.wee.wasm Binary files differnew file mode 100644 index 0000000..d8ed0f6 --- /dev/null +++ b/tests/proj2/tests/i32.add0.wee.wasm diff --git a/tests/proj2/tests/i32.and0.runs b/tests/proj2/tests/i32.and0.runs new file mode 100644 index 0000000..4f3cf4a --- /dev/null +++ b/tests/proj2/tests/i32.and0.runs @@ -0,0 +1,4 @@ +876234 982134 = 810050 +897234 0 = 0 +89273498 -1 = 89273498 +-555 -2147483648 = -2147483648 diff --git a/tests/proj2/tests/i32.and0.wasm b/tests/proj2/tests/i32.and0.wasm Binary files differnew file mode 100644 index 0000000..77bc761 --- /dev/null +++ b/tests/proj2/tests/i32.and0.wasm diff --git a/tests/proj2/tests/i32.and0.wat b/tests/proj2/tests/i32.and0.wat new file mode 100644 index 0000000..741abdb --- /dev/null +++ b/tests/proj2/tests/i32.and0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.and (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.and0.wee.wasm b/tests/proj2/tests/i32.and0.wee.wasm Binary files differnew file mode 100644 index 0000000..5106aca --- /dev/null +++ b/tests/proj2/tests/i32.and0.wee.wasm diff --git a/tests/proj2/tests/i32.clz0.runs b/tests/proj2/tests/i32.clz0.runs new file mode 100644 index 0000000..73adce0 --- /dev/null +++ b/tests/proj2/tests/i32.clz0.runs @@ -0,0 +1,5 @@ +0 = 32 +1 = 31 +-2147483648 = 0 +897234987 = 2 +65000 = 16 diff --git a/tests/proj2/tests/i32.clz0.wasm b/tests/proj2/tests/i32.clz0.wasm Binary files differnew file mode 100644 index 0000000..9929ae6 --- /dev/null +++ b/tests/proj2/tests/i32.clz0.wasm diff --git a/tests/proj2/tests/i32.clz0.wat b/tests/proj2/tests/i32.clz0.wat new file mode 100644 index 0000000..b954051 --- /dev/null +++ b/tests/proj2/tests/i32.clz0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.clz (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.clz0.wee.wasm b/tests/proj2/tests/i32.clz0.wee.wasm Binary files differnew file mode 100644 index 0000000..484462f --- /dev/null +++ b/tests/proj2/tests/i32.clz0.wee.wasm diff --git a/tests/proj2/tests/i32.ctz0.runs b/tests/proj2/tests/i32.ctz0.runs new file mode 100644 index 0000000..b694360 --- /dev/null +++ b/tests/proj2/tests/i32.ctz0.runs @@ -0,0 +1,5 @@ +0 = 32 +1 = 0 +-2147483648 = 31 +897234987 = 0 +65536 = 16 diff --git a/tests/proj2/tests/i32.ctz0.wasm b/tests/proj2/tests/i32.ctz0.wasm Binary files differnew file mode 100644 index 0000000..948b44e --- /dev/null +++ b/tests/proj2/tests/i32.ctz0.wasm diff --git a/tests/proj2/tests/i32.ctz0.wat b/tests/proj2/tests/i32.ctz0.wat new file mode 100644 index 0000000..c88bbd2 --- /dev/null +++ b/tests/proj2/tests/i32.ctz0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.ctz (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.ctz0.wee.wasm b/tests/proj2/tests/i32.ctz0.wee.wasm Binary files differnew file mode 100644 index 0000000..30e1f91 --- /dev/null +++ b/tests/proj2/tests/i32.ctz0.wee.wasm diff --git a/tests/proj2/tests/i32.div_s0.runs b/tests/proj2/tests/i32.div_s0.runs new file mode 100644 index 0000000..931ca6c --- /dev/null +++ b/tests/proj2/tests/i32.div_s0.runs @@ -0,0 +1,5 @@ +5555 1111 = 5 +-77777777 11111111 = -7 +-77777777 11111 = -7000 +-2147483648 -1 = !trap +333 0 = !trap diff --git a/tests/proj2/tests/i32.div_s0.wasm b/tests/proj2/tests/i32.div_s0.wasm Binary files differnew file mode 100644 index 0000000..1800629 --- /dev/null +++ b/tests/proj2/tests/i32.div_s0.wasm diff --git a/tests/proj2/tests/i32.div_s0.wat b/tests/proj2/tests/i32.div_s0.wat new file mode 100644 index 0000000..98288d7 --- /dev/null +++ b/tests/proj2/tests/i32.div_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.div_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.div_s0.wee.wasm b/tests/proj2/tests/i32.div_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..95dc30b --- /dev/null +++ b/tests/proj2/tests/i32.div_s0.wee.wasm diff --git a/tests/proj2/tests/i32.div_u0.runs b/tests/proj2/tests/i32.div_u0.runs new file mode 100644 index 0000000..05bc291 --- /dev/null +++ b/tests/proj2/tests/i32.div_u0.runs @@ -0,0 +1,5 @@ +5555 1111 = 5 +-77777777 11111111 = 379 +-77777777 11111 = 379550 +-2147483648 -1 = 0 +3553 0 = !trap diff --git a/tests/proj2/tests/i32.div_u0.wasm b/tests/proj2/tests/i32.div_u0.wasm Binary files differnew file mode 100644 index 0000000..41d0371 --- /dev/null +++ b/tests/proj2/tests/i32.div_u0.wasm diff --git a/tests/proj2/tests/i32.div_u0.wat b/tests/proj2/tests/i32.div_u0.wat new file mode 100644 index 0000000..db522a7 --- /dev/null +++ b/tests/proj2/tests/i32.div_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.div_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.div_u0.wee.wasm b/tests/proj2/tests/i32.div_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..72be5b5 --- /dev/null +++ b/tests/proj2/tests/i32.div_u0.wee.wasm diff --git a/tests/proj2/tests/i32.eq0.runs b/tests/proj2/tests/i32.eq0.runs new file mode 100644 index 0000000..0e5c23b --- /dev/null +++ b/tests/proj2/tests/i32.eq0.runs @@ -0,0 +1,5 @@ +0 0 = 1 +1 0 = 0 +0 1 = 0 +5555 5555 = 1 +-87239487 -8723487 = 0 diff --git a/tests/proj2/tests/i32.eq0.wasm b/tests/proj2/tests/i32.eq0.wasm Binary files differnew file mode 100644 index 0000000..811bbdf --- /dev/null +++ b/tests/proj2/tests/i32.eq0.wasm diff --git a/tests/proj2/tests/i32.eq0.wat b/tests/proj2/tests/i32.eq0.wat new file mode 100644 index 0000000..69f9184 --- /dev/null +++ b/tests/proj2/tests/i32.eq0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.eq (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.eq0.wee.wasm b/tests/proj2/tests/i32.eq0.wee.wasm Binary files differnew file mode 100644 index 0000000..18895ce --- /dev/null +++ b/tests/proj2/tests/i32.eq0.wee.wasm diff --git a/tests/proj2/tests/i32.eqz0.runs b/tests/proj2/tests/i32.eqz0.runs new file mode 100644 index 0000000..f13d128 --- /dev/null +++ b/tests/proj2/tests/i32.eqz0.runs @@ -0,0 +1,4 @@ +0 = 1 +1 = 0 +-2147483648 = 0 +897234987 = 0 diff --git a/tests/proj2/tests/i32.eqz0.wasm b/tests/proj2/tests/i32.eqz0.wasm Binary files differnew file mode 100644 index 0000000..6c27e23 --- /dev/null +++ b/tests/proj2/tests/i32.eqz0.wasm diff --git a/tests/proj2/tests/i32.eqz0.wat b/tests/proj2/tests/i32.eqz0.wat new file mode 100644 index 0000000..e966b97 --- /dev/null +++ b/tests/proj2/tests/i32.eqz0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.eqz (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.eqz0.wee.wasm b/tests/proj2/tests/i32.eqz0.wee.wasm Binary files differnew file mode 100644 index 0000000..f0f1a64 --- /dev/null +++ b/tests/proj2/tests/i32.eqz0.wee.wasm diff --git a/tests/proj2/tests/i32.extend16_s0.runs b/tests/proj2/tests/i32.extend16_s0.runs new file mode 100644 index 0000000..6d27b73 --- /dev/null +++ b/tests/proj2/tests/i32.extend16_s0.runs @@ -0,0 +1,6 @@ +0 = 0 +1 = 1 +-2147483648 = 0 +897234987 = -18389 +128 = 128 +32768 = -32768 diff --git a/tests/proj2/tests/i32.extend16_s0.wasm b/tests/proj2/tests/i32.extend16_s0.wasm Binary files differnew file mode 100644 index 0000000..def3221 --- /dev/null +++ b/tests/proj2/tests/i32.extend16_s0.wasm diff --git a/tests/proj2/tests/i32.extend16_s0.wat b/tests/proj2/tests/i32.extend16_s0.wat new file mode 100644 index 0000000..ac1685c --- /dev/null +++ b/tests/proj2/tests/i32.extend16_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.extend16_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.extend16_s0.wee.wasm b/tests/proj2/tests/i32.extend16_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..a0186e3 --- /dev/null +++ b/tests/proj2/tests/i32.extend16_s0.wee.wasm diff --git a/tests/proj2/tests/i32.extend8_s0.runs b/tests/proj2/tests/i32.extend8_s0.runs new file mode 100644 index 0000000..5f1ab42 --- /dev/null +++ b/tests/proj2/tests/i32.extend8_s0.runs @@ -0,0 +1,5 @@ +0 = 0 +1 = 1 +-2147483648 = 0 +897234987 = 43 +128 = -128 diff --git a/tests/proj2/tests/i32.extend8_s0.wasm b/tests/proj2/tests/i32.extend8_s0.wasm Binary files differnew file mode 100644 index 0000000..e6cd61a --- /dev/null +++ b/tests/proj2/tests/i32.extend8_s0.wasm diff --git a/tests/proj2/tests/i32.extend8_s0.wat b/tests/proj2/tests/i32.extend8_s0.wat new file mode 100644 index 0000000..e64b80c --- /dev/null +++ b/tests/proj2/tests/i32.extend8_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.extend8_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.extend8_s0.wee.wasm b/tests/proj2/tests/i32.extend8_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..5a95da6 --- /dev/null +++ b/tests/proj2/tests/i32.extend8_s0.wee.wasm diff --git a/tests/proj2/tests/i32.ge_s0.runs b/tests/proj2/tests/i32.ge_s0.runs new file mode 100644 index 0000000..458410e --- /dev/null +++ b/tests/proj2/tests/i32.ge_s0.runs @@ -0,0 +1,12 @@ +-1 0 = 0 +-1 -2 = 1 +-55 -55 = 1 +30000000 40000000 = 0 +-30000000 -40000000 = 1 +-2147483648 -1 = 0 +-2147483648 -2147483647 = 0 +55 54 = 1 +55 55 = 1 +55 56 = 0 +-56 -55 = 0 +-55 56 = 0 diff --git a/tests/proj2/tests/i32.ge_s0.wasm b/tests/proj2/tests/i32.ge_s0.wasm Binary files differnew file mode 100644 index 0000000..fdd6af1 --- /dev/null +++ b/tests/proj2/tests/i32.ge_s0.wasm diff --git a/tests/proj2/tests/i32.ge_s0.wat b/tests/proj2/tests/i32.ge_s0.wat new file mode 100644 index 0000000..de5b2c7 --- /dev/null +++ b/tests/proj2/tests/i32.ge_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.ge_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.ge_s0.wee.wasm b/tests/proj2/tests/i32.ge_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..e921c24 --- /dev/null +++ b/tests/proj2/tests/i32.ge_s0.wee.wasm diff --git a/tests/proj2/tests/i32.ge_u0.runs b/tests/proj2/tests/i32.ge_u0.runs new file mode 100644 index 0000000..a9bdfc7 --- /dev/null +++ b/tests/proj2/tests/i32.ge_u0.runs @@ -0,0 +1,12 @@ +-1 0 = 1 +-5 -6 = 1 +-55 -55 = 1 +30000000 40000000 = 0 +-20000000 -40000000 = 1 +-2147483648 -1 = 0 +-2147483648 -2147483647 = 0 +55 54 = 1 +55 55 = 1 +55 56 = 0 +-56 -55 = 0 +-55 56 = 1 diff --git a/tests/proj2/tests/i32.ge_u0.wasm b/tests/proj2/tests/i32.ge_u0.wasm Binary files differnew file mode 100644 index 0000000..2eb0c6c --- /dev/null +++ b/tests/proj2/tests/i32.ge_u0.wasm diff --git a/tests/proj2/tests/i32.ge_u0.wat b/tests/proj2/tests/i32.ge_u0.wat new file mode 100644 index 0000000..f0810d5 --- /dev/null +++ b/tests/proj2/tests/i32.ge_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.ge_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.ge_u0.wee.wasm b/tests/proj2/tests/i32.ge_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..2e3877c --- /dev/null +++ b/tests/proj2/tests/i32.ge_u0.wee.wasm diff --git a/tests/proj2/tests/i32.gt_s0.runs b/tests/proj2/tests/i32.gt_s0.runs new file mode 100644 index 0000000..6c79f10 --- /dev/null +++ b/tests/proj2/tests/i32.gt_s0.runs @@ -0,0 +1,12 @@ +-1 0 = 0 +-1 -2 = 1 +-55 -55 = 0 +30000000 40000000 = 0 +-30000000 -40000000 = 1 +-2147483648 -1 = 0 +-2147483648 -2147483647 = 0 +55 54 = 1 +55 55 = 0 +55 56 = 0 +-56 -55 = 0 +-55 56 = 0 diff --git a/tests/proj2/tests/i32.gt_s0.wasm b/tests/proj2/tests/i32.gt_s0.wasm Binary files differnew file mode 100644 index 0000000..42c6e90 --- /dev/null +++ b/tests/proj2/tests/i32.gt_s0.wasm diff --git a/tests/proj2/tests/i32.gt_s0.wat b/tests/proj2/tests/i32.gt_s0.wat new file mode 100644 index 0000000..8be6996 --- /dev/null +++ b/tests/proj2/tests/i32.gt_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.gt_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.gt_s0.wee.wasm b/tests/proj2/tests/i32.gt_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..7586819 --- /dev/null +++ b/tests/proj2/tests/i32.gt_s0.wee.wasm diff --git a/tests/proj2/tests/i32.gt_u0.runs b/tests/proj2/tests/i32.gt_u0.runs new file mode 100644 index 0000000..3a9f7ea --- /dev/null +++ b/tests/proj2/tests/i32.gt_u0.runs @@ -0,0 +1,12 @@ +-1 0 = 1 +-1 -2 = 1 +-55 -55 = 0 +30000000 40000000 = 0 +-30000000 -40000000 = 1 +-2147483648 -1 = 0 +-2147483648 -2147483647 = 0 +55 54 = 1 +55 55 = 0 +55 56 = 0 +-56 -55 = 0 +-55 56 = 1 diff --git a/tests/proj2/tests/i32.gt_u0.wasm b/tests/proj2/tests/i32.gt_u0.wasm Binary files differnew file mode 100644 index 0000000..b80c786 --- /dev/null +++ b/tests/proj2/tests/i32.gt_u0.wasm diff --git a/tests/proj2/tests/i32.gt_u0.wat b/tests/proj2/tests/i32.gt_u0.wat new file mode 100644 index 0000000..e9becf8 --- /dev/null +++ b/tests/proj2/tests/i32.gt_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.gt_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.gt_u0.wee.wasm b/tests/proj2/tests/i32.gt_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..0eada3e --- /dev/null +++ b/tests/proj2/tests/i32.gt_u0.wee.wasm diff --git a/tests/proj2/tests/i32.le_s0.runs b/tests/proj2/tests/i32.le_s0.runs new file mode 100644 index 0000000..1511108 --- /dev/null +++ b/tests/proj2/tests/i32.le_s0.runs @@ -0,0 +1,12 @@ +-1 0 = 1 +-2 -3 = 0 +-55 -55 = 1 +50000000 60000000 = 1 +-50000000 -60000000 = 0 +-2147483648 -1 = 1 +-2147483648 -2147483647 = 1 +55 54 = 0 +55 55 = 1 +55 56 = 1 +-56 -55 = 1 +-55 56 = 1 diff --git a/tests/proj2/tests/i32.le_s0.wasm b/tests/proj2/tests/i32.le_s0.wasm Binary files differnew file mode 100644 index 0000000..3c16e28 --- /dev/null +++ b/tests/proj2/tests/i32.le_s0.wasm diff --git a/tests/proj2/tests/i32.le_s0.wat b/tests/proj2/tests/i32.le_s0.wat new file mode 100644 index 0000000..533908d --- /dev/null +++ b/tests/proj2/tests/i32.le_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.le_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.le_s0.wee.wasm b/tests/proj2/tests/i32.le_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..c269465 --- /dev/null +++ b/tests/proj2/tests/i32.le_s0.wee.wasm diff --git a/tests/proj2/tests/i32.le_u0.runs b/tests/proj2/tests/i32.le_u0.runs new file mode 100644 index 0000000..17808cd --- /dev/null +++ b/tests/proj2/tests/i32.le_u0.runs @@ -0,0 +1,12 @@ +-1 0 = 0 +-3 -4 = 0 +-55 -55 = 1 +50000000 60000000 = 1 +-50000000 -60000000 = 0 +-2147483648 -1 = 1 +-2147483648 -2147483647 = 1 +55 54 = 0 +55 55 = 1 +55 56 = 1 +-56 -55 = 1 +-55 56 = 0 diff --git a/tests/proj2/tests/i32.le_u0.wasm b/tests/proj2/tests/i32.le_u0.wasm Binary files differnew file mode 100644 index 0000000..46b4597 --- /dev/null +++ b/tests/proj2/tests/i32.le_u0.wasm diff --git a/tests/proj2/tests/i32.le_u0.wat b/tests/proj2/tests/i32.le_u0.wat new file mode 100644 index 0000000..fe9addf --- /dev/null +++ b/tests/proj2/tests/i32.le_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.le_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.le_u0.wee.wasm b/tests/proj2/tests/i32.le_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..12c2079 --- /dev/null +++ b/tests/proj2/tests/i32.le_u0.wee.wasm diff --git a/tests/proj2/tests/i32.load0.runs b/tests/proj2/tests/i32.load0.runs new file mode 100644 index 0000000..ea38b0e --- /dev/null +++ b/tests/proj2/tests/i32.load0.runs @@ -0,0 +1,6 @@ +0 = 0 +1 = 0 +100 = 0 +1024 = 0 +65530 = 0 +65532 = 0 diff --git a/tests/proj2/tests/i32.load0.wasm b/tests/proj2/tests/i32.load0.wasm Binary files differnew file mode 100644 index 0000000..3e76665 --- /dev/null +++ b/tests/proj2/tests/i32.load0.wasm diff --git a/tests/proj2/tests/i32.load0.wat b/tests/proj2/tests/i32.load0.wat new file mode 100644 index 0000000..23d8b8c --- /dev/null +++ b/tests/proj2/tests/i32.load0.wat @@ -0,0 +1,6 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.load offset=0 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load0.wee.wasm b/tests/proj2/tests/i32.load0.wee.wasm Binary files differnew file mode 100644 index 0000000..0eaed96 --- /dev/null +++ b/tests/proj2/tests/i32.load0.wee.wasm diff --git a/tests/proj2/tests/i32.load1.runs b/tests/proj2/tests/i32.load1.runs new file mode 100644 index 0000000..8643400 --- /dev/null +++ b/tests/proj2/tests/i32.load1.runs @@ -0,0 +1,7 @@ +0 = 0 +1 = 0 +100 = 0 +1024 = 0 +65500 = 0 +65530 = !trap +65532 = !trap diff --git a/tests/proj2/tests/i32.load1.wasm b/tests/proj2/tests/i32.load1.wasm Binary files differnew file mode 100644 index 0000000..f360bc6 --- /dev/null +++ b/tests/proj2/tests/i32.load1.wasm diff --git a/tests/proj2/tests/i32.load1.wat b/tests/proj2/tests/i32.load1.wat new file mode 100644 index 0000000..3137264 --- /dev/null +++ b/tests/proj2/tests/i32.load1.wat @@ -0,0 +1,6 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.load offset=32 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load1.wee.wasm b/tests/proj2/tests/i32.load1.wee.wasm Binary files differnew file mode 100644 index 0000000..fe8d156 --- /dev/null +++ b/tests/proj2/tests/i32.load1.wee.wasm diff --git a/tests/proj2/tests/i32.load16_s0.runs b/tests/proj2/tests/i32.load16_s0.runs new file mode 100644 index 0000000..bfcdacd --- /dev/null +++ b/tests/proj2/tests/i32.load16_s0.runs @@ -0,0 +1,13 @@ +1100 = 0 +1101 = 0 +1102 = 0 +1103 = 30720 +1104 = -26248 +1105 = 12441 +1106 = 12592 +1107 = 49 +1108 = 0 +1109 = 0 +1110 = 0 +1111 = 0 +1112 = 0 diff --git a/tests/proj2/tests/i32.load16_s0.wasm b/tests/proj2/tests/i32.load16_s0.wasm Binary files differnew file mode 100644 index 0000000..931e190 --- /dev/null +++ b/tests/proj2/tests/i32.load16_s0.wasm diff --git a/tests/proj2/tests/i32.load16_s0.wat b/tests/proj2/tests/i32.load16_s0.wat new file mode 100644 index 0000000..b6229d1 --- /dev/null +++ b/tests/proj2/tests/i32.load16_s0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 1104) "x\9901") + (func (export "main") (param i32) (result i32) + (i32.load16_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load16_s0.wee.wasm b/tests/proj2/tests/i32.load16_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..686dfef --- /dev/null +++ b/tests/proj2/tests/i32.load16_s0.wee.wasm diff --git a/tests/proj2/tests/i32.load16_u0.runs b/tests/proj2/tests/i32.load16_u0.runs new file mode 100644 index 0000000..0a9993c --- /dev/null +++ b/tests/proj2/tests/i32.load16_u0.runs @@ -0,0 +1,13 @@ +1000 = 0 +1001 = 0 +1002 = 0 +1003 = 30720 +1004 = 39288 +1005 = 12441 +1006 = 12592 +1007 = 49 +1008 = 0 +1009 = 0 +1010 = 0 +1011 = 0 +1012 = 0 diff --git a/tests/proj2/tests/i32.load16_u0.wasm b/tests/proj2/tests/i32.load16_u0.wasm Binary files differnew file mode 100644 index 0000000..7690cc7 --- /dev/null +++ b/tests/proj2/tests/i32.load16_u0.wasm diff --git a/tests/proj2/tests/i32.load16_u0.wat b/tests/proj2/tests/i32.load16_u0.wat new file mode 100644 index 0000000..7eba8e2 --- /dev/null +++ b/tests/proj2/tests/i32.load16_u0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 1004) "x\9901") + (func (export "main") (param i32) (result i32) + (i32.load16_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load16_u0.wee.wasm b/tests/proj2/tests/i32.load16_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..10b3052 --- /dev/null +++ b/tests/proj2/tests/i32.load16_u0.wee.wasm diff --git a/tests/proj2/tests/i32.load16_u1.runs b/tests/proj2/tests/i32.load16_u1.runs new file mode 100644 index 0000000..26374d0 --- /dev/null +++ b/tests/proj2/tests/i32.load16_u1.runs @@ -0,0 +1,13 @@ +500 = 0 +501 = 0 +502 = 0 +503 = 30720 +504 = 39288 +505 = 12441 +506 = 12592 +507 = 49 +508 = 0 +509 = 0 +55 = 0 +511 = 0 +512 = 0 diff --git a/tests/proj2/tests/i32.load16_u1.wasm b/tests/proj2/tests/i32.load16_u1.wasm Binary files differnew file mode 100644 index 0000000..2d0b46e --- /dev/null +++ b/tests/proj2/tests/i32.load16_u1.wasm diff --git a/tests/proj2/tests/i32.load16_u1.wat b/tests/proj2/tests/i32.load16_u1.wat new file mode 100644 index 0000000..6112295 --- /dev/null +++ b/tests/proj2/tests/i32.load16_u1.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 1004) "x\9901") + (func (export "main") (param i32) (result i32) + (i32.load16_u offset=500 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load16_u1.wee.wasm b/tests/proj2/tests/i32.load16_u1.wee.wasm Binary files differnew file mode 100644 index 0000000..f5140af --- /dev/null +++ b/tests/proj2/tests/i32.load16_u1.wee.wasm diff --git a/tests/proj2/tests/i32.load2.runs b/tests/proj2/tests/i32.load2.runs new file mode 100644 index 0000000..59f95d0 --- /dev/null +++ b/tests/proj2/tests/i32.load2.runs @@ -0,0 +1,11 @@ +0 = 0 +1 = 0 +100 = 0 +1024 = 0 +65500 = 0 +65530 = 0 +65532 = 0 +100000 = 0 +131072 = !trap +131040 = !trap +131036 = 0 diff --git a/tests/proj2/tests/i32.load2.wasm b/tests/proj2/tests/i32.load2.wasm Binary files differnew file mode 100644 index 0000000..57a2231 --- /dev/null +++ b/tests/proj2/tests/i32.load2.wasm diff --git a/tests/proj2/tests/i32.load2.wat b/tests/proj2/tests/i32.load2.wat new file mode 100644 index 0000000..90f3c1e --- /dev/null +++ b/tests/proj2/tests/i32.load2.wat @@ -0,0 +1,6 @@ +(module + (memory 2) + (func (export "main") (param i32) (result i32) + (i32.load offset=32 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load2.wee.wasm b/tests/proj2/tests/i32.load2.wee.wasm Binary files differnew file mode 100644 index 0000000..bfe1c18 --- /dev/null +++ b/tests/proj2/tests/i32.load2.wee.wasm diff --git a/tests/proj2/tests/i32.load3.runs b/tests/proj2/tests/i32.load3.runs new file mode 100644 index 0000000..61f2e00 --- /dev/null +++ b/tests/proj2/tests/i32.load3.runs @@ -0,0 +1,3 @@ +0 = 0 +60 = !trap +56 = 0 diff --git a/tests/proj2/tests/i32.load3.wasm b/tests/proj2/tests/i32.load3.wasm Binary files differnew file mode 100644 index 0000000..098ceb1 --- /dev/null +++ b/tests/proj2/tests/i32.load3.wasm diff --git a/tests/proj2/tests/i32.load3.wat b/tests/proj2/tests/i32.load3.wat new file mode 100644 index 0000000..6de5fe3 --- /dev/null +++ b/tests/proj2/tests/i32.load3.wat @@ -0,0 +1,6 @@ +(module + (memory 10) + (func (export "main") (param i32) (result i32) + (i32.load offset=655300 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load3.wee.wasm b/tests/proj2/tests/i32.load3.wee.wasm Binary files differnew file mode 100644 index 0000000..e1cd500 --- /dev/null +++ b/tests/proj2/tests/i32.load3.wee.wasm diff --git a/tests/proj2/tests/i32.load4.runs b/tests/proj2/tests/i32.load4.runs new file mode 100644 index 0000000..6263e85 --- /dev/null +++ b/tests/proj2/tests/i32.load4.runs @@ -0,0 +1,13 @@ +0 = 0 +1 = 2013265920 +2 = 2037907456 +3 = 2054780928 +4 = 2004515192 +5 = 7830137 +6 = 30586 +7 = 119 +8 = 0 +9 = 0 +10 = 0 +11 = 0 +12 = 0 diff --git a/tests/proj2/tests/i32.load4.wasm b/tests/proj2/tests/i32.load4.wasm Binary files differnew file mode 100644 index 0000000..02f890a --- /dev/null +++ b/tests/proj2/tests/i32.load4.wasm diff --git a/tests/proj2/tests/i32.load4.wat b/tests/proj2/tests/i32.load4.wat new file mode 100644 index 0000000..fc0ad0f --- /dev/null +++ b/tests/proj2/tests/i32.load4.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 4) "xyzw") + (func (export "main") (param i32) (result i32) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load4.wee.wasm b/tests/proj2/tests/i32.load4.wee.wasm Binary files differnew file mode 100644 index 0000000..7fc320e --- /dev/null +++ b/tests/proj2/tests/i32.load4.wee.wasm diff --git a/tests/proj2/tests/i32.load8_s0.runs b/tests/proj2/tests/i32.load8_s0.runs new file mode 100644 index 0000000..319a9e5 --- /dev/null +++ b/tests/proj2/tests/i32.load8_s0.runs @@ -0,0 +1,13 @@ +400 = 0 +401 = 0 +402 = 0 +403 = 0 +404 = 120 +405 = -103 +406 = 48 +407 = 49 +408 = 0 +409 = 0 +410 = 0 +411 = 0 +412 = 0 diff --git a/tests/proj2/tests/i32.load8_s0.wasm b/tests/proj2/tests/i32.load8_s0.wasm Binary files differnew file mode 100644 index 0000000..33e1fcd --- /dev/null +++ b/tests/proj2/tests/i32.load8_s0.wasm diff --git a/tests/proj2/tests/i32.load8_s0.wat b/tests/proj2/tests/i32.load8_s0.wat new file mode 100644 index 0000000..df2fa4a --- /dev/null +++ b/tests/proj2/tests/i32.load8_s0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 404) "x\9901") + (func (export "main") (param i32) (result i32) + (i32.load8_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load8_s0.wee.wasm b/tests/proj2/tests/i32.load8_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..34c7444 --- /dev/null +++ b/tests/proj2/tests/i32.load8_s0.wee.wasm diff --git a/tests/proj2/tests/i32.load8_u0.runs b/tests/proj2/tests/i32.load8_u0.runs new file mode 100644 index 0000000..dcab3c3 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u0.runs @@ -0,0 +1,13 @@ +500 = 0 +501 = 0 +502 = 0 +503 = 0 +504 = 120 +505 = 121 +506 = 122 +507 = 119 +508 = 0 +509 = 0 +510 = 0 +511 = 0 +512 = 0 diff --git a/tests/proj2/tests/i32.load8_u0.wasm b/tests/proj2/tests/i32.load8_u0.wasm Binary files differnew file mode 100644 index 0000000..c832368 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u0.wasm diff --git a/tests/proj2/tests/i32.load8_u0.wat b/tests/proj2/tests/i32.load8_u0.wat new file mode 100644 index 0000000..216f918 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 504) "xyzw") + (func (export "main") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load8_u0.wee.wasm b/tests/proj2/tests/i32.load8_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..302d8e1 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u0.wee.wasm diff --git a/tests/proj2/tests/i32.load8_u1.runs b/tests/proj2/tests/i32.load8_u1.runs new file mode 100644 index 0000000..77abaf2 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u1.runs @@ -0,0 +1,13 @@ +200 = 0 +201 = 0 +202 = 0 +203 = 0 +204 = 120 +205 = 121 +206 = 122 +207 = 119 +208 = 0 +209 = 0 +210 = 0 +211 = 0 +212 = 0 diff --git a/tests/proj2/tests/i32.load8_u1.wasm b/tests/proj2/tests/i32.load8_u1.wasm Binary files differnew file mode 100644 index 0000000..fbdb269 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u1.wasm diff --git a/tests/proj2/tests/i32.load8_u1.wat b/tests/proj2/tests/i32.load8_u1.wat new file mode 100644 index 0000000..60759d9 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u1.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 504) "xyzw") + (func (export "main") (param i32) (result i32) + (i32.load8_u offset=300 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.load8_u1.wee.wasm b/tests/proj2/tests/i32.load8_u1.wee.wasm Binary files differnew file mode 100644 index 0000000..aa62e25 --- /dev/null +++ b/tests/proj2/tests/i32.load8_u1.wee.wasm diff --git a/tests/proj2/tests/i32.lt_s0.runs b/tests/proj2/tests/i32.lt_s0.runs new file mode 100644 index 0000000..2c1aed0 --- /dev/null +++ b/tests/proj2/tests/i32.lt_s0.runs @@ -0,0 +1,12 @@ +-1 0 = 1 +-1 -2 = 0 +-55 -55 = 0 +30000000 40000000 = 1 +-30000000 -40000000 = 0 +-2147483648 -1 = 1 +-2147483648 -2147483647 = 1 +55 54 = 0 +55 55 = 0 +55 56 = 1 +-56 -55 = 1 +-55 56 = 1 diff --git a/tests/proj2/tests/i32.lt_s0.wasm b/tests/proj2/tests/i32.lt_s0.wasm Binary files differnew file mode 100644 index 0000000..b785865 --- /dev/null +++ b/tests/proj2/tests/i32.lt_s0.wasm diff --git a/tests/proj2/tests/i32.lt_s0.wat b/tests/proj2/tests/i32.lt_s0.wat new file mode 100644 index 0000000..c89d521 --- /dev/null +++ b/tests/proj2/tests/i32.lt_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.lt_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.lt_s0.wee.wasm b/tests/proj2/tests/i32.lt_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..3dac5d4 --- /dev/null +++ b/tests/proj2/tests/i32.lt_s0.wee.wasm diff --git a/tests/proj2/tests/i32.lt_u0.runs b/tests/proj2/tests/i32.lt_u0.runs new file mode 100644 index 0000000..12d002b --- /dev/null +++ b/tests/proj2/tests/i32.lt_u0.runs @@ -0,0 +1,12 @@ +-1 0 = 0 +-1 -2 = 0 +-55 -55 = 0 +30000000 40000000 = 1 +-30000000 -40000000 = 0 +-2147483648 -1 = 1 +-2147483648 -2147483647 = 1 +55 54 = 0 +55 55 = 0 +55 56 = 1 +-56 -55 = 1 +-55 56 = 0 diff --git a/tests/proj2/tests/i32.lt_u0.wasm b/tests/proj2/tests/i32.lt_u0.wasm Binary files differnew file mode 100644 index 0000000..3bbe9e9 --- /dev/null +++ b/tests/proj2/tests/i32.lt_u0.wasm diff --git a/tests/proj2/tests/i32.lt_u0.wat b/tests/proj2/tests/i32.lt_u0.wat new file mode 100644 index 0000000..8586101 --- /dev/null +++ b/tests/proj2/tests/i32.lt_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.lt_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.lt_u0.wee.wasm b/tests/proj2/tests/i32.lt_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..0d83759 --- /dev/null +++ b/tests/proj2/tests/i32.lt_u0.wee.wasm diff --git a/tests/proj2/tests/i32.mul0.runs b/tests/proj2/tests/i32.mul0.runs new file mode 100644 index 0000000..b0374bc --- /dev/null +++ b/tests/proj2/tests/i32.mul0.runs @@ -0,0 +1,9 @@ +8 9 = 72 +33 44 = 1452 +111 222 = 24642 +2222 3333 = 7405926 +111111111 666666666 = 1332460582 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = 909101411 +2000000000 1 = 2000000000 +2000000000 3 = 1705032704 diff --git a/tests/proj2/tests/i32.mul0.wasm b/tests/proj2/tests/i32.mul0.wasm Binary files differnew file mode 100644 index 0000000..ac058f7 --- /dev/null +++ b/tests/proj2/tests/i32.mul0.wasm diff --git a/tests/proj2/tests/i32.mul0.wat b/tests/proj2/tests/i32.mul0.wat new file mode 100644 index 0000000..950ccf9 --- /dev/null +++ b/tests/proj2/tests/i32.mul0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.mul (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.mul0.wee.wasm b/tests/proj2/tests/i32.mul0.wee.wasm Binary files differnew file mode 100644 index 0000000..e43be6e --- /dev/null +++ b/tests/proj2/tests/i32.mul0.wee.wasm diff --git a/tests/proj2/tests/i32.ne0.runs b/tests/proj2/tests/i32.ne0.runs new file mode 100644 index 0000000..2d9e7fe --- /dev/null +++ b/tests/proj2/tests/i32.ne0.runs @@ -0,0 +1,5 @@ +0 0 = 0 +1 0 = 1 +0 1 = 1 +5555 5555 = 0 +-87239487 -8723487 = 1 diff --git a/tests/proj2/tests/i32.ne0.wasm b/tests/proj2/tests/i32.ne0.wasm Binary files differnew file mode 100644 index 0000000..e53b5f7 --- /dev/null +++ b/tests/proj2/tests/i32.ne0.wasm diff --git a/tests/proj2/tests/i32.ne0.wat b/tests/proj2/tests/i32.ne0.wat new file mode 100644 index 0000000..cefe4f1 --- /dev/null +++ b/tests/proj2/tests/i32.ne0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.ne (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.ne0.wee.wasm b/tests/proj2/tests/i32.ne0.wee.wasm Binary files differnew file mode 100644 index 0000000..578fc5b --- /dev/null +++ b/tests/proj2/tests/i32.ne0.wee.wasm diff --git a/tests/proj2/tests/i32.or0.runs b/tests/proj2/tests/i32.or0.runs new file mode 100644 index 0000000..94753f6 --- /dev/null +++ b/tests/proj2/tests/i32.or0.runs @@ -0,0 +1,4 @@ +876234 982134 = 1048318 +897234 0 = 897234 +89273498 -1 = -1 +-555 -2147483648 = -555 diff --git a/tests/proj2/tests/i32.or0.wasm b/tests/proj2/tests/i32.or0.wasm Binary files differnew file mode 100644 index 0000000..c1f46c7 --- /dev/null +++ b/tests/proj2/tests/i32.or0.wasm diff --git a/tests/proj2/tests/i32.or0.wat b/tests/proj2/tests/i32.or0.wat new file mode 100644 index 0000000..8763eb7 --- /dev/null +++ b/tests/proj2/tests/i32.or0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.or (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.or0.wee.wasm b/tests/proj2/tests/i32.or0.wee.wasm Binary files differnew file mode 100644 index 0000000..df51bb9 --- /dev/null +++ b/tests/proj2/tests/i32.or0.wee.wasm diff --git a/tests/proj2/tests/i32.popcnt0.runs b/tests/proj2/tests/i32.popcnt0.runs new file mode 100644 index 0000000..10de3e3 --- /dev/null +++ b/tests/proj2/tests/i32.popcnt0.runs @@ -0,0 +1,6 @@ +0 = 0 +1 = 1 +2 = 1 +89721348 = 9 +-8934345 = 23 +-2147483648 = 1 diff --git a/tests/proj2/tests/i32.popcnt0.wasm b/tests/proj2/tests/i32.popcnt0.wasm Binary files differnew file mode 100644 index 0000000..758dffc --- /dev/null +++ b/tests/proj2/tests/i32.popcnt0.wasm diff --git a/tests/proj2/tests/i32.popcnt0.wat b/tests/proj2/tests/i32.popcnt0.wat new file mode 100644 index 0000000..d7017d1 --- /dev/null +++ b/tests/proj2/tests/i32.popcnt0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.popcnt (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.popcnt0.wee.wasm b/tests/proj2/tests/i32.popcnt0.wee.wasm Binary files differnew file mode 100644 index 0000000..cf78011 --- /dev/null +++ b/tests/proj2/tests/i32.popcnt0.wee.wasm diff --git a/tests/proj2/tests/i32.rem_s0.runs b/tests/proj2/tests/i32.rem_s0.runs new file mode 100644 index 0000000..a9c3537 --- /dev/null +++ b/tests/proj2/tests/i32.rem_s0.runs @@ -0,0 +1,8 @@ +99 10 = 9 +107 -10 = 7 +-107 -10 = -7 +-107 10 = -7 +1 0 = !trap +5559823 1 = 0 +-2147483648 -1 = 0 +876345 -1 = 0 diff --git a/tests/proj2/tests/i32.rem_s0.wasm b/tests/proj2/tests/i32.rem_s0.wasm Binary files differnew file mode 100644 index 0000000..64c2f86 --- /dev/null +++ b/tests/proj2/tests/i32.rem_s0.wasm diff --git a/tests/proj2/tests/i32.rem_s0.wat b/tests/proj2/tests/i32.rem_s0.wat new file mode 100644 index 0000000..e779dd8 --- /dev/null +++ b/tests/proj2/tests/i32.rem_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.rem_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.rem_s0.wee.wasm b/tests/proj2/tests/i32.rem_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..fafce8b --- /dev/null +++ b/tests/proj2/tests/i32.rem_s0.wee.wasm diff --git a/tests/proj2/tests/i32.rem_u0.runs b/tests/proj2/tests/i32.rem_u0.runs new file mode 100644 index 0000000..d9f3ea6 --- /dev/null +++ b/tests/proj2/tests/i32.rem_u0.runs @@ -0,0 +1,5 @@ +13338 10 = 8 +99 -3 = 99 +1 0 = !trap +555 1 = 0 +-2147483648 -1 = -2147483648 diff --git a/tests/proj2/tests/i32.rem_u0.wasm b/tests/proj2/tests/i32.rem_u0.wasm Binary files differnew file mode 100644 index 0000000..cb08fe9 --- /dev/null +++ b/tests/proj2/tests/i32.rem_u0.wasm diff --git a/tests/proj2/tests/i32.rem_u0.wat b/tests/proj2/tests/i32.rem_u0.wat new file mode 100644 index 0000000..7b26f03 --- /dev/null +++ b/tests/proj2/tests/i32.rem_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.rem_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.rem_u0.wee.wasm b/tests/proj2/tests/i32.rem_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..7a3a50a --- /dev/null +++ b/tests/proj2/tests/i32.rem_u0.wee.wasm diff --git a/tests/proj2/tests/i32.rotl0.runs b/tests/proj2/tests/i32.rotl0.runs new file mode 100644 index 0000000..ac7cbf5 --- /dev/null +++ b/tests/proj2/tests/i32.rotl0.runs @@ -0,0 +1,5 @@ +1044480 0 = 1044480 +1044480 32 = 1044480 +8972134 13 = 485277713 +-8972134 13 = -485269522 +-1412628189 36 = -1127214534 diff --git a/tests/proj2/tests/i32.rotl0.wasm b/tests/proj2/tests/i32.rotl0.wasm Binary files differnew file mode 100644 index 0000000..3dc31fc --- /dev/null +++ b/tests/proj2/tests/i32.rotl0.wasm diff --git a/tests/proj2/tests/i32.rotl0.wat b/tests/proj2/tests/i32.rotl0.wat new file mode 100644 index 0000000..aee7a86 --- /dev/null +++ b/tests/proj2/tests/i32.rotl0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.rotl (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.rotl0.wee.wasm b/tests/proj2/tests/i32.rotl0.wee.wasm Binary files differnew file mode 100644 index 0000000..5d4bd39 --- /dev/null +++ b/tests/proj2/tests/i32.rotl0.wee.wasm diff --git a/tests/proj2/tests/i32.rotr0.runs b/tests/proj2/tests/i32.rotr0.runs new file mode 100644 index 0000000..5dd3a4e --- /dev/null +++ b/tests/proj2/tests/i32.rotr0.runs @@ -0,0 +1,5 @@ +1044480 0 = 1044480 +1044480 32 = 1044480 +8972134 13 = 993002567 +-8972134 13 = -992478280 +-1412628189 36 = 985452562 diff --git a/tests/proj2/tests/i32.rotr0.wasm b/tests/proj2/tests/i32.rotr0.wasm Binary files differnew file mode 100644 index 0000000..aae96a1 --- /dev/null +++ b/tests/proj2/tests/i32.rotr0.wasm diff --git a/tests/proj2/tests/i32.rotr0.wat b/tests/proj2/tests/i32.rotr0.wat new file mode 100644 index 0000000..c563af3 --- /dev/null +++ b/tests/proj2/tests/i32.rotr0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.rotr (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.rotr0.wee.wasm b/tests/proj2/tests/i32.rotr0.wee.wasm Binary files differnew file mode 100644 index 0000000..4161906 --- /dev/null +++ b/tests/proj2/tests/i32.rotr0.wee.wasm diff --git a/tests/proj2/tests/i32.shl0.runs b/tests/proj2/tests/i32.shl0.runs new file mode 100644 index 0000000..449f471 --- /dev/null +++ b/tests/proj2/tests/i32.shl0.runs @@ -0,0 +1,5 @@ +1044480 0 = 1044480 +1044480 32 = 1044480 +8972134 23 = -1291845632 +-1 31 = -2147483648 +1044480 36 = 16711680 diff --git a/tests/proj2/tests/i32.shl0.wasm b/tests/proj2/tests/i32.shl0.wasm Binary files differnew file mode 100644 index 0000000..dcc34a4 --- /dev/null +++ b/tests/proj2/tests/i32.shl0.wasm diff --git a/tests/proj2/tests/i32.shl0.wat b/tests/proj2/tests/i32.shl0.wat new file mode 100644 index 0000000..0fee16f --- /dev/null +++ b/tests/proj2/tests/i32.shl0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.shl (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.shl0.wee.wasm b/tests/proj2/tests/i32.shl0.wee.wasm Binary files differnew file mode 100644 index 0000000..fcc234a --- /dev/null +++ b/tests/proj2/tests/i32.shl0.wee.wasm diff --git a/tests/proj2/tests/i32.shr_s0.runs b/tests/proj2/tests/i32.shr_s0.runs new file mode 100644 index 0000000..eb74900 --- /dev/null +++ b/tests/proj2/tests/i32.shr_s0.runs @@ -0,0 +1,7 @@ +1044480 0 = 1044480 +1044480 32 = 1044480 +8972134 13 = 1095 +-8972134 13 = -1096 +268435455 27 = 1 +-256 4 = -16 +1044480 36 = 65280 diff --git a/tests/proj2/tests/i32.shr_s0.wasm b/tests/proj2/tests/i32.shr_s0.wasm Binary files differnew file mode 100644 index 0000000..7717511 --- /dev/null +++ b/tests/proj2/tests/i32.shr_s0.wasm diff --git a/tests/proj2/tests/i32.shr_s0.wat b/tests/proj2/tests/i32.shr_s0.wat new file mode 100644 index 0000000..e3d9d75 --- /dev/null +++ b/tests/proj2/tests/i32.shr_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.shr_s (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.shr_s0.wee.wasm b/tests/proj2/tests/i32.shr_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..69fc69e --- /dev/null +++ b/tests/proj2/tests/i32.shr_s0.wee.wasm diff --git a/tests/proj2/tests/i32.shr_u0.runs b/tests/proj2/tests/i32.shr_u0.runs new file mode 100644 index 0000000..cd50052 --- /dev/null +++ b/tests/proj2/tests/i32.shr_u0.runs @@ -0,0 +1,6 @@ +1044480 0 = 1044480 +1044480 32 = 1044480 +8972134 13 = 1095 +-8972134 13 = 523192 +-1 31 = 1 +1044480 36 = 65280 diff --git a/tests/proj2/tests/i32.shr_u0.wasm b/tests/proj2/tests/i32.shr_u0.wasm Binary files differnew file mode 100644 index 0000000..273fcc0 --- /dev/null +++ b/tests/proj2/tests/i32.shr_u0.wasm diff --git a/tests/proj2/tests/i32.shr_u0.wat b/tests/proj2/tests/i32.shr_u0.wat new file mode 100644 index 0000000..3609d05 --- /dev/null +++ b/tests/proj2/tests/i32.shr_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.shr_u (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.shr_u0.wee.wasm b/tests/proj2/tests/i32.shr_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..a560fbd --- /dev/null +++ b/tests/proj2/tests/i32.shr_u0.wee.wasm diff --git a/tests/proj2/tests/i32.store0.runs b/tests/proj2/tests/i32.store0.runs new file mode 100644 index 0000000..eb9aada --- /dev/null +++ b/tests/proj2/tests/i32.store0.runs @@ -0,0 +1,10 @@ +0 = 0 +996 = 0 +997 = 1426063360 +998 = 1146421248 +999 = 860116224 +1000 = 573785173 +1001 = 2241348 +1002 = 8755 +1003 = 34 +1004 = 0 diff --git a/tests/proj2/tests/i32.store0.wasm b/tests/proj2/tests/i32.store0.wasm Binary files differnew file mode 100644 index 0000000..8579aba --- /dev/null +++ b/tests/proj2/tests/i32.store0.wasm diff --git a/tests/proj2/tests/i32.store0.wat b/tests/proj2/tests/i32.store0.wat new file mode 100644 index 0000000..0596153 --- /dev/null +++ b/tests/proj2/tests/i32.store0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.store (i32.const 1000) (i32.const 0x22334455)) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.store0.wee.wasm b/tests/proj2/tests/i32.store0.wee.wasm Binary files differnew file mode 100644 index 0000000..9a0206e --- /dev/null +++ b/tests/proj2/tests/i32.store0.wee.wasm diff --git a/tests/proj2/tests/i32.store1.runs b/tests/proj2/tests/i32.store1.runs new file mode 100644 index 0000000..107460d --- /dev/null +++ b/tests/proj2/tests/i32.store1.runs @@ -0,0 +1,10 @@ +496 = 0 +497 = 34 +498 = 8755 +499 = 2241348 +500 = 573785173 +501 = 860116224 +502 = 1146421248 +503 = 1426063360 +504 = 0 +505 = 0 diff --git a/tests/proj2/tests/i32.store1.wasm b/tests/proj2/tests/i32.store1.wasm Binary files differnew file mode 100644 index 0000000..c590d88 --- /dev/null +++ b/tests/proj2/tests/i32.store1.wasm diff --git a/tests/proj2/tests/i32.store1.wat b/tests/proj2/tests/i32.store1.wat new file mode 100644 index 0000000..74bb665 --- /dev/null +++ b/tests/proj2/tests/i32.store1.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.store (local.get 0) (i32.const 0x22334455)) + (i32.load (i32.const 500)) + ) +) diff --git a/tests/proj2/tests/i32.store1.wee.wasm b/tests/proj2/tests/i32.store1.wee.wasm Binary files differnew file mode 100644 index 0000000..ccb06d8 --- /dev/null +++ b/tests/proj2/tests/i32.store1.wee.wasm diff --git a/tests/proj2/tests/i32.store16_0.runs b/tests/proj2/tests/i32.store16_0.runs new file mode 100644 index 0000000..5c30cf5 --- /dev/null +++ b/tests/proj2/tests/i32.store16_0.runs @@ -0,0 +1,10 @@ +0 = 0 +996 = 0 +997 = 1426063360 +998 = 1146421248 +999 = 4478208 +1000 = 17493 +1001 = 68 +1002 = 0 +1003 = 0 +1004 = 0 diff --git a/tests/proj2/tests/i32.store16_0.wasm b/tests/proj2/tests/i32.store16_0.wasm Binary files differnew file mode 100644 index 0000000..15d8f76 --- /dev/null +++ b/tests/proj2/tests/i32.store16_0.wasm diff --git a/tests/proj2/tests/i32.store16_0.wat b/tests/proj2/tests/i32.store16_0.wat new file mode 100644 index 0000000..95519fd --- /dev/null +++ b/tests/proj2/tests/i32.store16_0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.store16 (i32.const 1000) (i32.const 0x22334455)) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.store16_0.wee.wasm b/tests/proj2/tests/i32.store16_0.wee.wasm Binary files differnew file mode 100644 index 0000000..291c0af --- /dev/null +++ b/tests/proj2/tests/i32.store16_0.wee.wasm diff --git a/tests/proj2/tests/i32.store8_0.runs b/tests/proj2/tests/i32.store8_0.runs new file mode 100644 index 0000000..2ab9847 --- /dev/null +++ b/tests/proj2/tests/i32.store8_0.runs @@ -0,0 +1,10 @@ +0 = 0 +996 = 0 +997 = 1426063360 +998 = 5570560 +999 = 21760 +1000 = 85 +1001 = 0 +1002 = 0 +1003 = 0 +1004 = 0 diff --git a/tests/proj2/tests/i32.store8_0.wasm b/tests/proj2/tests/i32.store8_0.wasm Binary files differnew file mode 100644 index 0000000..225bc26 --- /dev/null +++ b/tests/proj2/tests/i32.store8_0.wasm diff --git a/tests/proj2/tests/i32.store8_0.wat b/tests/proj2/tests/i32.store8_0.wat new file mode 100644 index 0000000..649338d --- /dev/null +++ b/tests/proj2/tests/i32.store8_0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (i32.store8 (i32.const 1000) (i32.const 0x22334455)) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.store8_0.wee.wasm b/tests/proj2/tests/i32.store8_0.wee.wasm Binary files differnew file mode 100644 index 0000000..e6b688e --- /dev/null +++ b/tests/proj2/tests/i32.store8_0.wee.wasm diff --git a/tests/proj2/tests/i32.sub0.runs b/tests/proj2/tests/i32.sub0.runs new file mode 100644 index 0000000..dd17d1b --- /dev/null +++ b/tests/proj2/tests/i32.sub0.runs @@ -0,0 +1,8 @@ +8 9 = -1 +33 44 = -11 +111 222 = -111 +2222 3333 = -1111 +111111111 666666666 = -555555555 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = -35791394 +2000000000 1 = 1999999999 diff --git a/tests/proj2/tests/i32.sub0.wasm b/tests/proj2/tests/i32.sub0.wasm Binary files differnew file mode 100644 index 0000000..60d2e71 --- /dev/null +++ b/tests/proj2/tests/i32.sub0.wasm diff --git a/tests/proj2/tests/i32.sub0.wat b/tests/proj2/tests/i32.sub0.wat new file mode 100644 index 0000000..0a6782a --- /dev/null +++ b/tests/proj2/tests/i32.sub0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.sub (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.sub0.wee.wasm b/tests/proj2/tests/i32.sub0.wee.wasm Binary files differnew file mode 100644 index 0000000..579d572 --- /dev/null +++ b/tests/proj2/tests/i32.sub0.wee.wasm diff --git a/tests/proj2/tests/i32.trunc_f64_s0.runs b/tests/proj2/tests/i32.trunc_f64_s0.runs new file mode 100644 index 0000000..bc9401f --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_s0.runs @@ -0,0 +1,8 @@ +0d = 0 +0.9d = 0 +-0.9d = 0 +1d = 1 +-87234d = -87234 +-2147483648d = -2147483648 +-3000000000d = !trap +3000000000d = !trap diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wasm b/tests/proj2/tests/i32.trunc_f64_s0.wasm Binary files differnew file mode 100644 index 0000000..672b69c --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_s0.wasm diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wat b/tests/proj2/tests/i32.trunc_f64_s0.wat new file mode 100644 index 0000000..c70234b --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_s0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64) (result i32) + (i32.trunc_f64_s (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm b/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm Binary files differnew file mode 100644 index 0000000..fa6f6ba --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_s0.wee.wasm diff --git a/tests/proj2/tests/i32.trunc_f64_u0.runs b/tests/proj2/tests/i32.trunc_f64_u0.runs new file mode 100644 index 0000000..13759f2 --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_u0.runs @@ -0,0 +1,7 @@ +0d = 0 +1d = 1 +0.9d = 0 +-0.9d = 0 +-87234d = !trap +-2147483648d = !trap +3000000000d = -1294967296 diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wasm b/tests/proj2/tests/i32.trunc_f64_u0.wasm Binary files differnew file mode 100644 index 0000000..5e161df --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_u0.wasm diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wat b/tests/proj2/tests/i32.trunc_f64_u0.wat new file mode 100644 index 0000000..54f39b4 --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_u0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param f64) (result i32) + (i32.trunc_f64_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm b/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm Binary files differnew file mode 100644 index 0000000..242b7bb --- /dev/null +++ b/tests/proj2/tests/i32.trunc_f64_u0.wee.wasm diff --git a/tests/proj2/tests/i32.xor0.runs b/tests/proj2/tests/i32.xor0.runs new file mode 100644 index 0000000..d0a1f1a --- /dev/null +++ b/tests/proj2/tests/i32.xor0.runs @@ -0,0 +1,4 @@ +876234 982134 = 238268 +897234 0 = 897234 +89273498 -1 = -89273499 +-555 -2147483648 = 2147483093 diff --git a/tests/proj2/tests/i32.xor0.wasm b/tests/proj2/tests/i32.xor0.wasm Binary files differnew file mode 100644 index 0000000..3a0d000 --- /dev/null +++ b/tests/proj2/tests/i32.xor0.wasm diff --git a/tests/proj2/tests/i32.xor0.wat b/tests/proj2/tests/i32.xor0.wat new file mode 100644 index 0000000..a982151 --- /dev/null +++ b/tests/proj2/tests/i32.xor0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.xor (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/i32.xor0.wee.wasm b/tests/proj2/tests/i32.xor0.wee.wasm Binary files differnew file mode 100644 index 0000000..9e015ae --- /dev/null +++ b/tests/proj2/tests/i32.xor0.wee.wasm diff --git a/tests/proj2/tests/load_oob0.runs b/tests/proj2/tests/load_oob0.runs new file mode 100644 index 0000000..de1a1e0 --- /dev/null +++ b/tests/proj2/tests/load_oob0.runs @@ -0,0 +1,12 @@ +65531 = 1144201728 +65532 = 1430532898 +65533 = !trap +65534 = !trap +65535 = !trap +65536 = !trap +100000 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/load_oob0.wasm b/tests/proj2/tests/load_oob0.wasm Binary files differnew file mode 100644 index 0000000..52c4268 --- /dev/null +++ b/tests/proj2/tests/load_oob0.wasm diff --git a/tests/proj2/tests/load_oob0.wat b/tests/proj2/tests/load_oob0.wat new file mode 100644 index 0000000..08e9555 --- /dev/null +++ b/tests/proj2/tests/load_oob0.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 65532) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/load_oob0.wee.wasm b/tests/proj2/tests/load_oob0.wee.wasm Binary files differnew file mode 100644 index 0000000..2f26796 --- /dev/null +++ b/tests/proj2/tests/load_oob0.wee.wasm diff --git a/tests/proj2/tests/load_oob1.runs b/tests/proj2/tests/load_oob1.runs new file mode 100644 index 0000000..a594e28 --- /dev/null +++ b/tests/proj2/tests/load_oob1.runs @@ -0,0 +1,16 @@ +65531 = 0 +65532 = 0 +65533 = 0 +65534 = 0 +131066 = 857866240 +131067 = 1144201728 +131068 = 1430532898 +131069 = !trap +131070 = !trap +131071 = !trap +131072 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/load_oob1.wasm b/tests/proj2/tests/load_oob1.wasm Binary files differnew file mode 100644 index 0000000..add5875 --- /dev/null +++ b/tests/proj2/tests/load_oob1.wasm diff --git a/tests/proj2/tests/load_oob1.wat b/tests/proj2/tests/load_oob1.wat new file mode 100644 index 0000000..1317e30 --- /dev/null +++ b/tests/proj2/tests/load_oob1.wat @@ -0,0 +1,7 @@ +(module + (memory 2) + (data (i32.const 131068) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.load (local.get 0)) + ) +) diff --git a/tests/proj2/tests/load_oob1.wee.wasm b/tests/proj2/tests/load_oob1.wee.wasm Binary files differnew file mode 100644 index 0000000..818df89 --- /dev/null +++ b/tests/proj2/tests/load_oob1.wee.wasm diff --git a/tests/proj2/tests/load_oob2.runs b/tests/proj2/tests/load_oob2.runs new file mode 100644 index 0000000..23c54a5 --- /dev/null +++ b/tests/proj2/tests/load_oob2.runs @@ -0,0 +1,12 @@ +65531 = 0 +65532 = 34 +65533 = 51 +65534 = 68 +65535 = 85 +65536 = !trap +100000 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/load_oob2.wasm b/tests/proj2/tests/load_oob2.wasm Binary files differnew file mode 100644 index 0000000..02f28c9 --- /dev/null +++ b/tests/proj2/tests/load_oob2.wasm diff --git a/tests/proj2/tests/load_oob2.wat b/tests/proj2/tests/load_oob2.wat new file mode 100644 index 0000000..c00e6c0 --- /dev/null +++ b/tests/proj2/tests/load_oob2.wat @@ -0,0 +1,7 @@ +(module + (memory 1) + (data (i32.const 65532) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) diff --git a/tests/proj2/tests/load_oob2.wee.wasm b/tests/proj2/tests/load_oob2.wee.wasm Binary files differnew file mode 100644 index 0000000..c33c69a --- /dev/null +++ b/tests/proj2/tests/load_oob2.wee.wasm diff --git a/tests/proj2/tests/load_oob3.runs b/tests/proj2/tests/load_oob3.runs new file mode 100644 index 0000000..de1a1e0 --- /dev/null +++ b/tests/proj2/tests/load_oob3.runs @@ -0,0 +1,12 @@ +65531 = 1144201728 +65532 = 1430532898 +65533 = !trap +65534 = !trap +65535 = !trap +65536 = !trap +100000 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/load_oob3.wasm b/tests/proj2/tests/load_oob3.wasm Binary files differnew file mode 100644 index 0000000..b68d6d0 --- /dev/null +++ b/tests/proj2/tests/load_oob3.wasm diff --git a/tests/proj2/tests/load_oob3.wat b/tests/proj2/tests/load_oob3.wat new file mode 100644 index 0000000..782c62c --- /dev/null +++ b/tests/proj2/tests/load_oob3.wat @@ -0,0 +1,7 @@ +(module + (memory 2) + (data (i32.const 131068) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.load offset=65536 (local.get 0)) + ) +) diff --git a/tests/proj2/tests/load_oob3.wee.wasm b/tests/proj2/tests/load_oob3.wee.wasm Binary files differnew file mode 100644 index 0000000..21edfed --- /dev/null +++ b/tests/proj2/tests/load_oob3.wee.wasm diff --git a/tests/proj2/tests/load_oob5.runs b/tests/proj2/tests/load_oob5.runs new file mode 100644 index 0000000..b57668e --- /dev/null +++ b/tests/proj2/tests/load_oob5.runs @@ -0,0 +1,12 @@ +0 = 145 +1 = 145 +1000 = 145 +65528 = 145 +65529 = !trap +65530 = !trap +65531 = !trap +65532 = !trap +65533 = !trap +65534 = !trap +65535 = !trap +65536 = !trap diff --git a/tests/proj2/tests/load_oob5.wasm b/tests/proj2/tests/load_oob5.wasm Binary files differnew file mode 100644 index 0000000..fca4f9b --- /dev/null +++ b/tests/proj2/tests/load_oob5.wasm diff --git a/tests/proj2/tests/load_oob5.wat b/tests/proj2/tests/load_oob5.wat new file mode 100644 index 0000000..0f38d58 --- /dev/null +++ b/tests/proj2/tests/load_oob5.wat @@ -0,0 +1,8 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (f64.load (local.get 0)) + (drop) + (i32.const 145) + ) +) diff --git a/tests/proj2/tests/load_oob5.wee.wasm b/tests/proj2/tests/load_oob5.wee.wasm Binary files differnew file mode 100644 index 0000000..3ced6de --- /dev/null +++ b/tests/proj2/tests/load_oob5.wee.wasm diff --git a/tests/proj2/tests/load_oob6.runs b/tests/proj2/tests/load_oob6.runs new file mode 100644 index 0000000..6b5514e --- /dev/null +++ b/tests/proj2/tests/load_oob6.runs @@ -0,0 +1,12 @@ +0 = 143 +1 = 143 +1000 = 143 +5528 = 143 +5529 = !trap +5530 = !trap +5531 = !trap +5532 = !trap +5533 = !trap +5534 = !trap +5535 = !trap +5536 = !trap diff --git a/tests/proj2/tests/load_oob6.wasm b/tests/proj2/tests/load_oob6.wasm Binary files differnew file mode 100644 index 0000000..3deb2c9 --- /dev/null +++ b/tests/proj2/tests/load_oob6.wasm diff --git a/tests/proj2/tests/load_oob6.wat b/tests/proj2/tests/load_oob6.wat new file mode 100644 index 0000000..1b9435a --- /dev/null +++ b/tests/proj2/tests/load_oob6.wat @@ -0,0 +1,8 @@ +(module + (memory 1) + (func (export "main") (param i32) (result i32) + (f64.load offset=60000 (local.get 0)) + (drop) + (i32.const 143) + ) +) diff --git a/tests/proj2/tests/load_oob6.wee.wasm b/tests/proj2/tests/load_oob6.wee.wasm Binary files differnew file mode 100644 index 0000000..af3ab64 --- /dev/null +++ b/tests/proj2/tests/load_oob6.wee.wasm diff --git a/tests/proj2/tests/mul0.runs b/tests/proj2/tests/mul0.runs new file mode 100644 index 0000000..b0374bc --- /dev/null +++ b/tests/proj2/tests/mul0.runs @@ -0,0 +1,9 @@ +8 9 = 72 +33 44 = 1452 +111 222 = 24642 +2222 3333 = 7405926 +111111111 666666666 = 1332460582 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = 909101411 +2000000000 1 = 2000000000 +2000000000 3 = 1705032704 diff --git a/tests/proj2/tests/mul0.wasm b/tests/proj2/tests/mul0.wasm Binary files differnew file mode 100644 index 0000000..ac058f7 --- /dev/null +++ b/tests/proj2/tests/mul0.wasm diff --git a/tests/proj2/tests/mul0.wat b/tests/proj2/tests/mul0.wat new file mode 100644 index 0000000..950ccf9 --- /dev/null +++ b/tests/proj2/tests/mul0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.mul (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/mul0.wee.wasm b/tests/proj2/tests/mul0.wee.wasm Binary files differnew file mode 100644 index 0000000..e43be6e --- /dev/null +++ b/tests/proj2/tests/mul0.wee.wasm diff --git a/tests/proj2/tests/rec.runs b/tests/proj2/tests/rec.runs new file mode 100644 index 0000000..e4b0cf4 --- /dev/null +++ b/tests/proj2/tests/rec.runs @@ -0,0 +1 @@ +0 = 20 diff --git a/tests/proj2/tests/rec.wasm b/tests/proj2/tests/rec.wasm Binary files differnew file mode 100644 index 0000000..961f36a --- /dev/null +++ b/tests/proj2/tests/rec.wasm diff --git a/tests/proj2/tests/rec.wat b/tests/proj2/tests/rec.wat new file mode 100644 index 0000000..b6c0abe --- /dev/null +++ b/tests/proj2/tests/rec.wat @@ -0,0 +1,11 @@ +(module + (global $g (mut i32) (i32.const 20)) + (func $ref (export "main") (param i32) (result i32) + (global.get $g) + (br_if 0 (i32.le_s (local.get 0) (i32.const 0))) + (i32.const 1) + (i32.add) + (global.set $g) + (call $ref (i32.sub (local.get 0) (i32.const 1))) + ) +) diff --git a/tests/proj2/tests/rec.wee.wasm b/tests/proj2/tests/rec.wee.wasm Binary files differnew file mode 100644 index 0000000..116a9f9 --- /dev/null +++ b/tests/proj2/tests/rec.wee.wasm diff --git a/tests/proj2/tests/return0.expect b/tests/proj2/tests/return0.expect new file mode 100644 index 0000000..98d9bcb --- /dev/null +++ b/tests/proj2/tests/return0.expect @@ -0,0 +1 @@ +17 diff --git a/tests/proj2/tests/return0.wasm b/tests/proj2/tests/return0.wasm Binary files differnew file mode 100644 index 0000000..22a9a60 --- /dev/null +++ b/tests/proj2/tests/return0.wasm diff --git a/tests/proj2/tests/return0.wat b/tests/proj2/tests/return0.wat new file mode 100644 index 0000000..796dfd6 --- /dev/null +++ b/tests/proj2/tests/return0.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (result i32) + i32.const 17 + return + ) +) diff --git a/tests/proj2/tests/return0.wee.wasm b/tests/proj2/tests/return0.wee.wasm Binary files differnew file mode 100644 index 0000000..66cbcb7 --- /dev/null +++ b/tests/proj2/tests/return0.wee.wasm diff --git a/tests/proj2/tests/return1.expect b/tests/proj2/tests/return1.expect new file mode 100644 index 0000000..b6a7d89 --- /dev/null +++ b/tests/proj2/tests/return1.expect @@ -0,0 +1 @@ +16 diff --git a/tests/proj2/tests/return1.wasm b/tests/proj2/tests/return1.wasm Binary files differnew file mode 100644 index 0000000..5bf6a32 --- /dev/null +++ b/tests/proj2/tests/return1.wasm diff --git a/tests/proj2/tests/return1.wat b/tests/proj2/tests/return1.wat new file mode 100644 index 0000000..4a6c696 --- /dev/null +++ b/tests/proj2/tests/return1.wat @@ -0,0 +1,7 @@ +(module + (func (export "main") (result i32) + i32.const 33 + i32.const 16 + return + ) +) diff --git a/tests/proj2/tests/return1.wee.wasm b/tests/proj2/tests/return1.wee.wasm Binary files differnew file mode 100644 index 0000000..100a386 --- /dev/null +++ b/tests/proj2/tests/return1.wee.wasm diff --git a/tests/proj2/tests/return2.expect b/tests/proj2/tests/return2.expect new file mode 100644 index 0000000..60d3b2f --- /dev/null +++ b/tests/proj2/tests/return2.expect @@ -0,0 +1 @@ +15 diff --git a/tests/proj2/tests/return2.wasm b/tests/proj2/tests/return2.wasm Binary files differnew file mode 100644 index 0000000..8a678b3 --- /dev/null +++ b/tests/proj2/tests/return2.wasm diff --git a/tests/proj2/tests/return2.wat b/tests/proj2/tests/return2.wat new file mode 100644 index 0000000..12dbcdb --- /dev/null +++ b/tests/proj2/tests/return2.wat @@ -0,0 +1,16 @@ +(module + (func (export "main") (result i32) + i32.const 31 + i32.const 32 + i32.const 33 + i32.const 34 + i32.const 35 + i32.const 36 + i32.const 37 + i32.const 38 + i32.const 39 + i32.const 39 + i32.const 15 + return + ) +) diff --git a/tests/proj2/tests/return2.wee.wasm b/tests/proj2/tests/return2.wee.wasm Binary files differnew file mode 100644 index 0000000..db836c2 --- /dev/null +++ b/tests/proj2/tests/return2.wee.wasm diff --git a/tests/proj2/tests/start0.expect b/tests/proj2/tests/start0.expect new file mode 100644 index 0000000..7273c0f --- /dev/null +++ b/tests/proj2/tests/start0.expect @@ -0,0 +1 @@ +25 diff --git a/tests/proj2/tests/start0.wasm b/tests/proj2/tests/start0.wasm Binary files differnew file mode 100644 index 0000000..e599fdf --- /dev/null +++ b/tests/proj2/tests/start0.wasm diff --git a/tests/proj2/tests/start0.wat b/tests/proj2/tests/start0.wat new file mode 100644 index 0000000..a498865 --- /dev/null +++ b/tests/proj2/tests/start0.wat @@ -0,0 +1,8 @@ +(module + (global $g (mut i32) (i32.const 20)) + (func $start (global.set $g (i32.const 25))) + (start $start) + (func (export "main") (result i32) + (global.get $g) + ) +)
\ No newline at end of file diff --git a/tests/proj2/tests/start0.wee.wasm b/tests/proj2/tests/start0.wee.wasm Binary files differnew file mode 100644 index 0000000..f98c676 --- /dev/null +++ b/tests/proj2/tests/start0.wee.wasm diff --git a/tests/proj2/tests/store_oob0.runs b/tests/proj2/tests/store_oob0.runs new file mode 100644 index 0000000..572928c --- /dev/null +++ b/tests/proj2/tests/store_oob0.runs @@ -0,0 +1,12 @@ +65531 = 12 +65532 = 12 +65533 = !trap +65534 = !trap +65535 = !trap +65536 = !trap +100000 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/store_oob0.wasm b/tests/proj2/tests/store_oob0.wasm Binary files differnew file mode 100644 index 0000000..1fa722a --- /dev/null +++ b/tests/proj2/tests/store_oob0.wasm diff --git a/tests/proj2/tests/store_oob0.wat b/tests/proj2/tests/store_oob0.wat new file mode 100644 index 0000000..a16bdf7 --- /dev/null +++ b/tests/proj2/tests/store_oob0.wat @@ -0,0 +1,8 @@ +(module + (memory 1) + (data (i32.const 65532) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.store (local.get 0) (i32.const 3)) + (i32.const 12) + ) +) diff --git a/tests/proj2/tests/store_oob0.wee.wasm b/tests/proj2/tests/store_oob0.wee.wasm Binary files differnew file mode 100644 index 0000000..676005b --- /dev/null +++ b/tests/proj2/tests/store_oob0.wee.wasm diff --git a/tests/proj2/tests/store_oob2.runs b/tests/proj2/tests/store_oob2.runs new file mode 100644 index 0000000..0461704 --- /dev/null +++ b/tests/proj2/tests/store_oob2.runs @@ -0,0 +1,12 @@ +65531 = 77 +65532 = 77 +65533 = 77 +65534 = 77 +65535 = 77 +65536 = !trap +100000 = !trap +1000000 = !trap +10000000 = !trap +100000000 = !trap +1000000000 = !trap +-1 = !trap diff --git a/tests/proj2/tests/store_oob2.wasm b/tests/proj2/tests/store_oob2.wasm Binary files differnew file mode 100644 index 0000000..cc9678a --- /dev/null +++ b/tests/proj2/tests/store_oob2.wasm diff --git a/tests/proj2/tests/store_oob2.wat b/tests/proj2/tests/store_oob2.wat new file mode 100644 index 0000000..e841c59 --- /dev/null +++ b/tests/proj2/tests/store_oob2.wat @@ -0,0 +1,8 @@ +(module + (memory 1) + (data (i32.const 65532) "\22\33\44\55") + (func (export "main") (param i32) (result i32) + (i32.store8 (local.get 0) (i32.const 44)) + (i32.const 77) + ) +) diff --git a/tests/proj2/tests/store_oob2.wee.wasm b/tests/proj2/tests/store_oob2.wee.wasm Binary files differnew file mode 100644 index 0000000..45c7b03 --- /dev/null +++ b/tests/proj2/tests/store_oob2.wee.wasm diff --git a/tests/proj2/tests/sub0.runs b/tests/proj2/tests/sub0.runs new file mode 100644 index 0000000..dd17d1b --- /dev/null +++ b/tests/proj2/tests/sub0.runs @@ -0,0 +1,8 @@ +8 9 = -1 +33 44 = -11 +111 222 = -111 +2222 3333 = -1111 +111111111 666666666 = -555555555 +-2147483648 -2147483648 = 0 +-2129587951 -2093796557 = -35791394 +2000000000 1 = 1999999999 diff --git a/tests/proj2/tests/sub0.wasm b/tests/proj2/tests/sub0.wasm Binary files differnew file mode 100644 index 0000000..60d2e71 --- /dev/null +++ b/tests/proj2/tests/sub0.wasm diff --git a/tests/proj2/tests/sub0.wat b/tests/proj2/tests/sub0.wat new file mode 100644 index 0000000..0a6782a --- /dev/null +++ b/tests/proj2/tests/sub0.wat @@ -0,0 +1,5 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.sub (local.get 0) (local.get 1)) + ) +) diff --git a/tests/proj2/tests/sub0.wee.wasm b/tests/proj2/tests/sub0.wee.wasm Binary files differnew file mode 100644 index 0000000..579d572 --- /dev/null +++ b/tests/proj2/tests/sub0.wee.wasm diff --git a/tests/proj2/tests/vobj0.runs b/tests/proj2/tests/vobj0.runs new file mode 100644 index 0000000..307483b --- /dev/null +++ b/tests/proj2/tests/vobj0.runs @@ -0,0 +1,5 @@ +0 = 11 +1 = 12 +2 = 33 +3 = 44 +4 = -55555 diff --git a/tests/proj2/tests/vobj0.wasm b/tests/proj2/tests/vobj0.wasm Binary files differnew file mode 100644 index 0000000..4e23ccb --- /dev/null +++ b/tests/proj2/tests/vobj0.wasm diff --git a/tests/proj2/tests/vobj0.wat b/tests/proj2/tests/vobj0.wat new file mode 100644 index 0000000..d4dd1af --- /dev/null +++ b/tests/proj2/tests/vobj0.wat @@ -0,0 +1,15 @@ +(module + (type (;0;) (func (param i32) (result i32))) + (func (;0;) (type 0) (param i32) (result i32) + i32.const 65536 + local.get 0 + i32.const 4 + i32.mul + i32.const 8 + i32.add + i32.add + i32.load + i32.load offset=4) + (memory (;0;) 3 3) + (export "main" (func 0)) + (data (;0;) (i32.const 65536) "\13\00\00\00\05\00\00\00\1c\00\01\00$\00\01\00,\00\01\004\00\01\00<\00\01\00\00\00\00\00\0b\00\00\00\00\00\00\00\0c\00\00\00\00\00\00\00!\00\00\00\00\00\00\00,\00\00\00\00\00\00\00\fd&\ff\ff")) diff --git a/tests/proj2/tests/vobj0.wee.wasm b/tests/proj2/tests/vobj0.wee.wasm Binary files differnew file mode 100644 index 0000000..cb05182 --- /dev/null +++ b/tests/proj2/tests/vobj0.wee.wasm diff --git a/tests/proj3/grade.sh b/tests/proj3/grade.sh new file mode 100755 index 0000000..d720ffb --- /dev/null +++ b/tests/proj3/grade.sh @@ -0,0 +1,121 @@ +#!/bin/bash + +if [ $# = 0 ]; then + WEERUN='../../weerun' +else + WEERUN=$1 + shift +fi + +T=${OUT:=/tmp/$USER/cs17670/$STUDENT/proj2-test/} +mkdir -p $T + + +if [ ! -x "$WEERUN" ]; then + printf "##+weerun\n" + printf "##-fail, weerun not found: %s\n" $WEERUN + exit 1 +fi + +if [ $# = 0 ]; then + TESTS=$(ls tests/*.wee.wasm) +else + TESTS=$@ +fi + +# substitute for the "timeout" command on MacOS +function xtimeout { + timeout=$1 + shift + command=("$@") + ( + "${command[@]}" & + runnerpid=$! + trap -- '' SIGTERM + ( # killer job + sleep $timeout + if ps -p $runnerpid > /dev/null; then + echo "Timed out, killing" + kill -SIGKILL $runnerpid 2>/dev/null + fi + ) & + killerpid=$! + wait $runnerpid + kill -SIGKILL $killerpid + ) +} + +function run_one() { + echo $WEERUN $f $ARGS + xtimeout 5s $WEERUN $f $ARGS > $OUT 2>$ERR + # ignore case + diff --strip-trailing-cr -i $EXP $OUT > $DIFF + OK=$? + if [ ! -s $DIFF ]; then + # remove empty diffs + rm $DIFF + else + cat $DIFF + fi + + if [ $OK = 0 ]; then + return 0 + else + echo diff $EXP $OUT + printf "##-fail: $ARGS\n" + return 1 + fi + +} + +for f in $TESTS; do + # replace slashes with _ + t=${f//\//_} + # replace .wasm with .runs + runs=${f/%.wee.wasm/.runs} + + printf "##+%s\n" $t + + OUT=$T/$t.out + ERR=$T/$t.err + EXP=$T/$t.expect + DIFF=$T/$t.diff + + if [ -f $runs ]; then + # do multiple runs for this test + ok=1 + while IFS= read -r line + do + ARGS=$(echo $line | cut -d= -f1) + EXPECT=$(echo $line | cut -d= -f2) + echo $EXPECT > $EXP + + run_one + + if [ $? != 0 ]; then + ok=0 + break; + fi + done < $runs + if [ $ok = 1 ]; then + printf "##-ok\n" + fi + else + # do one run + e=${f/%.wee.wasm/.expect} + args=${f/%.wee.wasm/.args} + cp $e $EXP + + if [ -f $args ]; then + ARGS=$(cat $args) + else + ARGS="" + fi + + run_one + + if [ $? = 0 ]; then + printf "##-ok\n" + fi + fi +done diff --git a/tests/proj3/tests/array_get0.runs b/tests/proj3/tests/array_get0.runs new file mode 100644 index 0000000..8e9739c --- /dev/null +++ b/tests/proj3/tests/array_get0.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +3 = !trap +4 = 4 +5 = 4 +12 = 4 diff --git a/tests/proj3/tests/array_get0.wasm b/tests/proj3/tests/array_get0.wasm Binary files differnew file mode 100644 index 0000000..ce491b6 --- /dev/null +++ b/tests/proj3/tests/array_get0.wasm diff --git a/tests/proj3/tests/array_get0.wat b/tests/proj3/tests/array_get0.wat new file mode 100644 index 0000000..4d5f395 --- /dev/null +++ b/tests/proj3/tests/array_get0.wat @@ -0,0 +1,26 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $alloc (param i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0))) + (local.set 0 (i32.sub (local.get 0) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 0) (i32.const 0))) + ) + (local.get $obj) + ) + + (func $get (param externref i32) (result i32) + (call $u (call $g (local.get 0) (call $b (local.get 1)))) + ) + + (func (export "main") (param i32) (result i32) + (call $get (call $alloc (local.get 0)) (i32.const 4)) + ) +) diff --git a/tests/proj3/tests/array_get0.wee.wasm b/tests/proj3/tests/array_get0.wee.wasm Binary files differnew file mode 100644 index 0000000..69454ec --- /dev/null +++ b/tests/proj3/tests/array_get0.wee.wasm diff --git a/tests/proj3/tests/array_sparse0.runs b/tests/proj3/tests/array_sparse0.runs new file mode 100644 index 0000000..009157f --- /dev/null +++ b/tests/proj3/tests/array_sparse0.runs @@ -0,0 +1,9 @@ +0 = !trap +4 = 4 +5 = !trap +100004 = 4 +200004 = 4 +1000004 = 4 +10000004 = 4 +100000004 = 4 +100000009 = !trap diff --git a/tests/proj3/tests/array_sparse0.wasm b/tests/proj3/tests/array_sparse0.wasm Binary files differnew file mode 100644 index 0000000..bb18b5b --- /dev/null +++ b/tests/proj3/tests/array_sparse0.wasm diff --git a/tests/proj3/tests/array_sparse0.wat b/tests/proj3/tests/array_sparse0.wat new file mode 100644 index 0000000..233453e --- /dev/null +++ b/tests/proj3/tests/array_sparse0.wat @@ -0,0 +1,26 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $alloc (param i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0))) + (local.set 0 (i32.sub (local.get 0) (i32.const 100000))) + (br_if $l (i32.ge_s (local.get 0) (i32.const 0))) + ) + (local.get $obj) + ) + + (func $get (param externref i32) (result i32) + (call $u (call $g (local.get 0) (call $b (local.get 1)))) + ) + + (func (export "main") (param i32) (result i32) + (call $get (call $alloc (local.get 0)) (i32.const 4)) + ) +) diff --git a/tests/proj3/tests/array_sparse0.wee.wasm b/tests/proj3/tests/array_sparse0.wee.wasm Binary files differnew file mode 100644 index 0000000..bdb4e7e --- /dev/null +++ b/tests/proj3/tests/array_sparse0.wee.wasm diff --git a/tests/proj3/tests/array_sparse1.runs b/tests/proj3/tests/array_sparse1.runs new file mode 100644 index 0000000..b317a60 --- /dev/null +++ b/tests/proj3/tests/array_sparse1.runs @@ -0,0 +1,4 @@ +0 = !trap +1 = 4763899 +500 = 4763899 +2000 = 4763899 diff --git a/tests/proj3/tests/array_sparse1.wasm b/tests/proj3/tests/array_sparse1.wasm Binary files differnew file mode 100644 index 0000000..7a34517 --- /dev/null +++ b/tests/proj3/tests/array_sparse1.wasm diff --git a/tests/proj3/tests/array_sparse1.wat b/tests/proj3/tests/array_sparse1.wat new file mode 100644 index 0000000..7b17cb5 --- /dev/null +++ b/tests/proj3/tests/array_sparse1.wat @@ -0,0 +1,28 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $alloc (param i32) (result externref) + (local $obj externref) + (local $key externref) + (local.set $obj (call $n)) + (loop $l + (local.set $key (call $b (i32.mul (local.get 0) (i32.const 4763899)))) + (call $s (local.get $obj) (local.get $key) (local.get $key)) + (local.set 0 (i32.sub (local.get 0) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 0) (i32.const 0))) + ) + (local.get $obj) + ) + + (func $get (param externref i32) (result i32) + (call $u (call $g (local.get 0) (call $b (local.get 1)))) + ) + + (func (export "main") (param i32) (result i32) + (call $get (call $alloc (local.get 0)) (i32.const 4763899)) + ) +) diff --git a/tests/proj3/tests/array_sparse1.wee.wasm b/tests/proj3/tests/array_sparse1.wee.wasm Binary files differnew file mode 100644 index 0000000..2a521e4 --- /dev/null +++ b/tests/proj3/tests/array_sparse1.wee.wasm diff --git a/tests/proj3/tests/array_sum0.runs b/tests/proj3/tests/array_sum0.runs new file mode 100644 index 0000000..c7b8734 --- /dev/null +++ b/tests/proj3/tests/array_sum0.runs @@ -0,0 +1,8 @@ +0 = 0 +1 = 1 +2 = 3 +3 = 6 +4 = 10 +5 = 15 +25 = 325 +55 = 1540 diff --git a/tests/proj3/tests/array_sum0.wasm b/tests/proj3/tests/array_sum0.wasm Binary files differnew file mode 100644 index 0000000..3c5d426 --- /dev/null +++ b/tests/proj3/tests/array_sum0.wasm diff --git a/tests/proj3/tests/array_sum0.wat b/tests/proj3/tests/array_sum0.wat new file mode 100644 index 0000000..fb3759f --- /dev/null +++ b/tests/proj3/tests/array_sum0.wat @@ -0,0 +1,32 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $alloc (param i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (local.get 0))) + (local.set 0 (i32.sub (local.get 0) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 0) (i32.const 0))) + ) + (local.get $obj) + ) + + (func $sum (param externref i32) (result i32) + (local $s i32) + (loop $l + (local.set $s (i32.add (local.get $s) (call $u (call $g (local.get 0) (call $b (local.get 1)))))) + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 1) (i32.const 0))) + ) + (local.get $s) + ) + + (func (export "main") (param i32) (result i32) + (call $sum (call $alloc (local.get 0)) (local.get 0)) + ) +) diff --git a/tests/proj3/tests/array_sum0.wee.wasm b/tests/proj3/tests/array_sum0.wee.wasm Binary files differnew file mode 100644 index 0000000..93bdc7f --- /dev/null +++ b/tests/proj3/tests/array_sum0.wee.wasm diff --git a/tests/proj3/tests/array_sum1.runs b/tests/proj3/tests/array_sum1.runs new file mode 100644 index 0000000..87cba9b --- /dev/null +++ b/tests/proj3/tests/array_sum1.runs @@ -0,0 +1,8 @@ +0 = 11 +1 = 23 +2 = 36 +3 = 50 +4 = 65 +5 = 81 +25 = 611 +55 = 2156 diff --git a/tests/proj3/tests/array_sum1.wasm b/tests/proj3/tests/array_sum1.wasm Binary files differnew file mode 100644 index 0000000..0d1f815 --- /dev/null +++ b/tests/proj3/tests/array_sum1.wasm diff --git a/tests/proj3/tests/array_sum1.wat b/tests/proj3/tests/array_sum1.wat new file mode 100644 index 0000000..41885a0 --- /dev/null +++ b/tests/proj3/tests/array_sum1.wat @@ -0,0 +1,32 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $alloc (param i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (i32.add (local.get 0) (i32.const 11)))) + (local.set 0 (i32.sub (local.get 0) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 0) (i32.const 0))) + ) + (local.get $obj) + ) + + (func $sum (param externref i32) (result i32) + (local $s i32) + (loop $l + (local.set $s (i32.add (local.get $s) (call $u (call $g (local.get 0) (call $b (local.get 1)))))) + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br_if $l (i32.ge_s (local.get 1) (i32.const 0))) + ) + (local.get $s) + ) + + (func (export "main") (param i32) (result i32) + (call $sum (call $alloc (local.get 0)) (local.get 0)) + ) +) diff --git a/tests/proj3/tests/array_sum1.wee.wasm b/tests/proj3/tests/array_sum1.wee.wasm Binary files differnew file mode 100644 index 0000000..df55408 --- /dev/null +++ b/tests/proj3/tests/array_sum1.wee.wasm diff --git a/tests/proj3/tests/br0.expect b/tests/proj3/tests/br0.expect new file mode 100644 index 0000000..920a139 --- /dev/null +++ b/tests/proj3/tests/br0.expect @@ -0,0 +1 @@ +43 diff --git a/tests/proj3/tests/br0.wasm b/tests/proj3/tests/br0.wasm Binary files differnew file mode 100644 index 0000000..c71f1fb --- /dev/null +++ b/tests/proj3/tests/br0.wasm diff --git a/tests/proj3/tests/br0.wat b/tests/proj3/tests/br0.wat new file mode 100644 index 0000000..d4607f2 --- /dev/null +++ b/tests/proj3/tests/br0.wat @@ -0,0 +1,8 @@ +(module + (func (export "main") (result i32) + (block + (br 0) + ) + (i32.const 43) + ) +) diff --git a/tests/proj3/tests/br0.wee.wasm b/tests/proj3/tests/br0.wee.wasm Binary files differnew file mode 100644 index 0000000..83ec9f9 --- /dev/null +++ b/tests/proj3/tests/br0.wee.wasm diff --git a/tests/proj3/tests/br1.expect b/tests/proj3/tests/br1.expect new file mode 100644 index 0000000..abac1ea --- /dev/null +++ b/tests/proj3/tests/br1.expect @@ -0,0 +1 @@ +47 diff --git a/tests/proj3/tests/br1.wasm b/tests/proj3/tests/br1.wasm Binary files differnew file mode 100644 index 0000000..bb64ae0 --- /dev/null +++ b/tests/proj3/tests/br1.wasm diff --git a/tests/proj3/tests/br1.wat b/tests/proj3/tests/br1.wat new file mode 100644 index 0000000..0e6e1f6 --- /dev/null +++ b/tests/proj3/tests/br1.wat @@ -0,0 +1,6 @@ +(module + (func (export "main") (result i32) + (i32.const 47) + (br 0) + ) +) diff --git a/tests/proj3/tests/br1.wee.wasm b/tests/proj3/tests/br1.wee.wasm Binary files differnew file mode 100644 index 0000000..75de416 --- /dev/null +++ b/tests/proj3/tests/br1.wee.wasm diff --git a/tests/proj3/tests/br2.expect b/tests/proj3/tests/br2.expect new file mode 100644 index 0000000..95f9650 --- /dev/null +++ b/tests/proj3/tests/br2.expect @@ -0,0 +1 @@ +49 diff --git a/tests/proj3/tests/br2.wasm b/tests/proj3/tests/br2.wasm Binary files differnew file mode 100644 index 0000000..49568d1 --- /dev/null +++ b/tests/proj3/tests/br2.wasm diff --git a/tests/proj3/tests/br2.wat b/tests/proj3/tests/br2.wat new file mode 100644 index 0000000..05c1ad8 --- /dev/null +++ b/tests/proj3/tests/br2.wat @@ -0,0 +1,9 @@ +(module + (func (export "main") (result i32) + (block + (i32.const 49) + (br 1) + drop) + (i32.const 67) + ) +) diff --git a/tests/proj3/tests/br2.wee.wasm b/tests/proj3/tests/br2.wee.wasm Binary files differnew file mode 100644 index 0000000..cd769c4 --- /dev/null +++ b/tests/proj3/tests/br2.wee.wasm diff --git a/tests/proj3/tests/br3.expect b/tests/proj3/tests/br3.expect new file mode 100644 index 0000000..59343b0 --- /dev/null +++ b/tests/proj3/tests/br3.expect @@ -0,0 +1 @@ +53 diff --git a/tests/proj3/tests/br3.wasm b/tests/proj3/tests/br3.wasm Binary files differnew file mode 100644 index 0000000..22be754 --- /dev/null +++ b/tests/proj3/tests/br3.wasm diff --git a/tests/proj3/tests/br3.wat b/tests/proj3/tests/br3.wat new file mode 100644 index 0000000..b5872ab --- /dev/null +++ b/tests/proj3/tests/br3.wat @@ -0,0 +1,11 @@ +(module + (func (export "main") (result i32) + (block + (block + (i32.const 53) + (br 2) + drop) + ) + (i32.const 67) + ) +) diff --git a/tests/proj3/tests/br3.wee.wasm b/tests/proj3/tests/br3.wee.wasm Binary files differnew file mode 100644 index 0000000..17ab547 --- /dev/null +++ b/tests/proj3/tests/br3.wee.wasm diff --git a/tests/proj3/tests/br_if0.runs b/tests/proj3/tests/br_if0.runs new file mode 100644 index 0000000..cf65396 --- /dev/null +++ b/tests/proj3/tests/br_if0.runs @@ -0,0 +1,3 @@ +0 = 57 +1 = 46 +87234 = 46 diff --git a/tests/proj3/tests/br_if0.wasm b/tests/proj3/tests/br_if0.wasm Binary files differnew file mode 100644 index 0000000..4e6e06a --- /dev/null +++ b/tests/proj3/tests/br_if0.wasm diff --git a/tests/proj3/tests/br_if0.wat b/tests/proj3/tests/br_if0.wat new file mode 100644 index 0000000..a07f636 --- /dev/null +++ b/tests/proj3/tests/br_if0.wat @@ -0,0 +1,8 @@ +(module + (func (export "main") (param i32) (result i32) + (i32.const 46) + (br_if 0 (local.get 0)) + (drop) + (i32.const 57) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/br_if0.wee.wasm b/tests/proj3/tests/br_if0.wee.wasm Binary files differnew file mode 100644 index 0000000..552356f --- /dev/null +++ b/tests/proj3/tests/br_if0.wee.wasm diff --git a/tests/proj3/tests/br_if1.runs b/tests/proj3/tests/br_if1.runs new file mode 100644 index 0000000..a47419c --- /dev/null +++ b/tests/proj3/tests/br_if1.runs @@ -0,0 +1,7 @@ +0 0 = 66 +1 0 = 44 +0 1 = 55 +-1 0 = 44 +0 -1 = 55 +98237 55 = 44 +0 982345 = 55 diff --git a/tests/proj3/tests/br_if1.wasm b/tests/proj3/tests/br_if1.wasm Binary files differnew file mode 100644 index 0000000..e1df9fa --- /dev/null +++ b/tests/proj3/tests/br_if1.wasm diff --git a/tests/proj3/tests/br_if1.wat b/tests/proj3/tests/br_if1.wat new file mode 100644 index 0000000..82d9c07 --- /dev/null +++ b/tests/proj3/tests/br_if1.wat @@ -0,0 +1,11 @@ +(module + (func (export "main") (param i32 i32) (result i32) + (i32.const 44) + (br_if 0 (local.get 0)) + (drop) + (i32.const 55) + (br_if 0 (local.get 1)) + (drop) + (i32.const 66) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/br_if1.wee.wasm b/tests/proj3/tests/br_if1.wee.wasm Binary files differnew file mode 100644 index 0000000..5db77d6 --- /dev/null +++ b/tests/proj3/tests/br_if1.wee.wasm diff --git a/tests/proj3/tests/br_if2.runs b/tests/proj3/tests/br_if2.runs new file mode 100644 index 0000000..581af19 --- /dev/null +++ b/tests/proj3/tests/br_if2.runs @@ -0,0 +1,8 @@ +0 0 0 = 44 +1 0 0 = 11 +0 1 0 = 22 +0 0 1 = 33 +1 0 0 = 11 +1 1 0 = 11 +1 1 1 = 11 +0 1 1 = 22 diff --git a/tests/proj3/tests/br_if2.wasm b/tests/proj3/tests/br_if2.wasm Binary files differnew file mode 100644 index 0000000..08e61b5 --- /dev/null +++ b/tests/proj3/tests/br_if2.wasm diff --git a/tests/proj3/tests/br_if2.wat b/tests/proj3/tests/br_if2.wat new file mode 100644 index 0000000..bd2d810 --- /dev/null +++ b/tests/proj3/tests/br_if2.wat @@ -0,0 +1,16 @@ +(module + (func (export "main") (param i32 i32 i32) (result i32) + (block + (i32.const 11) + (br_if 1 (local.get 0)) + (drop) + (i32.const 22) + (br_if 1 (local.get 1)) + (drop) + (i32.const 33) + (br_if 1 (local.get 2)) + (drop) + ) + (i32.const 44) + ) +) diff --git a/tests/proj3/tests/br_if2.wee.wasm b/tests/proj3/tests/br_if2.wee.wasm Binary files differnew file mode 100644 index 0000000..db48ae7 --- /dev/null +++ b/tests/proj3/tests/br_if2.wee.wasm diff --git a/tests/proj3/tests/br_table4.runs b/tests/proj3/tests/br_table4.runs new file mode 100644 index 0000000..9c5bf64 --- /dev/null +++ b/tests/proj3/tests/br_table4.runs @@ -0,0 +1,24 @@ +0 = 45 +1 = 46 +2 = 47 +3 = 48 +4 = 49 +5 = 56 +6 = 56 +7 = 49 +8 = 48 +9 = 47 +10 = 46 +11 = 45 +12 = 45 +13 = 45 +14 = 46 +15 = 46 +16 = 47 +17 = 47 +18 = 47 +19 = 47 +20 = 47 +21 = 47 +22 = 47 +23 = 47 diff --git a/tests/proj3/tests/br_table4.wasm b/tests/proj3/tests/br_table4.wasm Binary files differnew file mode 100644 index 0000000..5ed1ddf --- /dev/null +++ b/tests/proj3/tests/br_table4.wasm diff --git a/tests/proj3/tests/br_table4.wat b/tests/proj3/tests/br_table4.wat new file mode 100644 index 0000000..6b1d0b0 --- /dev/null +++ b/tests/proj3/tests/br_table4.wat @@ -0,0 +1,19 @@ +(module + (func (export "main") (param i32) (result i32) + (block + (block + (block + (block + (block + (block + (br_table 0 1 2 3 4 5 5 4 3 2 1 0 0 0 1 1 2 2 (local.get 0) + ) (return (i32.const 44)) + ) (return (i32.const 45)) + ) (return (i32.const 46)) + ) (return (i32.const 47)) + ) (return (i32.const 48)) + ) (return (i32.const 49)) + ) + (i32.const 56) + ) +) diff --git a/tests/proj3/tests/br_table4.wee.wasm b/tests/proj3/tests/br_table4.wee.wasm Binary files differnew file mode 100644 index 0000000..3357ef9 --- /dev/null +++ b/tests/proj3/tests/br_table4.wee.wasm diff --git a/tests/proj3/tests/build.sh b/tests/proj3/tests/build.sh new file mode 100755 index 0000000..a319aba --- /dev/null +++ b/tests/proj3/tests/build.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do + DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" +done +DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )" + +PROJ2=$(cd $DIR/.. && pwd) +WEEIFY=$PROJ2/weeify + +WAT2WASM=$(which wat2wasm) + +if [[ ! -x $WAT2WASM ]]; then + echo Error: wat2asm not found in PATH + exit 1 +fi + +if [[ ! -x $WEEIFY ]]; then + echo Error: weeify not found $DIR + exit 1 +fi + +if [ $# = 0 ]; then + FILES="*.wat" +else + FILES="$@" +fi + +for f in $FILES; do + wat2wasm $f + $WEEIFY -o ${f/%.wat/.wee.wasm} ${f/%.wat/.wasm} +done diff --git a/tests/proj3/tests/call_indirect0.runs b/tests/proj3/tests/call_indirect0.runs new file mode 100644 index 0000000..9b03289 --- /dev/null +++ b/tests/proj3/tests/call_indirect0.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect0.wasm b/tests/proj3/tests/call_indirect0.wasm Binary files differnew file mode 100644 index 0000000..e0383b1 --- /dev/null +++ b/tests/proj3/tests/call_indirect0.wasm diff --git a/tests/proj3/tests/call_indirect0.wat b/tests/proj3/tests/call_indirect0.wat new file mode 100644 index 0000000..5a08ddc --- /dev/null +++ b/tests/proj3/tests/call_indirect0.wat @@ -0,0 +1,10 @@ +(module + (table 5 funcref) + (type $v_r (func (result externref))) + + (func (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (local.get 0)) + (drop) + (i32.const 0) + ) +) diff --git a/tests/proj3/tests/call_indirect0.wee.wasm b/tests/proj3/tests/call_indirect0.wee.wasm Binary files differnew file mode 100644 index 0000000..f3ba3a1 --- /dev/null +++ b/tests/proj3/tests/call_indirect0.wee.wasm diff --git a/tests/proj3/tests/call_indirect1.runs b/tests/proj3/tests/call_indirect1.runs new file mode 100644 index 0000000..9b03289 --- /dev/null +++ b/tests/proj3/tests/call_indirect1.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect1.wasm b/tests/proj3/tests/call_indirect1.wasm Binary files differnew file mode 100644 index 0000000..449648d --- /dev/null +++ b/tests/proj3/tests/call_indirect1.wasm diff --git a/tests/proj3/tests/call_indirect1.wat b/tests/proj3/tests/call_indirect1.wat new file mode 100644 index 0000000..3e51c10 --- /dev/null +++ b/tests/proj3/tests/call_indirect1.wat @@ -0,0 +1,9 @@ +(module + (table funcref (elem $main)) + (type $v_r (func (result externref))) + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (local.get 0)) + (drop) + (i32.const 1) + ) +) diff --git a/tests/proj3/tests/call_indirect1.wee.wasm b/tests/proj3/tests/call_indirect1.wee.wasm Binary files differnew file mode 100644 index 0000000..cc7732e --- /dev/null +++ b/tests/proj3/tests/call_indirect1.wee.wasm diff --git a/tests/proj3/tests/call_indirect2.runs b/tests/proj3/tests/call_indirect2.runs new file mode 100644 index 0000000..62141a7 --- /dev/null +++ b/tests/proj3/tests/call_indirect2.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = 1888 +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect2.wasm b/tests/proj3/tests/call_indirect2.wasm Binary files differnew file mode 100644 index 0000000..e4abade --- /dev/null +++ b/tests/proj3/tests/call_indirect2.wasm diff --git a/tests/proj3/tests/call_indirect2.wat b/tests/proj3/tests/call_indirect2.wat new file mode 100644 index 0000000..e71c07f --- /dev/null +++ b/tests/proj3/tests/call_indirect2.wat @@ -0,0 +1,13 @@ +(module + (table funcref (elem $main $empty)) + (type $v_r (func (result externref))) + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (local.get 0)) + (drop) + (i32.const 1888) + ) + (func $empty (result externref) + (local $foo externref) + (local.get $foo) + ) +) diff --git a/tests/proj3/tests/call_indirect2.wee.wasm b/tests/proj3/tests/call_indirect2.wee.wasm Binary files differnew file mode 100644 index 0000000..3e13fcc --- /dev/null +++ b/tests/proj3/tests/call_indirect2.wee.wasm diff --git a/tests/proj3/tests/call_indirect3.runs b/tests/proj3/tests/call_indirect3.runs new file mode 100644 index 0000000..6c63a70 --- /dev/null +++ b/tests/proj3/tests/call_indirect3.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = -1877 +2 = -1877 +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect3.wasm b/tests/proj3/tests/call_indirect3.wasm Binary files differnew file mode 100644 index 0000000..54a094e --- /dev/null +++ b/tests/proj3/tests/call_indirect3.wasm diff --git a/tests/proj3/tests/call_indirect3.wat b/tests/proj3/tests/call_indirect3.wat new file mode 100644 index 0000000..6af5aba --- /dev/null +++ b/tests/proj3/tests/call_indirect3.wat @@ -0,0 +1,14 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + + (table funcref (elem $main $empty $n)) + (type $v_r (func (result externref))) + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (local.get 0)) + (drop) + (i32.const -1877) + ) + (func $empty (result externref) + (call $n) + ) +) diff --git a/tests/proj3/tests/call_indirect3.wee.wasm b/tests/proj3/tests/call_indirect3.wee.wasm Binary files differnew file mode 100644 index 0000000..0f5eb8e --- /dev/null +++ b/tests/proj3/tests/call_indirect3.wee.wasm diff --git a/tests/proj3/tests/call_indirect4.runs b/tests/proj3/tests/call_indirect4.runs new file mode 100644 index 0000000..9b03289 --- /dev/null +++ b/tests/proj3/tests/call_indirect4.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = !trap +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect4.wasm b/tests/proj3/tests/call_indirect4.wasm Binary files differnew file mode 100644 index 0000000..dcaf3cb --- /dev/null +++ b/tests/proj3/tests/call_indirect4.wasm diff --git a/tests/proj3/tests/call_indirect4.wat b/tests/proj3/tests/call_indirect4.wat new file mode 100644 index 0000000..32eea34 --- /dev/null +++ b/tests/proj3/tests/call_indirect4.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + + (table funcref (elem $main $empty)) + (type $v_r (func (result externref))) + + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (local.get 0)) + (drop) + (i32.const -1866) + ) + (func $empty (param externref) (result externref) + (call $n) + ) +) diff --git a/tests/proj3/tests/call_indirect4.wee.wasm b/tests/proj3/tests/call_indirect4.wee.wasm Binary files differnew file mode 100644 index 0000000..8062ec8 --- /dev/null +++ b/tests/proj3/tests/call_indirect4.wee.wasm diff --git a/tests/proj3/tests/call_indirect5.runs b/tests/proj3/tests/call_indirect5.runs new file mode 100644 index 0000000..828a780 --- /dev/null +++ b/tests/proj3/tests/call_indirect5.runs @@ -0,0 +1,7 @@ +0 = !trap +1 = -1865 +2 = !trap +4 = !trap +5 = !trap +6 = !trap +-1 = !trap diff --git a/tests/proj3/tests/call_indirect5.wasm b/tests/proj3/tests/call_indirect5.wasm Binary files differnew file mode 100644 index 0000000..db51d44 --- /dev/null +++ b/tests/proj3/tests/call_indirect5.wasm diff --git a/tests/proj3/tests/call_indirect5.wat b/tests/proj3/tests/call_indirect5.wat new file mode 100644 index 0000000..85d6510 --- /dev/null +++ b/tests/proj3/tests/call_indirect5.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + + (table funcref (elem $main $empty)) + (type $v_r (func (param externref) (result externref))) + + (func $main (export "main") (param i32) (result i32) + (call_indirect (type $v_r) (call $n) (local.get 0)) + (drop) + (i32.const -1865) + ) + (func $empty (param externref) (result externref) + (call $n) + ) +) diff --git a/tests/proj3/tests/call_indirect5.wee.wasm b/tests/proj3/tests/call_indirect5.wee.wasm Binary files differnew file mode 100644 index 0000000..5d7f07d --- /dev/null +++ b/tests/proj3/tests/call_indirect5.wee.wasm diff --git a/tests/proj3/tests/ec_puti0.expect b/tests/proj3/tests/ec_puti0.expect new file mode 100644 index 0000000..209cee3 --- /dev/null +++ b/tests/proj3/tests/ec_puti0.expect @@ -0,0 +1 @@ +4647 diff --git a/tests/proj3/tests/ec_puti0.wasm b/tests/proj3/tests/ec_puti0.wasm Binary files differnew file mode 100644 index 0000000..8c67c22 --- /dev/null +++ b/tests/proj3/tests/ec_puti0.wasm diff --git a/tests/proj3/tests/ec_puti0.wat b/tests/proj3/tests/ec_puti0.wat new file mode 100644 index 0000000..a42fc37 --- /dev/null +++ b/tests/proj3/tests/ec_puti0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "puti" (func $puti (param i32))) + (func (export "main") (result i32) + (call $puti (i32.const 46)) + (i32.const 47) + ) +) diff --git a/tests/proj3/tests/ec_puti0.wee.wasm b/tests/proj3/tests/ec_puti0.wee.wasm Binary files differnew file mode 100644 index 0000000..8b87e4b --- /dev/null +++ b/tests/proj3/tests/ec_puti0.wee.wasm diff --git a/tests/proj3/tests/ec_puti1.expect b/tests/proj3/tests/ec_puti1.expect new file mode 100644 index 0000000..f45c7ba --- /dev/null +++ b/tests/proj3/tests/ec_puti1.expect @@ -0,0 +1 @@ +46931111666 diff --git a/tests/proj3/tests/ec_puti1.wasm b/tests/proj3/tests/ec_puti1.wasm Binary files differnew file mode 100644 index 0000000..ec0001d --- /dev/null +++ b/tests/proj3/tests/ec_puti1.wasm diff --git a/tests/proj3/tests/ec_puti1.wat b/tests/proj3/tests/ec_puti1.wat new file mode 100644 index 0000000..a9288c2 --- /dev/null +++ b/tests/proj3/tests/ec_puti1.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "puti" (func $puti (param i32))) + (func (export "main") (result i32) + (call $puti (i32.const 46)) + (call $puti (i32.const 93)) + (call $puti (i32.const 1111)) + (i32.const 666) + ) +) diff --git a/tests/proj3/tests/ec_puti1.wee.wasm b/tests/proj3/tests/ec_puti1.wee.wasm Binary files differnew file mode 100644 index 0000000..84cbec1 --- /dev/null +++ b/tests/proj3/tests/ec_puti1.wee.wasm diff --git a/tests/proj3/tests/eq_null0.expect b/tests/proj3/tests/eq_null0.expect new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/proj3/tests/eq_null0.expect @@ -0,0 +1 @@ +0 diff --git a/tests/proj3/tests/eq_null0.wasm b/tests/proj3/tests/eq_null0.wasm Binary files differnew file mode 100644 index 0000000..68ee98d --- /dev/null +++ b/tests/proj3/tests/eq_null0.wasm diff --git a/tests/proj3/tests/eq_null0.wat b/tests/proj3/tests/eq_null0.wat new file mode 100644 index 0000000..7bc33c9 --- /dev/null +++ b/tests/proj3/tests/eq_null0.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func (export "main") (result i32) + (local $null externref) + (call $eq (local.get $null) (call $n)) + ) +) diff --git a/tests/proj3/tests/eq_null0.wee.wasm b/tests/proj3/tests/eq_null0.wee.wasm Binary files differnew file mode 100644 index 0000000..62ce3f2 --- /dev/null +++ b/tests/proj3/tests/eq_null0.wee.wasm diff --git a/tests/proj3/tests/eq_null1.expect b/tests/proj3/tests/eq_null1.expect new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/proj3/tests/eq_null1.expect @@ -0,0 +1 @@ +0 diff --git a/tests/proj3/tests/eq_null1.wasm b/tests/proj3/tests/eq_null1.wasm Binary files differnew file mode 100644 index 0000000..1f23dd2 --- /dev/null +++ b/tests/proj3/tests/eq_null1.wasm diff --git a/tests/proj3/tests/eq_null1.wat b/tests/proj3/tests/eq_null1.wat new file mode 100644 index 0000000..8c6b162 --- /dev/null +++ b/tests/proj3/tests/eq_null1.wat @@ -0,0 +1,8 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func (export "main") (result i32) + (call $eq (call $n) (call $n)) + ) +) diff --git a/tests/proj3/tests/eq_null1.wee.wasm b/tests/proj3/tests/eq_null1.wee.wasm Binary files differnew file mode 100644 index 0000000..e5e6683 --- /dev/null +++ b/tests/proj3/tests/eq_null1.wee.wasm diff --git a/tests/proj3/tests/eqn.expect b/tests/proj3/tests/eqn.expect new file mode 100644 index 0000000..ec63514 --- /dev/null +++ b/tests/proj3/tests/eqn.expect @@ -0,0 +1 @@ +9 diff --git a/tests/proj3/tests/eqn.wasm b/tests/proj3/tests/eqn.wasm Binary files differnew file mode 100644 index 0000000..a24fd58 --- /dev/null +++ b/tests/proj3/tests/eqn.wasm diff --git a/tests/proj3/tests/eqn.wat b/tests/proj3/tests/eqn.wat new file mode 100644 index 0000000..8bc199f --- /dev/null +++ b/tests/proj3/tests/eqn.wat @@ -0,0 +1,28 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $equal (param externref externref i32) (result i32) + (local.get 2) + (br_if 0 (call $eq (local.get 0) (local.get 1))) + (drop) + (i32.const 0) + ) + + (func (export "main") (result i32) + (local $o1 externref) + (local $o2 externref) + (local $o3 externref) + (local.set $o2 (call $n)) + (local.set $o3 (call $n)) + (i32.or + (i32.or + (i32.or + (call $equal (local.get 0) (local.get 0) (i32.const 1)) + (call $equal (local.get 0) (local.get 1) (i32.const 2))) + (i32.or + (call $equal (local.get 0) (local.get 2) (i32.const 4)) + (call $equal (local.get 1) (local.get 1) (i32.const 8)))) + (call $equal (local.get 1) (local.get 2) (i32.const 16))) + ) +) diff --git a/tests/proj3/tests/eqn.wee.wasm b/tests/proj3/tests/eqn.wee.wasm Binary files differnew file mode 100644 index 0000000..db4a331 --- /dev/null +++ b/tests/proj3/tests/eqn.wee.wasm diff --git a/tests/proj3/tests/eqn2.expect b/tests/proj3/tests/eqn2.expect new file mode 100644 index 0000000..7273c0f --- /dev/null +++ b/tests/proj3/tests/eqn2.expect @@ -0,0 +1 @@ +25 diff --git a/tests/proj3/tests/eqn2.wasm b/tests/proj3/tests/eqn2.wasm Binary files differnew file mode 100644 index 0000000..83ed0e7 --- /dev/null +++ b/tests/proj3/tests/eqn2.wasm diff --git a/tests/proj3/tests/eqn2.wat b/tests/proj3/tests/eqn2.wat new file mode 100644 index 0000000..9bb02ab --- /dev/null +++ b/tests/proj3/tests/eqn2.wat @@ -0,0 +1,28 @@ +(module + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + + (func $equal (param externref externref i32) (result i32) + (local.get 2) + (br_if 0 (call $eq (local.get 0) (local.get 1))) + (drop) + (i32.const 0) + ) + + (func (export "main") (result i32) + (local $o1 externref) + (local $o2 externref) + (local $o3 externref) + (local.set $o2 (call $b (i32.const 44))) + (local.set $o3 (call $b (i32.const 44))) + (i32.or + (i32.or + (i32.or + (call $equal (local.get 0) (local.get 0) (i32.const 1)) + (call $equal (local.get 0) (local.get 1) (i32.const 2))) + (i32.or + (call $equal (local.get 0) (local.get 2) (i32.const 4)) + (call $equal (local.get 1) (local.get 1) (i32.const 8)))) + (call $equal (local.get 1) (local.get 2) (i32.const 16))) + ) +) diff --git a/tests/proj3/tests/eqn2.wee.wasm b/tests/proj3/tests/eqn2.wee.wasm Binary files differnew file mode 100644 index 0000000..37cb551 --- /dev/null +++ b/tests/proj3/tests/eqn2.wee.wasm diff --git a/tests/proj3/tests/eqn3.expect b/tests/proj3/tests/eqn3.expect new file mode 100644 index 0000000..7273c0f --- /dev/null +++ b/tests/proj3/tests/eqn3.expect @@ -0,0 +1 @@ +25 diff --git a/tests/proj3/tests/eqn3.wasm b/tests/proj3/tests/eqn3.wasm Binary files differnew file mode 100644 index 0000000..f48ca5a --- /dev/null +++ b/tests/proj3/tests/eqn3.wasm diff --git a/tests/proj3/tests/eqn3.wat b/tests/proj3/tests/eqn3.wat new file mode 100644 index 0000000..5cab459 --- /dev/null +++ b/tests/proj3/tests/eqn3.wat @@ -0,0 +1,28 @@ +(module + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + + (func $equal (param externref externref i32) (result i32) + (local.get 2) + (br_if 0 (call $eq (local.get 0) (local.get 1))) + (drop) + (i32.const 0) + ) + + (func (export "main") (result i32) + (local $o1 externref) + (local $o2 externref) + (local $o3 externref) + (local.set $o2 (call $b (f64.const -44.55))) + (local.set $o3 (call $b (f64.const -44.55))) + (i32.or + (i32.or + (i32.or + (call $equal (local.get 0) (local.get 0) (i32.const 1)) + (call $equal (local.get 0) (local.get 1) (i32.const 2))) + (i32.or + (call $equal (local.get 0) (local.get 2) (i32.const 4)) + (call $equal (local.get 1) (local.get 1) (i32.const 8)))) + (call $equal (local.get 1) (local.get 2) (i32.const 16))) + ) +) diff --git a/tests/proj3/tests/eqn3.wee.wasm b/tests/proj3/tests/eqn3.wee.wasm Binary files differnew file mode 100644 index 0000000..5c3cda8 --- /dev/null +++ b/tests/proj3/tests/eqn3.wee.wasm diff --git a/tests/proj3/tests/f64.add0_d.runs b/tests/proj3/tests/f64.add0_d.runs new file mode 100644 index 0000000..51f77e8 --- /dev/null +++ b/tests/proj3/tests/f64.add0_d.runs @@ -0,0 +1,3 @@ +0d 1d = 1.000000 +0.25d -1.75d = -1.500000 +489728.83423d -782374.47d = -292645.635770 diff --git a/tests/proj3/tests/f64.add0_d.wasm b/tests/proj3/tests/f64.add0_d.wasm Binary files differnew file mode 100644 index 0000000..64225ec --- /dev/null +++ b/tests/proj3/tests/f64.add0_d.wasm diff --git a/tests/proj3/tests/f64.add0_d.wat b/tests/proj3/tests/f64.add0_d.wat new file mode 100644 index 0000000..39ccc28 --- /dev/null +++ b/tests/proj3/tests/f64.add0_d.wat @@ -0,0 +1,8 @@ +(module + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + + (func (export "main") (param f64 f64) (result f64) + (f64.add (call $u (call $b (local.get 0))) (call $u (call $b (local.get 1)))) + ) +) diff --git a/tests/proj3/tests/f64.add0_d.wee.wasm b/tests/proj3/tests/f64.add0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..c86930b --- /dev/null +++ b/tests/proj3/tests/f64.add0_d.wee.wasm diff --git a/tests/proj3/tests/f64.add1_d.runs b/tests/proj3/tests/f64.add1_d.runs new file mode 100644 index 0000000..51f77e8 --- /dev/null +++ b/tests/proj3/tests/f64.add1_d.runs @@ -0,0 +1,3 @@ +0d 1d = 1.000000 +0.25d -1.75d = -1.500000 +489728.83423d -782374.47d = -292645.635770 diff --git a/tests/proj3/tests/f64.add1_d.wasm b/tests/proj3/tests/f64.add1_d.wasm Binary files differnew file mode 100644 index 0000000..005a91b --- /dev/null +++ b/tests/proj3/tests/f64.add1_d.wasm diff --git a/tests/proj3/tests/f64.add1_d.wat b/tests/proj3/tests/f64.add1_d.wat new file mode 100644 index 0000000..b067e33 --- /dev/null +++ b/tests/proj3/tests/f64.add1_d.wat @@ -0,0 +1,8 @@ +(module + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + + (func (export "main") (param f64 f64) (result f64) + (f64.add (call $u (call $b (local.get 0))) (local.get 1)) + ) +) diff --git a/tests/proj3/tests/f64.add1_d.wee.wasm b/tests/proj3/tests/f64.add1_d.wee.wasm Binary files differnew file mode 100644 index 0000000..9f3a1c0 --- /dev/null +++ b/tests/proj3/tests/f64.add1_d.wee.wasm diff --git a/tests/proj3/tests/f64_box_unbox0_d.runs b/tests/proj3/tests/f64_box_unbox0_d.runs new file mode 100644 index 0000000..0110ba6 --- /dev/null +++ b/tests/proj3/tests/f64_box_unbox0_d.runs @@ -0,0 +1,2 @@ +0.000000d = 0.000000 +-44.25d = -44.250000 diff --git a/tests/proj3/tests/f64_box_unbox0_d.wasm b/tests/proj3/tests/f64_box_unbox0_d.wasm Binary files differnew file mode 100644 index 0000000..3ce66a5 --- /dev/null +++ b/tests/proj3/tests/f64_box_unbox0_d.wasm diff --git a/tests/proj3/tests/f64_box_unbox0_d.wat b/tests/proj3/tests/f64_box_unbox0_d.wat new file mode 100644 index 0000000..c9b1f60 --- /dev/null +++ b/tests/proj3/tests/f64_box_unbox0_d.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (func (export "main") (param f64) (result f64) + (call $u (call $b (local.get 0))) + ) +) diff --git a/tests/proj3/tests/f64_box_unbox0_d.wee.wasm b/tests/proj3/tests/f64_box_unbox0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..f6a93f2 --- /dev/null +++ b/tests/proj3/tests/f64_box_unbox0_d.wee.wasm diff --git a/tests/proj3/tests/f64_key0_d.runs b/tests/proj3/tests/f64_key0_d.runs new file mode 100644 index 0000000..9dcb868 --- /dev/null +++ b/tests/proj3/tests/f64_key0_d.runs @@ -0,0 +1,3 @@ +0d = 100.000000 +1.25d = 101.250000 +-99d = 1.000000 diff --git a/tests/proj3/tests/f64_key0_d.wasm b/tests/proj3/tests/f64_key0_d.wasm Binary files differnew file mode 100644 index 0000000..b0574ff --- /dev/null +++ b/tests/proj3/tests/f64_key0_d.wasm diff --git a/tests/proj3/tests/f64_key0_d.wat b/tests/proj3/tests/f64_key0_d.wat new file mode 100644 index 0000000..05192c2 --- /dev/null +++ b/tests/proj3/tests/f64_key0_d.wat @@ -0,0 +1,16 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + + (func (export "main") (param f64) (result f64) + (local $obj externref) + (local $k externref) + (local.set $obj (call $n)) + (local.set $k (call $b (local.get 0))) + (call $s (local.get $obj) (local.get $k) (call $b (f64.add (local.get 0) (f64.const 100)))) + (call $u (call $g (local.get $obj) (local.get $k))) + ) +) diff --git a/tests/proj3/tests/f64_key0_d.wee.wasm b/tests/proj3/tests/f64_key0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..ba641c6 --- /dev/null +++ b/tests/proj3/tests/f64_key0_d.wee.wasm diff --git a/tests/proj3/tests/f64_key1_d.runs b/tests/proj3/tests/f64_key1_d.runs new file mode 100644 index 0000000..9dcb868 --- /dev/null +++ b/tests/proj3/tests/f64_key1_d.runs @@ -0,0 +1,3 @@ +0d = 100.000000 +1.25d = 101.250000 +-99d = 1.000000 diff --git a/tests/proj3/tests/f64_key1_d.wasm b/tests/proj3/tests/f64_key1_d.wasm Binary files differnew file mode 100644 index 0000000..de9deb9 --- /dev/null +++ b/tests/proj3/tests/f64_key1_d.wasm diff --git a/tests/proj3/tests/f64_key1_d.wat b/tests/proj3/tests/f64_key1_d.wat new file mode 100644 index 0000000..8be55f3 --- /dev/null +++ b/tests/proj3/tests/f64_key1_d.wat @@ -0,0 +1,14 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + + (func (export "main") (param f64) (result f64) + (local $obj externref) + (local.set $obj (call $n)) + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100)))) + (call $u (call $g (local.get $obj) (call $b (local.get 0)))) + ) +) diff --git a/tests/proj3/tests/f64_key1_d.wee.wasm b/tests/proj3/tests/f64_key1_d.wee.wasm Binary files differnew file mode 100644 index 0000000..87adf92 --- /dev/null +++ b/tests/proj3/tests/f64_key1_d.wee.wasm diff --git a/tests/proj3/tests/f64_key2_d.runs b/tests/proj3/tests/f64_key2_d.runs new file mode 100644 index 0000000..c5d28c1 --- /dev/null +++ b/tests/proj3/tests/f64_key2_d.runs @@ -0,0 +1,3 @@ +0d = !trap +1.25d = !trap +-99d = !trap diff --git a/tests/proj3/tests/f64_key2_d.wasm b/tests/proj3/tests/f64_key2_d.wasm Binary files differnew file mode 100644 index 0000000..037e14f --- /dev/null +++ b/tests/proj3/tests/f64_key2_d.wasm diff --git a/tests/proj3/tests/f64_key2_d.wat b/tests/proj3/tests/f64_key2_d.wat new file mode 100644 index 0000000..106c2fb --- /dev/null +++ b/tests/proj3/tests/f64_key2_d.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + + (func (export "main") (param f64) (result f64) + (local $obj externref) + (local.set $obj (call $n)) + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100)))) + (call $u (call $g (local.get $obj) (call $bi (i32.trunc_f64_s (local.get 0))))) + ) +) diff --git a/tests/proj3/tests/f64_key2_d.wee.wasm b/tests/proj3/tests/f64_key2_d.wee.wasm Binary files differnew file mode 100644 index 0000000..0abd217 --- /dev/null +++ b/tests/proj3/tests/f64_key2_d.wee.wasm diff --git a/tests/proj3/tests/fib.runs b/tests/proj3/tests/fib.runs new file mode 100644 index 0000000..fba1687 --- /dev/null +++ b/tests/proj3/tests/fib.runs @@ -0,0 +1,9 @@ +0 = 1 +1 = 1 +2 = 2 +3 = 3 +4 = 5 +5 = 8 +6 = 13 +7 = 21 +8 = 34 diff --git a/tests/proj3/tests/fib.wasm b/tests/proj3/tests/fib.wasm Binary files differnew file mode 100644 index 0000000..e329719 --- /dev/null +++ b/tests/proj3/tests/fib.wasm diff --git a/tests/proj3/tests/fib.wat b/tests/proj3/tests/fib.wat new file mode 100644 index 0000000..920f2e5 --- /dev/null +++ b/tests/proj3/tests/fib.wat @@ -0,0 +1,29 @@ +(module + (export "main" (func $fib)) + (func $fib (param $n i32) (result i32) + (block + (br_if 0 (i32.ge_s + (local.get $n) + (i32.const 2) + )) + (return + (i32.const 1) + )) + (return + (i32.add + (call $fib + (i32.sub + (local.get $n) + (i32.const 2) + ) + ) + (call $fib + (i32.sub + (local.get $n) + (i32.const 1) + ) + ) + ) + ) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/fib.wee.wasm b/tests/proj3/tests/fib.wee.wasm Binary files differnew file mode 100644 index 0000000..23afd9e --- /dev/null +++ b/tests/proj3/tests/fib.wee.wasm diff --git a/tests/proj3/tests/i32_box_unbox0.runs b/tests/proj3/tests/i32_box_unbox0.runs new file mode 100644 index 0000000..cff4f69 --- /dev/null +++ b/tests/proj3/tests/i32_box_unbox0.runs @@ -0,0 +1,2 @@ +0 = 0 +457 = 457 diff --git a/tests/proj3/tests/i32_box_unbox0.wasm b/tests/proj3/tests/i32_box_unbox0.wasm Binary files differnew file mode 100644 index 0000000..50bbb27 --- /dev/null +++ b/tests/proj3/tests/i32_box_unbox0.wasm diff --git a/tests/proj3/tests/i32_box_unbox0.wat b/tests/proj3/tests/i32_box_unbox0.wat new file mode 100644 index 0000000..04ac19f --- /dev/null +++ b/tests/proj3/tests/i32_box_unbox0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (param i32) (result i32) + (call $u (call $b (local.get 0))) + ) +) diff --git a/tests/proj3/tests/i32_box_unbox0.wee.wasm b/tests/proj3/tests/i32_box_unbox0.wee.wasm Binary files differnew file mode 100644 index 0000000..0c92d6e --- /dev/null +++ b/tests/proj3/tests/i32_box_unbox0.wee.wasm diff --git a/tests/proj3/tests/junk0_d.runs b/tests/proj3/tests/junk0_d.runs new file mode 100644 index 0000000..cc8adb6 --- /dev/null +++ b/tests/proj3/tests/junk0_d.runs @@ -0,0 +1,3 @@ +0 = !trap +0.5d = 100.500000 +125.5d = 100.500000 diff --git a/tests/proj3/tests/junk0_d.wasm b/tests/proj3/tests/junk0_d.wasm Binary files differnew file mode 100644 index 0000000..45b5831 --- /dev/null +++ b/tests/proj3/tests/junk0_d.wasm diff --git a/tests/proj3/tests/junk0_d.wat b/tests/proj3/tests/junk0_d.wat new file mode 100644 index 0000000..fe0e25a --- /dev/null +++ b/tests/proj3/tests/junk0_d.wat @@ -0,0 +1,19 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + + (func (export "main") (param f64) (result f64) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100)))) + (local.set 0 (f64.sub (local.get 0) (f64.const 1.25))) + (br_if $l (f64.ge (local.get 0) (f64.const 0))) + ) + (call $u (call $g (local.get $obj) (call $b (f64.const 0.5)))) + ) +) diff --git a/tests/proj3/tests/junk0_d.wee.wasm b/tests/proj3/tests/junk0_d.wee.wasm Binary files differnew file mode 100644 index 0000000..f8bea66 --- /dev/null +++ b/tests/proj3/tests/junk0_d.wee.wasm diff --git a/tests/proj3/tests/junk1_d.runs b/tests/proj3/tests/junk1_d.runs new file mode 100644 index 0000000..cc8adb6 --- /dev/null +++ b/tests/proj3/tests/junk1_d.runs @@ -0,0 +1,3 @@ +0 = !trap +0.5d = 100.500000 +125.5d = 100.500000 diff --git a/tests/proj3/tests/junk1_d.wasm b/tests/proj3/tests/junk1_d.wasm Binary files differnew file mode 100644 index 0000000..27dfe06 --- /dev/null +++ b/tests/proj3/tests/junk1_d.wasm diff --git a/tests/proj3/tests/junk1_d.wat b/tests/proj3/tests/junk1_d.wat new file mode 100644 index 0000000..5ece7b6 --- /dev/null +++ b/tests/proj3/tests/junk1_d.wat @@ -0,0 +1,20 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + + (func (export "main") (param f64) (result f64) + (local $obj externref) + (local.set $obj (call $n)) + (loop $l + (call $s (local.get $obj) (call $b (local.get 0)) (call $b (f64.add (local.get 0) (f64.const 100)))) + (call $s (local.get $obj) (call $bi (i32.trunc_f64_s (local.get 0))) (call $b (local.get 0))) + (local.set 0 (f64.sub (local.get 0) (f64.const 1.25))) + (br_if $l (f64.ge (local.get 0) (f64.const 0))) + ) + (call $u (call $g (local.get $obj) (call $b (f64.const 0.5)))) + ) +) diff --git a/tests/proj3/tests/junk1_d.wee.wasm b/tests/proj3/tests/junk1_d.wee.wasm Binary files differnew file mode 100644 index 0000000..9f85f5a --- /dev/null +++ b/tests/proj3/tests/junk1_d.wee.wasm diff --git a/tests/proj3/tests/list0.runs b/tests/proj3/tests/list0.runs new file mode 100644 index 0000000..eab8be5 --- /dev/null +++ b/tests/proj3/tests/list0.runs @@ -0,0 +1,4 @@ +0 = 44 +1 = 55 +2 = -77 +3 = !trap diff --git a/tests/proj3/tests/list0.wasm b/tests/proj3/tests/list0.wasm Binary files differnew file mode 100644 index 0000000..4818b49 --- /dev/null +++ b/tests/proj3/tests/list0.wasm diff --git a/tests/proj3/tests/list0.wat b/tests/proj3/tests/list0.wat new file mode 100644 index 0000000..be2af6c --- /dev/null +++ b/tests/proj3/tests/list0.wat @@ -0,0 +1,44 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $cons (param i32 externref) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (call $s (local.get $obj) (call $b (i32.const 0)) (call $b (local.get 0))) + (call $s (local.get $obj) (call $b (i32.const 1)) (local.get 1)) + (local.get $obj) + ) + + (func $cdr (param externref) (result i32) + (call $u (call $g (local.get 0) (call $b (i32.const 0)))) + ) + + (func $car (param externref) (result externref) + (call $g (local.get 0) (call $b (i32.const 1))) + ) + + (func $get (param externref i32) (result i32) + (block $b + (loop $l + (br_if $b (i32.eqz (local.get 1))) + (local.set 0 (call $car (local.get 0))) + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br $l) + ) + ) + (call $cdr (local.get 0)) + ) + + + (func (export "main") (param i32) (result i32) + (local $null externref) + (call $get (call $cons (i32.const 44) + (call $cons (i32.const 55) + (call $cons (i32.const -77) (local.get $null)))) + (local.get 0)) + ) +) diff --git a/tests/proj3/tests/list0.wee.wasm b/tests/proj3/tests/list0.wee.wasm Binary files differnew file mode 100644 index 0000000..357a1e0 --- /dev/null +++ b/tests/proj3/tests/list0.wee.wasm diff --git a/tests/proj3/tests/list1.runs b/tests/proj3/tests/list1.runs new file mode 100644 index 0000000..cf1cbb0 --- /dev/null +++ b/tests/proj3/tests/list1.runs @@ -0,0 +1,7 @@ +1 0 = 33 +1 1 = !trap +5 4 = 165 +5 5 = !trap +199 165 = 5478 +245 165 = 5478 +9999 10000 = !trap diff --git a/tests/proj3/tests/list1.wasm b/tests/proj3/tests/list1.wasm Binary files differnew file mode 100644 index 0000000..17c7b2d --- /dev/null +++ b/tests/proj3/tests/list1.wasm diff --git a/tests/proj3/tests/list1.wat b/tests/proj3/tests/list1.wat new file mode 100644 index 0000000..476d712 --- /dev/null +++ b/tests/proj3/tests/list1.wat @@ -0,0 +1,55 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func $cons (param i32 externref) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (call $s (local.get $obj) (call $b (i32.const 0)) (call $b (local.get 0))) + (call $s (local.get $obj) (call $b (i32.const 1)) (local.get 1)) + (local.get $obj) + ) + + (func $cdr (param externref) (result i32) + (call $u (call $g (local.get 0) (call $b (i32.const 0)))) + ) + + (func $car (param externref) (result externref) + (call $g (local.get 0) (call $b (i32.const 1))) + ) + + (func $get (param externref i32) (result i32) + (block $b + (loop $l + (br_if $b (i32.eqz (local.get 1))) + (local.set 0 (call $car (local.get 0))) + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br $l) + ) + ) + (call $cdr (local.get 0)) + ) + + (func $alloc (param i32) (result externref) + (local $r externref) + (block $b + (loop $l + (br_if $b (i32.eqz (local.get 0))) + (local.set $r (call $cons (i32.mul (local.get 0) (i32.const 33)) (local.get $r))) + (local.set 0 (i32.sub (local.get 0) (i32.const 1))) + (br $l) + ) + ) + (local.get $r) + ) + + (func (export "main") (param i32 i32) (result i32) + (local $null externref) + (local $r externref) + (local.set $r (call $alloc (local.get 0))) + (call $get (local.get $r) (local.get 1)) + ) +) diff --git a/tests/proj3/tests/list1.wee.wasm b/tests/proj3/tests/list1.wee.wasm Binary files differnew file mode 100644 index 0000000..a1d1c38 --- /dev/null +++ b/tests/proj3/tests/list1.wee.wasm diff --git a/tests/proj3/tests/obj.eq0.expect b/tests/proj3/tests/obj.eq0.expect new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/proj3/tests/obj.eq0.expect @@ -0,0 +1 @@ +1 diff --git a/tests/proj3/tests/obj.eq0.wasm b/tests/proj3/tests/obj.eq0.wasm Binary files differnew file mode 100644 index 0000000..bdf1b40 --- /dev/null +++ b/tests/proj3/tests/obj.eq0.wasm diff --git a/tests/proj3/tests/obj.eq0.wat b/tests/proj3/tests/obj.eq0.wat new file mode 100644 index 0000000..e5c5a61 --- /dev/null +++ b/tests/proj3/tests/obj.eq0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32))) + (func (export "main") (result i32) + (local $f externref) + (call $f (local.get $f) (local.get $f)) + ) +) diff --git a/tests/proj3/tests/obj.eq0.wee.wasm b/tests/proj3/tests/obj.eq0.wee.wasm Binary files differnew file mode 100644 index 0000000..a70df87 --- /dev/null +++ b/tests/proj3/tests/obj.eq0.wee.wasm diff --git a/tests/proj3/tests/obj.eq1.runs b/tests/proj3/tests/obj.eq1.runs new file mode 100644 index 0000000..e8c6945 --- /dev/null +++ b/tests/proj3/tests/obj.eq1.runs @@ -0,0 +1,2 @@ +0 = 0 +-44 = 1 diff --git a/tests/proj3/tests/obj.eq1.wasm b/tests/proj3/tests/obj.eq1.wasm Binary files differnew file mode 100644 index 0000000..bb7e4ce --- /dev/null +++ b/tests/proj3/tests/obj.eq1.wasm diff --git a/tests/proj3/tests/obj.eq1.wat b/tests/proj3/tests/obj.eq1.wat new file mode 100644 index 0000000..d364007 --- /dev/null +++ b/tests/proj3/tests/obj.eq1.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32))) + (func (export "main") (param i32) (result i32) + (call $f (call $b (i32.const -44)) (call $b (local.get 0))) + ) +) diff --git a/tests/proj3/tests/obj.eq1.wee.wasm b/tests/proj3/tests/obj.eq1.wee.wasm Binary files differnew file mode 100644 index 0000000..6d43e9e --- /dev/null +++ b/tests/proj3/tests/obj.eq1.wee.wasm diff --git a/tests/proj3/tests/obj.eq2.runs b/tests/proj3/tests/obj.eq2.runs new file mode 100644 index 0000000..218d9ac --- /dev/null +++ b/tests/proj3/tests/obj.eq2.runs @@ -0,0 +1,3 @@ +0d = 0 +-44d = 0 +-49.25d = 1 diff --git a/tests/proj3/tests/obj.eq2.wasm b/tests/proj3/tests/obj.eq2.wasm Binary files differnew file mode 100644 index 0000000..cc6511d --- /dev/null +++ b/tests/proj3/tests/obj.eq2.wasm diff --git a/tests/proj3/tests/obj.eq2.wat b/tests/proj3/tests/obj.eq2.wat new file mode 100644 index 0000000..c0a931d --- /dev/null +++ b/tests/proj3/tests/obj.eq2.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.eq" (func $f (param externref externref) (result i32))) + (func (export "main") (param f64) (result i32) + (call $f (call $b (f64.const -49.25)) (call $b (local.get 0))) + ) +) diff --git a/tests/proj3/tests/obj.eq2.wee.wasm b/tests/proj3/tests/obj.eq2.wee.wasm Binary files differnew file mode 100644 index 0000000..9f964dc --- /dev/null +++ b/tests/proj3/tests/obj.eq2.wee.wasm diff --git a/tests/proj3/tests/obj.get0.expect b/tests/proj3/tests/obj.get0.expect new file mode 100644 index 0000000..1189174 --- /dev/null +++ b/tests/proj3/tests/obj.get0.expect @@ -0,0 +1 @@ +!trap diff --git a/tests/proj3/tests/obj.get0.wasm b/tests/proj3/tests/obj.get0.wasm Binary files differnew file mode 100644 index 0000000..5398ef9 --- /dev/null +++ b/tests/proj3/tests/obj.get0.wasm diff --git a/tests/proj3/tests/obj.get0.wat b/tests/proj3/tests/obj.get0.wat new file mode 100644 index 0000000..5ce1ec8 --- /dev/null +++ b/tests/proj3/tests/obj.get0.wat @@ -0,0 +1,8 @@ +(module + (import "weewasm" "obj.get" (func $f (param externref externref) (result externref))) + (func (export "main") (result i32) + (local $f externref) + (drop (call $f (local.get $f) (local.get $f))) + (i32.const 47) + ) +) diff --git a/tests/proj3/tests/obj.get0.wee.wasm b/tests/proj3/tests/obj.get0.wee.wasm Binary files differnew file mode 100644 index 0000000..3c07f8c --- /dev/null +++ b/tests/proj3/tests/obj.get0.wee.wasm diff --git a/tests/proj3/tests/obj.get1.expect b/tests/proj3/tests/obj.get1.expect new file mode 100644 index 0000000..1189174 --- /dev/null +++ b/tests/proj3/tests/obj.get1.expect @@ -0,0 +1 @@ +!trap diff --git a/tests/proj3/tests/obj.get1.wasm b/tests/proj3/tests/obj.get1.wasm Binary files differnew file mode 100644 index 0000000..a172efc --- /dev/null +++ b/tests/proj3/tests/obj.get1.wasm diff --git a/tests/proj3/tests/obj.get1.wat b/tests/proj3/tests/obj.get1.wat new file mode 100644 index 0000000..85e9278 --- /dev/null +++ b/tests/proj3/tests/obj.get1.wat @@ -0,0 +1,8 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (func (export "main") (result externref) + (local $f externref) + (call $g (call $n) (local.get $f)) + ) +) diff --git a/tests/proj3/tests/obj.get1.wee.wasm b/tests/proj3/tests/obj.get1.wee.wasm Binary files differnew file mode 100644 index 0000000..beb29be --- /dev/null +++ b/tests/proj3/tests/obj.get1.wee.wasm diff --git a/tests/proj3/tests/obj.getset0.runs b/tests/proj3/tests/obj.getset0.runs new file mode 100644 index 0000000..05f1f37 --- /dev/null +++ b/tests/proj3/tests/obj.getset0.runs @@ -0,0 +1,2 @@ +33 = 33 +-98234 = -98234 diff --git a/tests/proj3/tests/obj.getset0.wasm b/tests/proj3/tests/obj.getset0.wasm Binary files differnew file mode 100644 index 0000000..2d1b3ae --- /dev/null +++ b/tests/proj3/tests/obj.getset0.wasm diff --git a/tests/proj3/tests/obj.getset0.wat b/tests/proj3/tests/obj.getset0.wat new file mode 100644 index 0000000..caf8ba2 --- /dev/null +++ b/tests/proj3/tests/obj.getset0.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (param i32) (result i32) + (local $f externref) + (local $g externref) + (local.set $f (call $n)) + (local.set $g (call $n)) + (call $s (local.get $f) (local.get $g) (call $b (local.get 0))) + (call $u (call $g (local.get $f) (local.get $g))) + ) +) diff --git a/tests/proj3/tests/obj.getset0.wee.wasm b/tests/proj3/tests/obj.getset0.wee.wasm Binary files differnew file mode 100644 index 0000000..82397da --- /dev/null +++ b/tests/proj3/tests/obj.getset0.wee.wasm diff --git a/tests/proj3/tests/obj.getset1.runs b/tests/proj3/tests/obj.getset1.runs new file mode 100644 index 0000000..8ecf4b6 --- /dev/null +++ b/tests/proj3/tests/obj.getset1.runs @@ -0,0 +1,2 @@ +3344 = 3344 +-9823477 = -9823477 diff --git a/tests/proj3/tests/obj.getset1.wasm b/tests/proj3/tests/obj.getset1.wasm Binary files differnew file mode 100644 index 0000000..cf9756d --- /dev/null +++ b/tests/proj3/tests/obj.getset1.wasm diff --git a/tests/proj3/tests/obj.getset1.wat b/tests/proj3/tests/obj.getset1.wat new file mode 100644 index 0000000..1fa9a7f --- /dev/null +++ b/tests/proj3/tests/obj.getset1.wat @@ -0,0 +1,13 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (param i32) (result i32) + (local $f externref) + (local.set $f (call $n)) + (call $s (local.get $f) (call $b (i32.const 9999)) (call $b (local.get 0))) + (call $u (call $g (local.get $f) (call $b (i32.const 9999)))) + ) +) diff --git a/tests/proj3/tests/obj.getset1.wee.wasm b/tests/proj3/tests/obj.getset1.wee.wasm Binary files differnew file mode 100644 index 0000000..a05b7c9 --- /dev/null +++ b/tests/proj3/tests/obj.getset1.wee.wasm diff --git a/tests/proj3/tests/obj.getset2.expect b/tests/proj3/tests/obj.getset2.expect new file mode 100644 index 0000000..1189174 --- /dev/null +++ b/tests/proj3/tests/obj.getset2.expect @@ -0,0 +1 @@ +!trap diff --git a/tests/proj3/tests/obj.getset2.wasm b/tests/proj3/tests/obj.getset2.wasm Binary files differnew file mode 100644 index 0000000..b02155e --- /dev/null +++ b/tests/proj3/tests/obj.getset2.wasm diff --git a/tests/proj3/tests/obj.getset2.wat b/tests/proj3/tests/obj.getset2.wat new file mode 100644 index 0000000..b588472 --- /dev/null +++ b/tests/proj3/tests/obj.getset2.wat @@ -0,0 +1,16 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (result i32) + (local $f externref) + (local $g externref) + (local.set $f (call $n)) + (local.set $g (call $n)) + (call $s (local.get $g) (call $b (i32.const 222)) (call $b (i32.const 111))) + (call $s (local.get $f) (local.get $g) (call $b (i32.const 1234))) + (call $u (call $g (local.get $f) (call $n))) + ) +) diff --git a/tests/proj3/tests/obj.getset2.wee.wasm b/tests/proj3/tests/obj.getset2.wee.wasm Binary files differnew file mode 100644 index 0000000..5676f41 --- /dev/null +++ b/tests/proj3/tests/obj.getset2.wee.wasm diff --git a/tests/proj3/tests/obj.getset3_d.runs b/tests/proj3/tests/obj.getset3_d.runs new file mode 100644 index 0000000..9ed9cb5 --- /dev/null +++ b/tests/proj3/tests/obj.getset3_d.runs @@ -0,0 +1,2 @@ +0d = 0.000000 +-99.25d = -99.250000 diff --git a/tests/proj3/tests/obj.getset3_d.wasm b/tests/proj3/tests/obj.getset3_d.wasm Binary files differnew file mode 100644 index 0000000..bd3b0e7 --- /dev/null +++ b/tests/proj3/tests/obj.getset3_d.wasm diff --git a/tests/proj3/tests/obj.getset3_d.wat b/tests/proj3/tests/obj.getset3_d.wat new file mode 100644 index 0000000..29cdfec --- /dev/null +++ b/tests/proj3/tests/obj.getset3_d.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (func (export "main") (param f64) (result f64) + (local $f externref) + (local $g externref) + (local.set $f (call $n)) + (local.set $g (call $n)) + (call $s (local.get $f) (local.get $g) (call $b (local.get 0))) + (call $u (call $g (local.get $f) (local.get $g))) + ) +) diff --git a/tests/proj3/tests/obj.getset3_d.wee.wasm b/tests/proj3/tests/obj.getset3_d.wee.wasm Binary files differnew file mode 100644 index 0000000..eaa960e --- /dev/null +++ b/tests/proj3/tests/obj.getset3_d.wee.wasm diff --git a/tests/proj3/tests/obj.getset4_d.runs b/tests/proj3/tests/obj.getset4_d.runs new file mode 100644 index 0000000..29cbb58 --- /dev/null +++ b/tests/proj3/tests/obj.getset4_d.runs @@ -0,0 +1,3 @@ +0d = 0.000000 +-9.25d = -9.250000 +33.999d = 33.999000 diff --git a/tests/proj3/tests/obj.getset4_d.wasm b/tests/proj3/tests/obj.getset4_d.wasm Binary files differnew file mode 100644 index 0000000..0fbd798 --- /dev/null +++ b/tests/proj3/tests/obj.getset4_d.wasm diff --git a/tests/proj3/tests/obj.getset4_d.wat b/tests/proj3/tests/obj.getset4_d.wat new file mode 100644 index 0000000..42d3cd5 --- /dev/null +++ b/tests/proj3/tests/obj.getset4_d.wat @@ -0,0 +1,15 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "f64.unbox" (func $u (param externref) (result f64))) + (func (export "main") (param f64) (result f64) + (local $f externref) + (local $g externref) + (local.set $f (call $n)) + (local.set $g (call $b (f64.add (local.get 0) (f64.const 3.44)))) + (call $s (local.get $f) (local.get $g) (call $b (local.get 0))) + (call $u (call $g (local.get $f) (local.get $g))) + ) +) diff --git a/tests/proj3/tests/obj.getset4_d.wee.wasm b/tests/proj3/tests/obj.getset4_d.wee.wasm Binary files differnew file mode 100644 index 0000000..4ad85c8 --- /dev/null +++ b/tests/proj3/tests/obj.getset4_d.wee.wasm diff --git a/tests/proj3/tests/obj.getset5.runs b/tests/proj3/tests/obj.getset5.runs new file mode 100644 index 0000000..0a09d96 --- /dev/null +++ b/tests/proj3/tests/obj.getset5.runs @@ -0,0 +1,3 @@ +0d 0 = !trap +33d 33 = !trap +-77.77d 66 = !trap diff --git a/tests/proj3/tests/obj.getset5.wasm b/tests/proj3/tests/obj.getset5.wasm Binary files differnew file mode 100644 index 0000000..de45410 --- /dev/null +++ b/tests/proj3/tests/obj.getset5.wasm diff --git a/tests/proj3/tests/obj.getset5.wat b/tests/proj3/tests/obj.getset5.wat new file mode 100644 index 0000000..2c53307 --- /dev/null +++ b/tests/proj3/tests/obj.getset5.wat @@ -0,0 +1,14 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (param f64 i32) (result i32) + (local $f externref) + (local.set $f (call $n)) + (call $s (local.get $f) (call $b (local.get 0)) (call $bi (local.get 1))) + (call $u (call $g (local.get $f) (call $bi (local.get 1)))) + ) +) diff --git a/tests/proj3/tests/obj.getset5.wee.wasm b/tests/proj3/tests/obj.getset5.wee.wasm Binary files differnew file mode 100644 index 0000000..cf8c336 --- /dev/null +++ b/tests/proj3/tests/obj.getset5.wee.wasm diff --git a/tests/proj3/tests/obj.getset6.runs b/tests/proj3/tests/obj.getset6.runs new file mode 100644 index 0000000..1fc3983 --- /dev/null +++ b/tests/proj3/tests/obj.getset6.runs @@ -0,0 +1,4 @@ +0d 0 = 0 +33d 33 = 33 +-44667788d -44667788 = -44667788 +-77.77d 66 = !trap diff --git a/tests/proj3/tests/obj.getset6.wasm b/tests/proj3/tests/obj.getset6.wasm Binary files differnew file mode 100644 index 0000000..052675c --- /dev/null +++ b/tests/proj3/tests/obj.getset6.wasm diff --git a/tests/proj3/tests/obj.getset6.wat b/tests/proj3/tests/obj.getset6.wat new file mode 100644 index 0000000..9519cae --- /dev/null +++ b/tests/proj3/tests/obj.getset6.wat @@ -0,0 +1,14 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.box_i32" (func $bi (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (func (export "main") (param f64 i32) (result i32) + (local $f externref) + (local.set $f (call $n)) + (call $s (local.get $f) (call $b (local.get 0)) (call $bi (local.get 1))) + (call $u (call $g (local.get $f) (call $b (f64.convert_i32_s (local.get 1))))) + ) +) diff --git a/tests/proj3/tests/obj.getset6.wee.wasm b/tests/proj3/tests/obj.getset6.wee.wasm Binary files differnew file mode 100644 index 0000000..a01127b --- /dev/null +++ b/tests/proj3/tests/obj.getset6.wee.wasm diff --git a/tests/proj3/tests/obj.inflate0.expect b/tests/proj3/tests/obj.inflate0.expect new file mode 100644 index 0000000..bb95160 --- /dev/null +++ b/tests/proj3/tests/obj.inflate0.expect @@ -0,0 +1 @@ +33 diff --git a/tests/proj3/tests/obj.inflate0.wasm b/tests/proj3/tests/obj.inflate0.wasm Binary files differnew file mode 100644 index 0000000..bd1a300 --- /dev/null +++ b/tests/proj3/tests/obj.inflate0.wasm diff --git a/tests/proj3/tests/obj.inflate0.wat b/tests/proj3/tests/obj.inflate0.wat new file mode 100644 index 0000000..fa354ef --- /dev/null +++ b/tests/proj3/tests/obj.inflate0.wat @@ -0,0 +1,18 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + + (func (export "main") (result i32) + (local $obj externref) + (local.set $obj (call $n)) + (call $s (local.get $obj) (call $b (i32.const 0)) (local.get $obj)) + (call $s (local.get $obj) (call $b (i32.const 1)) (local.get $obj)) + (call $s (local.get $obj) (call $b (i32.const 2)) (local.get $obj)) + (call $s (local.get $obj) (call $b (i32.const 3)) (local.get $obj)) + (call $s (local.get $obj) (call $b (i32.const 4)) (local.get $obj)) + (call $s (local.get $obj) (call $b (i32.const 5)) (local.get $obj)) + (i32.const 33) + ) +) diff --git a/tests/proj3/tests/obj.inflate0.wee.wasm b/tests/proj3/tests/obj.inflate0.wee.wasm Binary files differnew file mode 100644 index 0000000..9c1ed47 --- /dev/null +++ b/tests/proj3/tests/obj.inflate0.wee.wasm diff --git a/tests/proj3/tests/obj.new0.expect b/tests/proj3/tests/obj.new0.expect new file mode 100644 index 0000000..c739b42 --- /dev/null +++ b/tests/proj3/tests/obj.new0.expect @@ -0,0 +1 @@ +44 diff --git a/tests/proj3/tests/obj.new0.wasm b/tests/proj3/tests/obj.new0.wasm Binary files differnew file mode 100644 index 0000000..0daa52a --- /dev/null +++ b/tests/proj3/tests/obj.new0.wasm diff --git a/tests/proj3/tests/obj.new0.wat b/tests/proj3/tests/obj.new0.wat new file mode 100644 index 0000000..10f05d7 --- /dev/null +++ b/tests/proj3/tests/obj.new0.wat @@ -0,0 +1,7 @@ +(module + (import "weewasm" "obj.new" (func $f (result externref))) + (func (export "main") (result i32) + (drop (call $f)) + (i32.const 44) + ) +) diff --git a/tests/proj3/tests/obj.new0.wee.wasm b/tests/proj3/tests/obj.new0.wee.wasm Binary files differnew file mode 100644 index 0000000..9dbdfd1 --- /dev/null +++ b/tests/proj3/tests/obj.new0.wee.wasm diff --git a/tests/proj3/tests/obj.set1.expect b/tests/proj3/tests/obj.set1.expect new file mode 100644 index 0000000..1189174 --- /dev/null +++ b/tests/proj3/tests/obj.set1.expect @@ -0,0 +1 @@ +!trap diff --git a/tests/proj3/tests/obj.set1.wasm b/tests/proj3/tests/obj.set1.wasm Binary files differnew file mode 100644 index 0000000..93a2e46 --- /dev/null +++ b/tests/proj3/tests/obj.set1.wasm diff --git a/tests/proj3/tests/obj.set1.wat b/tests/proj3/tests/obj.set1.wat new file mode 100644 index 0000000..7fd1cee --- /dev/null +++ b/tests/proj3/tests/obj.set1.wat @@ -0,0 +1,9 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (func (export "main") (result i32) + (local $f externref) + (call $s (call $n) (local.get $f) (local.get $f)) + (i32.const 55) + ) +) diff --git a/tests/proj3/tests/obj.set1.wee.wasm b/tests/proj3/tests/obj.set1.wee.wasm Binary files differnew file mode 100644 index 0000000..e492417 --- /dev/null +++ b/tests/proj3/tests/obj.set1.wee.wasm diff --git a/tests/proj3/tests/pick0.runs b/tests/proj3/tests/pick0.runs new file mode 100644 index 0000000..e9dc6ab --- /dev/null +++ b/tests/proj3/tests/pick0.runs @@ -0,0 +1,4 @@ +0 = 1 +1 = 0 +2 = 0 +3 = 0 diff --git a/tests/proj3/tests/pick0.wasm b/tests/proj3/tests/pick0.wasm Binary files differnew file mode 100644 index 0000000..496ea33 --- /dev/null +++ b/tests/proj3/tests/pick0.wasm diff --git a/tests/proj3/tests/pick0.wat b/tests/proj3/tests/pick0.wat new file mode 100644 index 0000000..2415f0d --- /dev/null +++ b/tests/proj3/tests/pick0.wat @@ -0,0 +1,27 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $get (param externref externref externref i32) (result externref) + (local.get 0) + (br_if 0 (i32.eq (local.get 3) (i32.const 0))) + (drop) + + (local.get 1) + (br_if 0 (i32.eq (local.get 3) (i32.const 1))) + (drop) + + (local.get 2) + ) + + (func (export "main") (param i32) (result i32) + (local $a externref) + (local $b externref) + (local $c externref) + (local.set $a (call $n)) + (local.set $b (call $n)) + (local.set $c (call $n)) + + (call $eq (call $get (local.get $a) (local.get $b) (local.get $c) (local.get 0)) (local.get $a)) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/pick0.wee.wasm b/tests/proj3/tests/pick0.wee.wasm Binary files differnew file mode 100644 index 0000000..61453b9 --- /dev/null +++ b/tests/proj3/tests/pick0.wee.wasm diff --git a/tests/proj3/tests/rec.runs b/tests/proj3/tests/rec.runs new file mode 100644 index 0000000..e4b0cf4 --- /dev/null +++ b/tests/proj3/tests/rec.runs @@ -0,0 +1 @@ +0 = 20 diff --git a/tests/proj3/tests/rec.wasm b/tests/proj3/tests/rec.wasm Binary files differnew file mode 100644 index 0000000..961f36a --- /dev/null +++ b/tests/proj3/tests/rec.wasm diff --git a/tests/proj3/tests/rec.wat b/tests/proj3/tests/rec.wat new file mode 100644 index 0000000..b6c0abe --- /dev/null +++ b/tests/proj3/tests/rec.wat @@ -0,0 +1,11 @@ +(module + (global $g (mut i32) (i32.const 20)) + (func $ref (export "main") (param i32) (result i32) + (global.get $g) + (br_if 0 (i32.le_s (local.get 0) (i32.const 0))) + (i32.const 1) + (i32.add) + (global.set $g) + (call $ref (i32.sub (local.get 0) (i32.const 1))) + ) +) diff --git a/tests/proj3/tests/rec.wee.wasm b/tests/proj3/tests/rec.wee.wasm Binary files differnew file mode 100644 index 0000000..116a9f9 --- /dev/null +++ b/tests/proj3/tests/rec.wee.wasm diff --git a/tests/proj3/tests/swap0.expect b/tests/proj3/tests/swap0.expect new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/tests/proj3/tests/swap0.expect @@ -0,0 +1 @@ +1 diff --git a/tests/proj3/tests/swap0.wasm b/tests/proj3/tests/swap0.wasm Binary files differnew file mode 100644 index 0000000..a3bd7e6 --- /dev/null +++ b/tests/proj3/tests/swap0.wasm diff --git a/tests/proj3/tests/swap0.wat b/tests/proj3/tests/swap0.wat new file mode 100644 index 0000000..0886f2f --- /dev/null +++ b/tests/proj3/tests/swap0.wat @@ -0,0 +1,17 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $swap (param externref externref) (result externref) + (local.get 1) + ) + + (func (export "main") (result i32) + (local $a externref) + (local $b externref) + (local.set $a (call $n)) + (local.set $b (call $n)) + + (call $eq (call $swap (local.get $a) (local.get $b)) (local.get $b)) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/swap0.wee.wasm b/tests/proj3/tests/swap0.wee.wasm Binary files differnew file mode 100644 index 0000000..ef8ee8d --- /dev/null +++ b/tests/proj3/tests/swap0.wee.wasm diff --git a/tests/proj3/tests/swap1.expect b/tests/proj3/tests/swap1.expect new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/proj3/tests/swap1.expect @@ -0,0 +1 @@ +0 diff --git a/tests/proj3/tests/swap1.wasm b/tests/proj3/tests/swap1.wasm Binary files differnew file mode 100644 index 0000000..a2bd1cc --- /dev/null +++ b/tests/proj3/tests/swap1.wasm diff --git a/tests/proj3/tests/swap1.wat b/tests/proj3/tests/swap1.wat new file mode 100644 index 0000000..dd6aabc --- /dev/null +++ b/tests/proj3/tests/swap1.wat @@ -0,0 +1,17 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $swap (param externref externref) (result externref) + (local.get 1) + ) + + (func (export "main") (result i32) + (local $a externref) + (local $b externref) + (local.set $a (call $n)) + (local.set $b (call $n)) + + (call $eq (call $swap (local.get $b) (local.get $a)) (local.get $b)) + ) +)
\ No newline at end of file diff --git a/tests/proj3/tests/swap1.wee.wasm b/tests/proj3/tests/swap1.wee.wasm Binary files differnew file mode 100644 index 0000000..eb34a08 --- /dev/null +++ b/tests/proj3/tests/swap1.wee.wasm diff --git a/tests/proj3/tests/tree0.runs b/tests/proj3/tests/tree0.runs new file mode 100644 index 0000000..e6d97be --- /dev/null +++ b/tests/proj3/tests/tree0.runs @@ -0,0 +1,6 @@ +0 = 1 +1 = 1 +2 = 2 +5 = 5 +10 = 10 +15 = 15 diff --git a/tests/proj3/tests/tree0.wasm b/tests/proj3/tests/tree0.wasm Binary files differnew file mode 100644 index 0000000..cbd9421 --- /dev/null +++ b/tests/proj3/tests/tree0.wasm diff --git a/tests/proj3/tests/tree0.wat b/tests/proj3/tests/tree0.wat new file mode 100644 index 0000000..d57f3e9 --- /dev/null +++ b/tests/proj3/tests/tree0.wat @@ -0,0 +1,67 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "i32.unbox" (func $u (param externref) (result i32))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $array_get (param externref i32) (result externref) + (call $g (local.get 0) (call $b (local.get 1))) + ) + + (func $array_set (param externref i32 externref) + (call $s (local.get 0) (call $b (local.get 1)) (local.get 2)) + ) + + (func $left_key (param externref) (result externref) + (call $array_get (local.get 0) (i32.const 11))) + + (func $right_key (param externref) (result externref) + (call $array_get (local.get 0) (i32.const 22))) + + (func $keys (result externref) + (local $r externref) + (local.set $r (call $n)) + (call $array_set (local.get $r) (i32.const 11) (call $n)) + (call $array_set (local.get $r) (i32.const 22) (call $n)) + (local.get $r) + ) + + (func $isnull (param externref) (result i32) + (local $n externref) + (call $eq (local.get $n) (local.get 0))) + + (func $alloc (param externref i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (block $l + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br_if $l (i32.le_s (local.get 1) (i32.const 0))) + (call $s (local.get $obj) (call $left_key (local.get 0)) (call $alloc (local.get 0) (local.get 1))) + (call $s (local.get $obj) (call $right_key (local.get 0)) (call $alloc (local.get 0) (local.get 1))) + ) + (local.get $obj) + ) + + (func $height (param externref externref) (result i32) + (local $h i32) + (block $b + (loop $l + (br_if $b (call $isnull (local.get 1))) + (local.set $h (i32.add (local.get $h) (i32.const 1))) + (local.set 1 (call $g (local.get 1) (call $left_key (local.get 0)))) + (br 0) + ) + ) + (local.get $h) + ) + + (func (export "main") (param i32) (result i32) + (local $k externref) + (local $t externref) + (local.set $k (call $keys)) + (local.set $t (call $alloc (local.get $k) (local.get 0))) + (call $height (local.get $k) (local.get $t)) + ) +) diff --git a/tests/proj3/tests/tree0.wee.wasm b/tests/proj3/tests/tree0.wee.wasm Binary files differnew file mode 100644 index 0000000..88cb0c2 --- /dev/null +++ b/tests/proj3/tests/tree0.wee.wasm diff --git a/tests/proj3/tests/tree1.runs b/tests/proj3/tests/tree1.runs new file mode 100644 index 0000000..e6d97be --- /dev/null +++ b/tests/proj3/tests/tree1.runs @@ -0,0 +1,6 @@ +0 = 1 +1 = 1 +2 = 2 +5 = 5 +10 = 10 +15 = 15 diff --git a/tests/proj3/tests/tree1.wasm b/tests/proj3/tests/tree1.wasm Binary files differnew file mode 100644 index 0000000..8509d92 --- /dev/null +++ b/tests/proj3/tests/tree1.wasm diff --git a/tests/proj3/tests/tree1.wat b/tests/proj3/tests/tree1.wat new file mode 100644 index 0000000..b7f087c --- /dev/null +++ b/tests/proj3/tests/tree1.wat @@ -0,0 +1,58 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_f64" (func $b (param f64) (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $left_key (result externref) + (call $b (f64.const 3.25))) + + (func $right_key (result externref) + (call $b (f64.const -6.5))) + + (func $keys (result externref) + (local $r externref) + (local.set $r (call $n)) + (call $s (local.get $r) (call $left_key) (call $n)) + (call $s (local.get $r) (call $right_key) (call $n)) + (local.get $r) + ) + + (func $isnull (param externref) (result i32) + (local $n externref) + (call $eq (local.get $n) (local.get 0))) + + (func $alloc (param externref i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (block $l + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br_if $l (i32.le_s (local.get 1) (i32.const 0))) + (call $s (local.get $obj) (call $left_key) (call $alloc (local.get 0) (local.get 1))) + (call $s (local.get $obj) (call $right_key) (call $alloc (local.get 0) (local.get 1))) + ) + (local.get $obj) + ) + + (func $height (param externref externref) (result i32) + (local $h i32) + (block $b + (loop $l + (br_if $b (call $isnull (local.get 1))) + (local.set $h (i32.add (local.get $h) (i32.const 1))) + (local.set 1 (call $g (local.get 1) (call $left_key))) + (br 0) + ) + ) + (local.get $h) + ) + + (func (export "main") (param i32) (result i32) + (local $k externref) + (local $t externref) + (local.set $k (call $keys)) + (local.set $t (call $alloc (local.get $k) (local.get 0))) + (call $height (local.get $k) (local.get $t)) + ) +) diff --git a/tests/proj3/tests/tree1.wee.wasm b/tests/proj3/tests/tree1.wee.wasm Binary files differnew file mode 100644 index 0000000..4a8968c --- /dev/null +++ b/tests/proj3/tests/tree1.wee.wasm diff --git a/tests/proj3/tests/tree2.runs b/tests/proj3/tests/tree2.runs new file mode 100644 index 0000000..e6d97be --- /dev/null +++ b/tests/proj3/tests/tree2.runs @@ -0,0 +1,6 @@ +0 = 1 +1 = 1 +2 = 2 +5 = 5 +10 = 10 +15 = 15 diff --git a/tests/proj3/tests/tree2.wasm b/tests/proj3/tests/tree2.wasm Binary files differnew file mode 100644 index 0000000..57aab2e --- /dev/null +++ b/tests/proj3/tests/tree2.wasm diff --git a/tests/proj3/tests/tree2.wat b/tests/proj3/tests/tree2.wat new file mode 100644 index 0000000..dc16e27 --- /dev/null +++ b/tests/proj3/tests/tree2.wat @@ -0,0 +1,58 @@ +(module + (import "weewasm" "obj.new" (func $n (result externref))) + (import "weewasm" "obj.box_i32" (func $b (param i32) (result externref))) + (import "weewasm" "obj.get" (func $g (param externref externref) (result externref))) + (import "weewasm" "obj.set" (func $s (param externref externref externref))) + (import "weewasm" "obj.eq" (func $eq (param externref externref) (result i32))) + + (func $left_key (result externref) + (call $b (i32.const 77665544))) + + (func $right_key (result externref) + (call $b (i32.const -99887766))) + + (func $keys (result externref) + (local $r externref) + (local.set $r (call $n)) + (call $s (local.get $r) (call $left_key) (call $n)) + (call $s (local.get $r) (call $right_key) (call $n)) + (local.get $r) + ) + + (func $isnull (param externref) (result i32) + (local $n externref) + (call $eq (local.get $n) (local.get 0))) + + (func $alloc (param externref i32) (result externref) + (local $obj externref) + (local.set $obj (call $n)) + (block $l + (local.set 1 (i32.sub (local.get 1) (i32.const 1))) + (br_if $l (i32.le_s (local.get 1) (i32.const 0))) + (call $s (local.get $obj) (call $left_key) (call $alloc (local.get 0) (local.get 1))) + (call $s (local.get $obj) (call $right_key) (call $alloc (local.get 0) (local.get 1))) + ) + (local.get $obj) + ) + + (func $height (param externref externref) (result i32) + (local $h i32) + (block $b + (loop $l + (br_if $b (call $isnull (local.get 1))) + (local.set $h (i32.add (local.get $h) (i32.const 1))) + (local.set 1 (call $g (local.get 1) (call $left_key))) + (br 0) + ) + ) + (local.get $h) + ) + + (func (export "main") (param i32) (result i32) + (local $k externref) + (local $t externref) + (local.set $k (call $keys)) + (local.set $t (call $alloc (local.get $k) (local.get 0))) + (call $height (local.get $k) (local.get $t)) + ) +) diff --git a/tests/proj3/tests/tree2.wee.wasm b/tests/proj3/tests/tree2.wee.wasm Binary files differnew file mode 100644 index 0000000..d9d7c57 --- /dev/null +++ b/tests/proj3/tests/tree2.wee.wasm @@ -0,0 +1,20 @@ +#pragma once +#include <stdint.h> + +typedef struct { + uint8_t *ip; +} VM; + +typedef struct { +} Chunk; + +typedef enum { + INTERPRET_OK, + INTERPRET_COMPILE_ERROR, + INTERPRET_RUNTIME_ERROR +} InterpretResult; + +void initVM(); +void freeVM(); +InterpretResult interpret(Chunk* chunk); + Binary files differdiff --git a/weeify.c b/weeify.c new file mode 100644 index 0000000..adf3b66 --- /dev/null +++ b/weeify.c @@ -0,0 +1,647 @@ +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <unistd.h> +#include <stddef.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "common.h" +#include "vm.h" +#include "test.h" +#include "weewasm.h" +#include "illegal.h" + +int weeify(int out_fd, const byte* start, const byte* end); + +// Parse arguments and {weeify()} a single file. +int main(int argc, char* argv[]) { + const char* in_path = NULL; + const char* out_path = NULL; + + // parse arguments + for (int i = 1; i < argc; i++) { + const char *arg = argv[i]; + if (strcmp(arg, "-trace") == 0) { + g_trace = 1; + continue; + } + if (strcmp(arg, "-o") == 0 && i < (argc - 1)) { + out_path = argv[++i]; + continue; + } + if (in_path != NULL) { + out_path = NULL; + break; + } + in_path = arg; + } + + // check both {in_path} and {out_path} are specified + if (in_path == NULL || out_path == NULL) { + printf("Usage: weeify [-trace] -o <out_file> <in_file>\n"); + return 1; + } + + // load input file and create output file + { + byte* start = NULL; + byte* end = NULL; + ssize_t r = load_file(in_path, &start, &end); + if (r < 0) { + ERR("failed to load: %s\n", in_path); + return 2; + } + TRACE("loaded %s: %ld bytes\n", in_path, r); + + int out_fd = open(out_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (out_fd < 0) { + ERR("failed to create: %s\n", out_path); + return 3; + } + weeify(out_fd, start, end); + close(out_fd); + unload_file(&start, &end); + return 0; + } +} + +// emits a single byte +void emit1(int out_fd, byte val) { + write(out_fd, &val, 1); +} + +// emits an unsigned LEB, not padded +void emit_u32leb(int out_fd, uint32_t val) { + off_t cur = lseek(out_fd, 0, SEEK_CUR); + TRACE(" cur=0x%llx: emit_u32leb = %u\n", (long long)cur, val); + do { + uint32_t next = val >> 7; + uint32_t v = val & 0x7F; + if (next != 0) v |= 0x80; + emit1(out_fd, v); + val = next; + } while (val != 0); +} + +// emits an unsigned LEB, padded to 4 bytes +void emit_u32leb4(int out_fd, uint32_t val) { + off_t cur = lseek(out_fd, 0, SEEK_CUR); + TRACE(" cur=0x%llx: emit_u32leb4 = %u\n", (long long)cur, val); + byte buf[4]; + buf[0] = 0x80 | (val & 0x7F); + buf[1] = 0x80 | ((val >> 7) & 0x7F); + buf[2] = 0x80 | ((val >> 14) & 0x7F); + buf[3] = ((val >> 21) & 0x7F); + write(out_fd, buf, 4); +} + +// emits an unsigned LEB, padded to 5 bytes +void emit_u32leb5(int out_fd, uint32_t val) { + off_t cur = lseek(out_fd, 0, SEEK_CUR); + TRACE(" cur=0x%llx: emit_u32leb5 = %u\n", (long long)cur, val); + byte buf[5]; + buf[0] = 0x80 | (val & 0x7F); + buf[1] = 0x80 | ((val >> 7) & 0x7F); + buf[2] = 0x80 | ((val >> 14) & 0x7F); + buf[3] = 0x80 | ((val >> 21) & 0x7F); + buf[4] = ((val >> 28) & 0x7F); + write(out_fd, buf, 5); +} + +// emits the bytes from {start ... buf->ptr} +void emit_from(int out_fd, const byte* start, buffer_t* buf) { + off_t cur = lseek(out_fd, 0, SEEK_CUR); + TRACE(" cur=0x%llx: emit_from: %d bytes\n", (long long)cur, (int)(buf->ptr - start)); + write(out_fd, start, (buf->ptr - start)); +} + +off_t emit_reserved_length(int out_fd) { + off_t before = lseek(out_fd, 0, SEEK_CUR); + TRACE(" cur=0x%llx: reserve 5 byte LEB for length\n", (long long)before); + emit_u32leb5(out_fd, 0); + return before; +} + +void emit_patched_length(int out_fd, off_t before) { + off_t cur = lseek(out_fd, 0, SEEK_CUR); + off_t diff = cur - before - 5; + TRACE(" cur=0x%llx: patch 5 byte LEB for length @ 0x%llx = %lld\n", (long long)cur, (long long)before, (long long)diff); + lseek(out_fd, before, SEEK_SET); + emit_u32leb5(out_fd, diff); + lseek(out_fd, cur, SEEK_SET); +} + +// Returns the string name of a section code. +const char* section_name(byte code) { + switch (code) { + case WASM_SECT_TYPE: return "type"; + case WASM_SECT_IMPORT: return "import"; + case WASM_SECT_FUNCTION: return "function"; + case WASM_SECT_TABLE: return "table"; + case WASM_SECT_MEMORY: return "memory"; + case WASM_SECT_GLOBAL: return "global"; + case WASM_SECT_EXPORT: return "export"; + case WASM_SECT_START: return "start"; + case WASM_SECT_ELEMENT: return "element"; + case WASM_SECT_CODE: return "code"; + case WASM_SECT_DATA: return "data"; + case 0: return "custom"; + default: + return "unknown"; + } +} + +#define WASM_TYPE_I32 -1 +#define WASM_TYPE_I64 -2 +#define WASM_TYPE_F32 -3 +#define WASM_TYPE_F64 -4 +#define WASM_TYPE_V128 -5 +#define WASM_TYPE_EXTERNREF -17 +#define WASM_TYPE_FUNCREF -16 + +// Returns the string name of a type code. +const char* type_name(uint32_t code) { + switch (code) { + case WASM_TYPE_I32: return "i32"; + case WASM_TYPE_I64: return "<!illegal i64>"; + case WASM_TYPE_F32: return "<!illegal f32>"; + case WASM_TYPE_F64: return "f64"; + case WASM_TYPE_V128: return "<!illegal v128>"; + case WASM_TYPE_EXTERNREF: return "externref"; + case WASM_TYPE_FUNCREF: return "funcref"; + default: return "<!unknown type>"; + } +} + +int transform_code_section(int out_fd, buffer_t* buf); +int transform_body(int out_fd, buffer_t* buf); + +// Transforms the wasm file in {start ... end} and outputs the bytes to {out_fd}. +int weeify(int out_fd, const byte* start, const byte* end) { + buffer_t onstack_buf = { + start, + start, + end + }; + buffer_t* buf = &onstack_buf; + ssize_t len = 0; + + //==== Check magic word ============================================= + uint32_t magic = decode_u32(buf->ptr, buf->end, &len); + TRACE("read_magic = 0x%08x\n", magic); + if (len != 4 || magic != WASM_MAGIC) { + ERR("invalid magic word, expected %x\n", WASM_MAGIC); + return -1; + } + buf->ptr += 4; + + //==== Check Wasm Version =========================================== + uint32_t version = decode_u32(buf->ptr, buf->end, &len); + TRACE("read_version = 0x%08x\n", version); + if (len != 4 || version != WASM_VERSION) { + ERR("invalid Wasm version, expected %x\n", WASM_VERSION); + return -2; + } + buf->ptr += 4; + + TRACE(" copy header\n"); + emit_from(out_fd, buf->start, buf); + + //==== Read Wasm sections =========================================== + while (buf->ptr < buf->end) { + const byte* section_start = buf->ptr; + + byte code = read_u8(buf); + uint32_t sectlen = read_u32leb(buf); + TRACE("read_section_code = 0x%02x (%s), %u bytes\n", code, section_name(code), sectlen); + const byte* section_end = buf->ptr + sectlen; + if (section_end > end) { + ERR("invalid: section length too large"); + return -4; + } + + if (code == WASM_SECT_CODE) { + // transform a code section + buffer_t code_buf = { // use a sub-buffer to avoid going OOB + section_start, + buf->ptr, + section_end + }; + int result = transform_code_section(out_fd, &code_buf); + if (result != 0) return result; + } else { + // not a code section; copy section verbatim + ptrdiff_t diff = (section_end - section_start); + TRACE(" copy %td byte section\n", diff); + write(out_fd, section_start, diff); + } + + buf->ptr = section_end; + + if (section_end == section_start) { + ERR("internal error: zero-length section"); + return -3; + } + } + off_t cur = lseek(out_fd, 0, SEEK_CUR); + TRACE("file size = %lld bytes\n", (long long)cur); + return 0; +} + +// Transforms a code section, padding branch instructions to be at least 4-byte LEBs. +int transform_code_section(int out_fd, buffer_t* buf) { + emit1(out_fd, WASM_SECT_CODE); + off_t before = emit_reserved_length(out_fd); + + uint32_t body_count = read_u32leb(buf); + emit_u32leb(out_fd, body_count); + for (uint32_t i = 0; i < body_count; i++) { + TRACE("transform body #%u\n", i); + const byte* body_start = buf->ptr; + uint32_t body_len = read_u32leb(buf); + buffer_t body_buf = { // use a sub-buffer to avoid going OOB + body_start, + buf->ptr, + buf->ptr + body_len + }; + + transform_body(out_fd, &body_buf); + buf->ptr = body_buf.end; + } + emit_patched_length(out_fd, before); + return 0; +} + +// Support for disassembling/transforming the bytecode +typedef struct { + const char* mnemonic; + int immkind; + int illegal; +} opcode_imm_t; + +#define IMM_NONE 0 +#define IMM_BLOCKT 1 +#define IMM_LABEL 2 +#define IMM_LABELS 3 +#define IMM_FUNC 4 +#define IMM_SIG_TABLE 5 +#define IMM_LOCAL 6 +#define IMM_GLOBAL 7 +#define IMM_TABLE 8 +#define IMM_MEMARG 9 +#define IMM_I32 10 +#define IMM_F64 11 +#define IMM_MEMORY 12 +#define IMM_TAG 13 +#define IMM_I64 14 +#define IMM_F32 15 +#define IMM_REFNULLT 16 +#define IMM_VALTS 17 + +opcode_imm_t opcode_imm_table[256] = { + [WASM_OP_UNREACHABLE] = {"unreachable" }, + [WASM_OP_NOP] = {"nop" }, + [WASM_OP_BLOCK] = {"block", IMM_BLOCKT }, + [WASM_OP_LOOP] = {"loop", IMM_BLOCKT }, + [WASM_OP_END] = {"end" }, + [WASM_OP_BR] = {"br", IMM_LABEL }, + [WASM_OP_BR_IF] = {"br_if", IMM_LABEL }, + [WASM_OP_BR_TABLE] = {"br_table", IMM_LABELS }, + [WASM_OP_RETURN] = {"return" }, + [WASM_OP_CALL] = {"call", IMM_FUNC }, + [WASM_OP_CALL_INDIRECT] = {"call_indirect", IMM_SIG_TABLE }, + [WASM_OP_DROP] = {"drop" }, + [WASM_OP_SELECT] = {"select" }, + [WASM_OP_LOCAL_GET] = {"local.get", IMM_LOCAL }, + [WASM_OP_LOCAL_SET] = {"local.set", IMM_LOCAL }, + [WASM_OP_LOCAL_TEE] = {"local.tee", IMM_LOCAL }, + [WASM_OP_GLOBAL_GET] = {"global.get", IMM_GLOBAL }, + [WASM_OP_GLOBAL_SET] = {"global.set", IMM_GLOBAL }, + [WASM_OP_TABLE_GET] = {"table.get", IMM_TABLE }, + [WASM_OP_TABLE_SET] = {"table.set", IMM_TABLE }, + [WASM_OP_I32_LOAD] = {"i32.load", IMM_MEMARG }, + [WASM_OP_F64_LOAD] = {"f64.load", IMM_MEMARG }, + [WASM_OP_I32_LOAD8_S] = {"i32.load8_s", IMM_MEMARG }, + [WASM_OP_I32_LOAD8_U] = {"i32.load8_u", IMM_MEMARG }, + [WASM_OP_I32_LOAD16_S] = {"i32.load16_s", IMM_MEMARG }, + [WASM_OP_I32_LOAD16_U] = {"i32.load16_u", IMM_MEMARG }, + [WASM_OP_I32_STORE] = {"i32.store", IMM_MEMARG }, + [WASM_OP_F64_STORE] = {"f64.store", IMM_MEMARG }, + [WASM_OP_I32_STORE8] = {"i32.store8", IMM_MEMARG }, + [WASM_OP_I32_STORE16] = {"i32.store16", IMM_MEMARG }, + [WASM_OP_I32_CONST] = {"i32.const", IMM_I32 }, + [WASM_OP_F64_CONST] = {"f64.const", IMM_F64 }, + [WASM_OP_I32_EQZ] = {"i32.eqz" }, + [WASM_OP_I32_EQ] = {"i32.eq" }, + [WASM_OP_I32_NE] = {"i32.ne" }, + [WASM_OP_I32_LT_S] = {"i32.lt_s" }, + [WASM_OP_I32_LT_U] = {"i32.lt_u" }, + [WASM_OP_I32_GT_S] = {"i32.gt_s" }, + [WASM_OP_I32_GT_U] = {"i32.gt_u" }, + [WASM_OP_I32_LE_S] = {"i32.le_s" }, + [WASM_OP_I32_LE_U] = {"i32.le_u" }, + [WASM_OP_I32_GE_S] = {"i32.ge_s" }, + [WASM_OP_I32_GE_U] = {"i32.ge_u" }, + [WASM_OP_F64_EQ] = {"f64.eq" }, + [WASM_OP_F64_NE] = {"f64.ne" }, + [WASM_OP_F64_LT] = {"f64.lt" }, + [WASM_OP_F64_GT] = {"f64.gt" }, + [WASM_OP_F64_LE] = {"f64.le" }, + [WASM_OP_F64_GE] = {"f64.ge" }, + [WASM_OP_I32_CLZ] = {"i32.clz" }, + [WASM_OP_I32_CTZ] = {"i32.ctz" }, + [WASM_OP_I32_POPCNT] = {"i32.popcnt" }, + [WASM_OP_I32_ADD] = {"i32.add" }, + [WASM_OP_I32_SUB] = {"i32.sub" }, + [WASM_OP_I32_MUL] = {"i32.mul" }, + [WASM_OP_I32_DIV_S] = {"i32.div_s" }, + [WASM_OP_I32_DIV_U] = {"i32.div_u" }, + [WASM_OP_I32_REM_S] = {"i32.rem_s" }, + [WASM_OP_I32_REM_U] = {"i32.rem_u" }, + [WASM_OP_I32_AND] = {"i32.and" }, + [WASM_OP_I32_OR] = {"i32.or" }, + [WASM_OP_I32_XOR] = {"i32.xor" }, + [WASM_OP_I32_SHL] = {"i32.shl" }, + [WASM_OP_I32_SHR_S] = {"i32.shr_s" }, + [WASM_OP_I32_SHR_U] = {"i32.shr_u" }, + [WASM_OP_I32_ROTL] = {"i32.rotl" }, + [WASM_OP_I32_ROTR] = {"i32.rotr" }, + [WASM_OP_F64_ADD] = {"f64.add" }, + [WASM_OP_F64_SUB] = {"f64.sub" }, + [WASM_OP_F64_MUL] = {"f64.mul" }, + [WASM_OP_F64_DIV] = {"f64.div" }, + [WASM_OP_I32_TRUNC_F64_S] = {"i32.trunc_f64_s" }, + [WASM_OP_I32_TRUNC_F64_U] = {"i32.trunc_f64_u" }, + [WASM_OP_F64_CONVERT_I32_S] = {"f64.convert_i32_s" }, + [WASM_OP_F64_CONVERT_I32_U] = {"f64.convert_i32_u" }, + [WASM_OP_F64_CONVERT_I64_S] = {"f64.convert_i64_s" }, + [WASM_OP_F64_CONVERT_I64_U] = {"f64.convert_i64_u" }, + [WASM_OP_I32_EXTEND8_S] = {"i32.extend8_s" }, + [WASM_OP_I32_EXTEND16_S] = {"i32.extend16_s" }, + // illegal bytecodes + [WASM_OP_IF] = {"if", IMM_BLOCKT, -1 }, + [WASM_OP_ELSE] = {"else", -1 }, + [WASM_OP_TRY] = {"try", IMM_BLOCKT, -1}, + [WASM_OP_CATCH] = {"catch", IMM_TAG, -1}, + [WASM_OP_THROW] = {"throw", IMM_TAG, -1}, + [WASM_OP_RETHROW] = {"rethrow", IMM_NONE, -1}, + [WASM_OP_RETURN_CALL] = {"return_call", IMM_FUNC, -1}, + [WASM_OP_RETURN_CALL_INDIRECT]= {"return_call_indirect", IMM_SIG_TABLE, -1}, + [WASM_OP_CALL_REF] = {"call_ref", IMM_NONE, -1}, + [WASM_OP_RETURN_CALL_REF] = {"return_call_ref", IMM_NONE, -1}, + [WASM_OP_DELEGATE] = {"delegate", IMM_NONE, -1}, + [WASM_OP_CATCH_ALL] = {"catch_all", IMM_NONE, -1}, + [WASM_OP_SELECT_T] = {"select", IMM_VALTS, -1}, + [WASM_OP_I64_LOAD] = {"i64.load", IMM_MEMARG, -1}, + [WASM_OP_F32_LOAD] = {"f32.load", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD8_S] = {"i64.load8_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD8_U] = {"i64.load8_u", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD16_S] = {"i64.load16_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD16_U] = {"i64.load16_u", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD32_S] = {"i64.load32_s", IMM_MEMARG, -1}, + [WASM_OP_I64_LOAD32_U] = {"i64.load32_u", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE] = {"i64.store", IMM_MEMARG, -1}, + [WASM_OP_F32_STORE] = {"f32.store", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE8] = {"i64.store8", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE16] = {"i64.store16", IMM_MEMARG, -1}, + [WASM_OP_I64_STORE32] = {"i64.store32", IMM_MEMARG, -1}, + [WASM_OP_MEMORY_SIZE] = {"memory.size", IMM_MEMORY, -1}, + [WASM_OP_MEMORY_GROW] = {"memory.grow", IMM_MEMORY, -1}, + [WASM_OP_I64_CONST] = {"i64.const", IMM_I64, -1}, + [WASM_OP_F32_CONST] = {"f32.const", IMM_F32, -1}, + [WASM_OP_I64_EQZ] = {"i64.eqz", IMM_NONE, -1}, + [WASM_OP_I64_EQ] = {"i64.eq", IMM_NONE, -1}, + [WASM_OP_I64_NE] = {"i64.ne", IMM_NONE, -1}, + [WASM_OP_I64_LT_S] = {"i64.lt_s", IMM_NONE, -1}, + [WASM_OP_I64_LT_U] = {"i64.lt_u", IMM_NONE, -1}, + [WASM_OP_I64_GT_S] = {"i64.gt_s", IMM_NONE, -1}, + [WASM_OP_I64_GT_U] = {"i64.gt_u", IMM_NONE, -1}, + [WASM_OP_I64_LE_S] = {"i64.le_s", IMM_NONE, -1}, + [WASM_OP_I64_LE_U] = {"i64.le_u", IMM_NONE, -1}, + [WASM_OP_I64_GE_S] = {"i64.ge_s", IMM_NONE, -1}, + [WASM_OP_I64_GE_U] = {"i64.ge_u", IMM_NONE, -1}, + [WASM_OP_F32_EQ] = {"f32.eq", IMM_NONE, -1}, + [WASM_OP_F32_NE] = {"f32.ne", IMM_NONE, -1}, + [WASM_OP_F32_LT] = {"f32.lt", IMM_NONE, -1}, + [WASM_OP_F32_GT] = {"f32.gt", IMM_NONE, -1}, + [WASM_OP_F32_LE] = {"f32.le", IMM_NONE, -1}, + [WASM_OP_F32_GE] = {"f32.ge", IMM_NONE, -1}, + [WASM_OP_I64_CLZ] = {"i64.clz", IMM_NONE, -1}, + [WASM_OP_I64_CTZ] = {"i64.ctz", IMM_NONE, -1}, + [WASM_OP_I64_POPCNT] = {"i64.popcnt", IMM_NONE, -1}, + [WASM_OP_I64_ADD] = {"i64.add", IMM_NONE, -1}, + [WASM_OP_I64_SUB] = {"i64.sub", IMM_NONE, -1}, + [WASM_OP_I64_MUL] = {"i64.mul", IMM_NONE, -1}, + [WASM_OP_I64_DIV_S] = {"i64.div_s", IMM_NONE, -1}, + [WASM_OP_I64_DIV_U] = {"i64.div_u", IMM_NONE, -1}, + [WASM_OP_I64_REM_S] = {"i64.rem_s", IMM_NONE, -1}, + [WASM_OP_I64_REM_U] = {"i64.rem_u", IMM_NONE, -1}, + [WASM_OP_I64_AND] = {"i64.and", IMM_NONE, -1}, + [WASM_OP_I64_OR] = {"i64.or", IMM_NONE, -1}, + [WASM_OP_I64_XOR] = {"i64.xor", IMM_NONE, -1}, + [WASM_OP_I64_SHL] = {"i64.shl", IMM_NONE, -1}, + [WASM_OP_I64_SHR_S] = {"i64.shr_s", IMM_NONE, -1}, + [WASM_OP_I64_SHR_U] = {"i64.shr_u", IMM_NONE, -1}, + [WASM_OP_I64_ROTL] = {"i64.rotl", IMM_NONE, -1}, + [WASM_OP_I64_ROTR] = {"i64.rotr", IMM_NONE, -1}, + [WASM_OP_F32_ABS] = {"f32.abs", IMM_NONE, -1}, + [WASM_OP_F32_NEG] = {"f32.neg", IMM_NONE, -1}, + [WASM_OP_F32_CEIL] = {"f32.ceil", IMM_NONE, -1}, + [WASM_OP_F32_FLOOR] = {"f32.floor", IMM_NONE, -1}, + [WASM_OP_F32_TRUNC] = {"f32.trunc", IMM_NONE, -1}, + [WASM_OP_F32_NEAREST] = {"f32.nearest", IMM_NONE, -1}, + [WASM_OP_F32_SQRT] = {"f32.sqrt", IMM_NONE, -1}, + [WASM_OP_F32_ADD] = {"f32.add", IMM_NONE, -1}, + [WASM_OP_F32_SUB] = {"f32.sub", IMM_NONE, -1}, + [WASM_OP_F32_MUL] = {"f32.mul", IMM_NONE, -1}, + [WASM_OP_F32_DIV] = {"f32.div", IMM_NONE, -1}, + [WASM_OP_F32_MIN] = {"f32.min", IMM_NONE, -1}, + [WASM_OP_F32_MAX] = {"f32.max", IMM_NONE, -1}, + [WASM_OP_F32_COPYSIGN] = {"f32.copysign", IMM_NONE, -1}, + [WASM_OP_F64_ABS] = {"f64.abs", IMM_NONE, -1}, + [WASM_OP_F64_NEG] = {"f64.neg", IMM_NONE, -1}, + [WASM_OP_F64_CEIL] = {"f64.ceil", IMM_NONE, -1}, + [WASM_OP_F64_FLOOR] = {"f64.floor", IMM_NONE, -1}, + [WASM_OP_F64_TRUNC] = {"f64.trunc", IMM_NONE, -1}, + [WASM_OP_F64_NEAREST] = {"f64.nearest", IMM_NONE, -1}, + [WASM_OP_F64_SQRT] = {"f64.sqrt", IMM_NONE, -1}, + [WASM_OP_F64_MIN] = {"f64.min", IMM_NONE, -1}, + [WASM_OP_F64_MAX] = {"f64.max", IMM_NONE, -1}, + [WASM_OP_F64_COPYSIGN] = {"f64.copysign", IMM_NONE, -1}, + [WASM_OP_I32_WRAP_I64] = {"i32.wrap_i64", IMM_NONE, -1}, + [WASM_OP_I32_TRUNC_F32_S] = {"i32.trunc_f32_s", IMM_NONE, -1}, + [WASM_OP_I32_TRUNC_F32_U] = {"i32.trunc_f32_u", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND_I32_S] = {"i64.extend_i32_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND_I32_U] = {"i64.extend_i32_u", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F32_S] = {"i64.trunc_f32_s", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F32_U] = {"i64.trunc_f32_u", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F64_S] = {"i64.trunc_f64_s", IMM_NONE, -1}, + [WASM_OP_I64_TRUNC_F64_U] = {"i64.trunc_f64_u", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I32_S] = {"f32.convert_i32_s", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I32_U] = {"f32.convert_i32_u", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I64_S] = {"f32.convert_i64_s", IMM_NONE, -1}, + [WASM_OP_F32_CONVERT_I64_U] = {"f32.convert_i64_u", IMM_NONE, -1}, + [WASM_OP_F32_DEMOTE_F64] = {"f32.demote_f64", IMM_NONE, -1}, + [WASM_OP_F64_PROMOTE_F32] = {"f64.promote_f32", IMM_NONE, -1}, + [WASM_OP_I32_REINTERPRET_F32] = {"i32.reinterpret_f32", IMM_NONE, -1}, + [WASM_OP_I64_REINTERPRET_F64] = {"i64.reinterpret_f64", IMM_NONE, -1}, + [WASM_OP_F32_REINTERPRET_I32] = {"f32.reinterpret_i32", IMM_NONE, -1}, + [WASM_OP_F64_REINTERPRET_I64] = {"f64.reinterpret_i64", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND8_S] = {"i64.extend8_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND16_S] = {"i64.extend16_s", IMM_NONE, -1}, + [WASM_OP_I64_EXTEND32_S] = {"i64.extend32_s", IMM_NONE, -1}, + [WASM_OP_REF_NULL] = {"ref.null", IMM_REFNULLT, -1}, + [WASM_OP_REF_IS_NULL] = {"ref.is_null", IMM_NONE, -1}, + [WASM_OP_REF_FUNC] = {"ref.func", IMM_FUNC, -1}, + [WASM_OP_REF_AS_NON_NULL] = {"ref.as_non_null", IMM_NONE, -1}, + [WASM_OP_BR_ON_NULL] = {"br_on_null", IMM_LABEL, -1}, + [WASM_OP_REF_EQ] = {"ref.eq", IMM_NONE, -1}, + [WASM_OP_BR_ON_NON_NULL] = {"br_on_non_null", IMM_LABEL, -1}, +}; + +int transform_bytecode(int out_fd, buffer_t* buf) { + TRACE(" "); + const byte* start = buf->ptr; + + byte code = read_u8(buf); + opcode_imm_t* entry = &opcode_imm_table[code]; + if (entry->mnemonic == NULL) { + ERR("<!illegal bytecode %02X>", code); + return -3; + } else if (entry->illegal) { + ERR("<!illegal %s>", entry->mnemonic); + return -4; + } else { + TRACE("%s", entry->mnemonic); + } + switch (entry->immkind) { + case IMM_LABEL: { + // expand to 4-byte LEB + uint32_t imm = read_u32leb(buf); + TRACE(" %u", imm); + emit1(out_fd, code); + emit_u32leb4(out_fd, imm); + return 0; + } + case IMM_LABELS: { + // expand to 4-byte LEBs + uint32_t count = read_u32leb(buf); + TRACE(" %u", count); + emit1(out_fd, code); + emit_u32leb4(out_fd, count); + for (uint32_t i = 0; i <= count && buf->ptr < buf->end; i++) { + uint32_t lbl = read_u32leb(buf); + emit_u32leb4(out_fd, lbl); + TRACE(" %u", lbl); + } + return 0; + } + case IMM_FUNC: // fallthru + case IMM_LOCAL: // fallthru + case IMM_GLOBAL: // fallthru + case IMM_MEMORY: // fallthru + case IMM_TAG: // fallthru + case IMM_REFNULLT: + case IMM_TABLE: { + uint32_t imm = read_u32leb(buf); + TRACE(" %u", imm); + break; + } + + case IMM_NONE: break; + case IMM_BLOCKT: { + int32_t imm = read_i32leb(buf); + if (imm != -64) { + ERR(" <!illegal blocktype %d>", imm); + return -5; + } + break; + } + case IMM_SIG_TABLE: { + uint32_t sig = read_u32leb(buf); + TRACE(" %d", sig); + uint32_t tbl = read_u32leb(buf); + if (tbl != 0) { + ERR(" <!illegal table %d>", tbl);\ + return -2; + } + break; + } + case IMM_MEMARG: { + byte b = read_u8(buf); + uint32_t offset = read_u32leb(buf); + TRACE(" %u", offset); + break; + } + case IMM_I32: { + int32_t imm = read_i32leb(buf); + TRACE(" %d", imm); + break; + } + case IMM_F64: { + if (buf->end - buf->ptr >= 8) { + uint64_t val = *((uint64_t*)buf->ptr); + TRACE(" %016" PRIx64, val); + buf->ptr += 8; + } else { + ERR(" <!invalid f64>"); + return -6; + } + break; + } + case IMM_I64: { + ssize_t leblen = 0; + if (buf->ptr >= buf->end) break; + int64_t imm = decode_i64leb(buf->ptr, buf->end, &leblen); + if (leblen <= 0) buf->ptr = buf->end; // force failure + else buf->ptr += leblen; + TRACE(" %" PRId64 "", imm); + break; + } + case IMM_F32: { + for (int i = 0; i < 4; i++) { + byte b = read_u8(buf); + TRACE(" %02X", b); + } + break; + } + case IMM_VALTS: { + int32_t tcode = read_i32leb(buf); + TRACE(" %s", type_name(tcode)); + break; + } + default: break; + } + TRACE("\n"); + // emit the bytes as-is + emit_from(out_fd, start, buf); + return 0; +} + +int transform_body(int out_fd, buffer_t* buf) { + off_t before = emit_reserved_length(out_fd); + + const byte* start = buf->ptr; + uint32_t cnt = read_u32leb(buf); + TRACE(" locals %d\n", cnt); + for (uint32_t i = 0; i < cnt; i++) { + uint32_t cnt = read_u32leb(buf); + TRACE(" %u", cnt); + int32_t type = read_i32leb(buf); + TRACE(" %s\n", type_name(type)); + } + emit_from(out_fd, start, buf); + // disassemble code + while (buf->ptr < buf->end) { + int result = transform_bytecode(out_fd, buf); + if (result != 0) return result; + } + + emit_patched_length(out_fd, before); + return 0; +} diff --git a/weerun.c b/weerun.c new file mode 100644 index 0000000..32b1ff0 --- /dev/null +++ b/weerun.c @@ -0,0 +1,68 @@ +#include <inttypes.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "common.h" +#include "ir.h" +#include "weewasm.h" + +// Initialize the runtime functions. +void init_runtime(); +void init_libc_runtime(); + +// Disassembles? and runs a wasm module. +wasm_typed_value_t run(const byte* start, + const byte* end, + uint32_t num_args, + wasm_value_t* args); + +// Main function. +// Parses arguments and either runs the tests or runs a file with arguments. +// -trace: enable tracing to stderr +// -test: run internal tests +int main(int argc, char* argv[]) { + for (int i = 1; i < argc; i++) { + char* arg = argv[i]; + if (strcmp(arg, "-trace") == 0) { + g_trace = 1; + continue; + } + if (strcmp(arg, "-disassemble") == 0) { + g_disassemble = 1; + continue; + } + + byte* start = NULL; + byte* end = NULL; + ssize_t r = load_file(arg, &start, &end); + if (r >= 0) { + TRACE("loaded %s: %ld bytes\n", arg, r); + int num_args = argc - i - 1; + wasm_value_t* args = NULL; + if (num_args > 0) { + args = (wasm_value_t*)malloc(sizeof(wasm_value_t) * num_args); + for (int j = i + 1; j < argc; j++) { + int a = j - i - 1; + args[a] = parse_wasm_value(argv[j]); + TRACE("args[%d] = ", a); + // trace_wasm_value(args[a]); + TRACE("\n"); + } + } + init_runtime(); + init_libc_runtime(); + wasm_typed_value_t result = run(start, end, num_args, args); + unload_file(&start, &end); + print_wasm_value(result); + printf("\n"); + exit(0); + return 0; + } else { + ERR("failed to load: %s\n", arg); + return 1; + } + } + return 0; +} diff --git a/weerun.hpp b/weerun.hpp new file mode 100644 index 0000000..e9f0ed3 --- /dev/null +++ b/weerun.hpp @@ -0,0 +1,255 @@ +#pragma once + +#include <assert.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <iostream> +#include <map> +#include <memory> +#include <string> +#include <unordered_map> +#include <vector> + +extern "C" { +#include "common.h" +#include "ir.h" +#include "weewasm.h" +} + +#define WASM_TYPE_FUNCTION 0x60 +#define WASM_TYPE_I32 0x7F +#define WASM_TYPE_I64 0x7E +#define WASM_TYPE_F64 0x7C +#define WASM_TYPE_FUNCREF 0x70 +#define WASM_TYPE_EXTERNREF 0x6F + +struct wasm_func_decl_t { + std::vector<uint8_t> args_; + std::vector<uint8_t> ret_; +}; + +struct wasm_table_decl_t { + uint8_t type_; + byte has_max_; + uint32_t init_; + uint32_t max_; +}; + +struct wasm_memory_decl_t { + byte has_max_; + uint32_t init_; + uint32_t max_; +}; + +struct wasm_global_decl_t { + uint8_t type_; + byte is_mut_; +}; + +struct wasm_import_decl_t { + enum class type { FUNCTION = 0x0, TABLE = 0x1, MEMORY = 0x2, GLOBAL = 0x3 }; + + type type_; + std::string module_; + std::string name_; + union { + uint32_t funcindex_; + wasm_table_decl_t table_; + wasm_memory_decl_t memory_; + wasm_global_decl_t global_; + }; +}; + +struct wasm_global_t { + wasm_global_decl_t type_; + union { + uint32_t i32; + double f64; + void* ref; + } val_; +}; + +struct wasm_export_t { + std::string name_; + uint32_t type_; + uint32_t idx_; +}; + +struct wasm_elem_decl_t { + int32_t offset_; + std::vector<uint32_t> funcidx_; +}; + +struct wasm_local_decl_t { + uint32_t count_; + uint32_t type_; +}; + +struct wasm_code_decl_t { + uint32_t size_; + std::vector<wasm_local_decl_t> locals_; + std::vector<byte> code_; +}; + +struct wasm_data_decl_t { + uint32_t offset_; + std::vector<byte> data_; +}; + +struct wasm_instance_t; + +struct wasm_func_t { + wasm_func_decl_t* sig_; + uint32_t typeid_; + std::vector<wasm_local_decl_t> locals_; + std::vector<byte> code_; + + // run imported function in interperter + void (*run_)(wasm_instance_t* ins); + // run imported function in JIT + void* run_jit_; +}; + +struct wasm_module_t { + wasm_memory_decl_t mem_limits_; + wasm_table_decl_t table_; + uint32_t num_import_funcs_; + uint32_t main_index_; + bool have_start_; + uint32_t start_index_; + std::vector<wasm_func_decl_t> sigs_; + std::vector<wasm_func_t> funcs_; + std::vector<wasm_global_t> globals_; + std::vector<wasm_data_decl_t> datas_; + std::vector<wasm_elem_decl_t> elems_; + + wasm_instance_t* create_instance(); +}; + +const uint32_t wasm_page_size = 65536; + +struct wasm_stack_frame_t { + buffer_t pc_; + wasm_func_t* f_; + std::vector<wasm_value_t> locals_; +}; + +struct wasm_jit_table_entry_t { + int64_t typeidx; + uint8_t* addr; +}; + +struct wasm_instance_t { + wasm_module_t* module_; + std::vector<byte> memory_; + std::vector<wasm_func_t*> table_; + std::vector<wasm_jit_table_entry_t> jit_table_; + std::vector<wasm_value_t> globals_; + std::vector<wasm_value_t> value_stack_; + std::vector<wasm_stack_frame_t> frames_; + wasm_stack_frame_t* cur_frame_; + uint32_t trapped; + + void run_function(uint32_t funcidx); + wasm_value_t run(std::vector<wasm_value_t> args); + wasm_value_t run_jit(std::vector<wasm_value_t> args); + void run_fn(uint8_t* f, + size_t num_args, + wasm_value_t* args, + uint8_t* arg_types, + wasm_value_t* r, + int r_type); + void trap(uint32_t reason); + + uint32_t read_u32leb(); + int32_t read_i32leb(); + double read_double(); + byte read_byte(); + + void push_value(wasm_value_t v); + wasm_value_t pop_value(); + void branch(uint32_t to_off); + + void push_frame(wasm_func_t* f); + void pop_frame(); + + void ensure_memory(uint32_t offset); + void ensure_table(uint32_t offset); +}; + +#define WASM_TRAP_REASON_NOTRAP 0 +#define WASM_TRAP_REASON_FUNCEND 1 +#define WASM_TRAP_REASON_SIGFPE 2 +#define WASM_TRAP_REASON_OOB 3 +#define WASM_TRAP_REASON_TYPEERR 4 +#define WASM_TRAP_REASON_UNREACHABLE 5 +#define WASM_TRAP_REASON_NULLFUNCREF 6 +#define WASM_TRAP_REASON_NULLEXTERNREF 7 +#define WASM_TRAP_REASON_BADOBJECT 8 + +#define WASM_INST_TYPE_NOARG 0 +#define WASM_INST_TYPE_BLOCK 1 +#define WASM_INST_TYPE_I32 2 +#define WASM_INST_TYPE_F64 3 +#define WASM_INST_TYPE_MEMARG 4 +#define WASM_INST_TYPE_BRTABLE 5 +#define WASM_INST_TYPE_I32_I32 6 +#define WASM_INST_TYPE_S32 7 + +struct wasm_jit_t; + +struct wasm_inst_desc_t { + byte opcode_; + byte type_; + const char* name_; + void (*run)(wasm_instance_t* ins, byte opcode); + void (wasm_jit_t::*emit)(); +}; + +extern const struct wasm_inst_desc_t g_inst_desc[]; + +struct wasm_rt_func_t { + void (*run_)(wasm_instance_t* ins); + void* run_jit_; +}; +extern std::unordered_map<std::string, wasm_rt_func_t> g_runtime_funcs; + +#define WASM_EXTERN_NULL 0 +#define WASM_EXTERN_OBJECT 1 +#define WASM_EXTERN_STRING 2 +#define WASM_EXTERN_BOXI32 3 +#define WASM_EXTERN_BOXF64 4 + +struct wasm_externref_t { + uint32_t type_; + // make it not move constructible + wasm_externref_t(wasm_externref_t&&) = delete; + wasm_externref_t(uint32_t type) : type_(type){}; +}; + +struct wasm_e_string_t : public wasm_externref_t { + std::string str_; + wasm_e_string_t(const char* str) + : wasm_externref_t(WASM_EXTERN_STRING), str_(str) {} +}; + +typedef std::pair<uint32_t, uint64_t> wasm_key_t; + +struct wasm_e_object_t : public wasm_externref_t { + std::map<wasm_key_t, wasm_externref_t*> map_; + wasm_e_object_t() : wasm_externref_t(WASM_EXTERN_OBJECT) {} +}; + +struct wasm_e_box_t : public wasm_externref_t { + union { + int32_t i32_; + double f64_; + }; + wasm_e_box_t(uint32_t type) : wasm_externref_t(type) {} +}; + +extern wasm_instance_t* active_instance; +extern uint32_t jit; diff --git a/weerun_dis.cpp b/weerun_dis.cpp new file mode 100644 index 0000000..0e930aa --- /dev/null +++ b/weerun_dis.cpp @@ -0,0 +1,314 @@ +#include <assert.h> +#include <inttypes.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <iostream> +#include <map> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "weerun.hpp" + +template <typename T> +T decode(buffer_t* buf); + +template <typename T> +std::vector<T> decode_vector(buffer_t* buf) { + std::vector<T> result; + uint32_t num_elem = read_u32leb(buf); + for (uint32_t i = 0; i < num_elem; i++) { + result.push_back(decode<T>(buf)); + } + return result; +} + +template <> +byte decode<byte>(buffer_t* buf) { + return read_u8(buf); +} + +template <> +uint32_t decode<uint32_t>(buffer_t* buf) { + return read_u32leb(buf); +} + +template <> +std::string decode<std::string>(buffer_t* buf) { + uint32_t length = read_u32leb(buf); + std::string result(buf->ptr, buf->ptr + length); + buf->ptr += length; + return result; +} + +template <> +wasm_func_decl_t decode<wasm_func_decl_t>(buffer_t* buf) { + read_u8(buf); + wasm_func_decl_t result; + result.args_ = decode_vector<uint8_t>(buf); + result.ret_ = decode_vector<uint8_t>(buf); + return result; +} + +template <> +wasm_table_decl_t decode<wasm_table_decl_t>(buffer_t* buf) { + wasm_table_decl_t result; + result.type_ = read_u8(buf); + result.has_max_ = read_u8(buf); + result.init_ = read_u32leb(buf); + if (result.has_max_ != 0) { + result.max_ = read_u32leb(buf); + } + return result; +} + +template <> +wasm_memory_decl_t decode<wasm_memory_decl_t>(buffer_t* buf) { + wasm_memory_decl_t result; + result.has_max_ = read_u8(buf); + result.init_ = read_u32leb(buf); + if (result.has_max_ != 0) { + result.max_ = read_u32leb(buf); + } + return result; +} + +template <> +wasm_global_decl_t decode<wasm_global_decl_t>(buffer_t* buf) { + wasm_global_decl_t result; + result.type_ = read_u8(buf); + result.is_mut_ = read_u8(buf); + return result; +} + +template <> +wasm_import_decl_t decode<wasm_import_decl_t>(buffer_t* buf) { + wasm_import_decl_t result; + result.module_ = decode<std::string>(buf); + result.name_ = decode<std::string>(buf); + result.type_ = (wasm_import_decl_t::type)read_u8(buf); + switch (result.type_) { + case wasm_import_decl_t::type::FUNCTION: + result.funcindex_ = read_u32leb(buf); + break; + default: + break; + } + return result; +} + +template <> +wasm_global_t decode<wasm_global_t>(buffer_t* buf) { + wasm_global_t result; + result.type_ = decode<wasm_global_decl_t>(buf); + uint32_t opcode = read_u8(buf); + switch (opcode) { + case WASM_OP_I32_CONST: + result.val_.i32 = read_i32leb(buf); + break; + case WASM_OP_F64_CONST: + result.val_.f64 = *(double*)buf->ptr; + buf->ptr += sizeof(double); + break; + } + opcode = read_u8(buf); + return result; +} + +template <> +wasm_export_t decode<wasm_export_t>(buffer_t* buf) { + wasm_export_t result; + result.name_ = decode<std::string>(buf); + result.type_ = read_u32leb(buf); + result.idx_ = read_u32leb(buf); + return result; +} + +template <> +wasm_elem_decl_t decode<wasm_elem_decl_t>(buffer_t* buf) { + wasm_elem_decl_t result; + uint32_t tmp = read_u32leb(buf); + assert(tmp == 0); + tmp = read_u8(buf); + assert(tmp == WASM_OP_I32_CONST); + result.offset_ = read_i32leb(buf); + tmp = read_u8(buf); + assert(tmp == WASM_OP_END); + result.funcidx_ = decode_vector<uint32_t>(buf); + return result; +} + +template <> +wasm_local_decl_t decode<wasm_local_decl_t>(buffer_t* buf) { + wasm_local_decl_t result; + result.count_ = read_u32leb(buf); + result.type_ = read_u8(buf); + return result; +} + +wasm_code_decl_t decode_code_decl(buffer_t* buf, wasm_module_t* module) { + wasm_code_decl_t result; + result.size_ = read_u32leb(buf); + result.locals_ = decode_vector<wasm_local_decl_t>(buf); + const byte* code_start = buf->ptr; + + int blocks = 1; + // a block's enclosing block + std::map<const byte*, const byte*> block_parent; + + // a br's target block when br happens + std::map<const byte*, const byte*> br_target; + + // when we reach an OP_END, we can record the current block's end/start + // address. for OP_BLOCK we record the end address (OP_END+1). for OP_LOOP we + // record the start address (OP_LOOP+1). so when a br instruction wants to + // jump to this block, we know where to jump + std::map<const byte*, const byte*> block_target; + + const byte* cur_block = code_start; + block_parent[cur_block] = cur_block; + while (blocks != 0) { + uint32_t opcode = read_u8(buf); + const wasm_inst_desc_t* desc = &g_inst_desc[opcode]; + switch (desc->type_) { + case WASM_INST_TYPE_NOARG: + if (opcode == WASM_OP_END) { + blocks--; + if (blocks == 0) { + // reach the OP_END for the function body + block_target[cur_block] = buf->ptr - 1; + break; + } + // An OP_END for an OP_BLOCK/OP_LOOP + if (*(cur_block - 2) == WASM_OP_BLOCK) { + // br a block will go to the end + block_target[cur_block] = buf->ptr; + } else { + // br a loop will go to the beginning (skip OP_LOOP and blocktype) + block_target[cur_block] = cur_block; + } + cur_block = block_parent[cur_block]; + } + break; + case WASM_INST_TYPE_I32: + if (opcode == WASM_OP_BR || opcode == WASM_OP_BR_IF) { + const byte* ptr = buf->ptr; + const byte* block = cur_block; + uint32_t depth = read_u32leb(buf); + while (depth > 0) { + block = block_parent[block]; + depth--; + } + br_target[ptr] = block; + } else { + read_u32leb(buf); + } + break; + case WASM_INST_TYPE_S32: + read_i32leb(buf); + break; + case WASM_INST_TYPE_I32_I32: + read_u32leb(buf); + read_u32leb(buf); + break; + case WASM_INST_TYPE_F64: + buf->ptr += sizeof(double); + break; + case WASM_INST_TYPE_MEMARG: + read_u32leb(buf); + read_u32leb(buf); + break; + case WASM_INST_TYPE_BLOCK: + read_u8(buf); + if (opcode == WASM_OP_BLOCK || opcode == WASM_OP_LOOP) { + blocks++; + // link a block to its enclosing block + block_parent[buf->ptr] = cur_block; + cur_block = buf->ptr; + } + break; + case WASM_INST_TYPE_BRTABLE: { + uint32_t num_cases = read_u32leb(buf); + // cases and the default case + for (uint32_t i = 0; i <= num_cases; i++) { + const byte* ptr = buf->ptr; + const byte* block = cur_block; + // go through the blocks to find the target block + uint32_t depth = read_u32leb(buf); + while (depth > 0) { + block = block_parent[block]; + depth--; + } + br_target[ptr] = block; + } + } break; + default: + break; + } + } + result.code_ = std::vector<byte>(code_start, buf->ptr); + byte* patch_code = result.code_.data(); + // resolve all brs and rewrite it to offset + for (auto br : br_target) { + *(uint32_t*)(patch_code + (br.first - code_start)) = + (uint32_t)(block_target[br.second] - code_start); + } + return result; +} + +wasm_code_decl_t decode_code_decl_jit(buffer_t* buf, wasm_module_t* module) { + wasm_code_decl_t result; + result.size_ = read_u32leb(buf); + const byte* code_end = buf->ptr + result.size_; + result.locals_ = decode_vector<wasm_local_decl_t>(buf); + result.code_ = std::vector<byte>(buf->ptr, code_end); + buf->ptr = code_end; + return result; +} + +// turns out that decoding code section needs the module context +std::vector<wasm_code_decl_t> decode_vector_code_decl(buffer_t* buf, + wasm_module_t* module) { + std::vector<wasm_code_decl_t> result; + uint32_t num_elem = read_u32leb(buf); + for (uint32_t i = 0; i < num_elem; i++) { + if (jit != 0) { + result.push_back(decode_code_decl_jit(buf, module)); + } else { + result.push_back(decode_code_decl(buf, module)); + } + } + return result; +} + +template <> +wasm_data_decl_t decode<wasm_data_decl_t>(buffer_t* buf) { + wasm_data_decl_t result; + read_u32leb(buf); + read_u8(buf); + result.offset_ = read_i32leb(buf); + read_u8(buf); + result.data_ = decode_vector<byte>(buf); + return result; +} + +template std::vector<wasm_func_decl_t> decode_vector<wasm_func_decl_t>( + buffer_t* buffer); +template std::vector<wasm_import_decl_t> decode_vector<wasm_import_decl_t>( + buffer_t* buffer); +template std::vector<wasm_table_decl_t> decode_vector<wasm_table_decl_t>( + buffer_t* buffer); +template std::vector<wasm_memory_decl_t> decode_vector<wasm_memory_decl_t>( + buffer_t* buffer); +template std::vector<wasm_global_t> decode_vector<wasm_global_t>( + buffer_t* buffer); +template std::vector<wasm_export_t> decode_vector<wasm_export_t>( + buffer_t* buffer); +template std::vector<wasm_elem_decl_t> decode_vector<wasm_elem_decl_t>( + buffer_t* buffer); +template std::vector<wasm_data_decl_t> decode_vector<wasm_data_decl_t>( + buffer_t* buffer); +template std::vector<uint32_t> decode_vector<uint32_t>(buffer_t* buffer); diff --git a/weerun_inst.cpp b/weerun_inst.cpp new file mode 100644 index 0000000..f05997b --- /dev/null +++ b/weerun_inst.cpp @@ -0,0 +1,978 @@ +#include <cmath> +#include <iostream> + +#include "weerun.hpp" +#include "weerun_jit.hpp" + +#define INVALID_INST \ + { 0, 0, "illegal", nullptr, nullptr } + +static void run_unreachable(wasm_instance_t* ins, byte opcode); +static void run_nop(wasm_instance_t* ins, byte opcode); +static void run_drop(wasm_instance_t* ins, byte opcode); +static void run_select(wasm_instance_t* ins, byte opcode); +static void run_local_get(wasm_instance_t* ins, byte opcode); +static void run_local_set(wasm_instance_t* ins, byte opcode); +static void run_local_tee(wasm_instance_t* ins, byte opcode); +static void run_global_get(wasm_instance_t* ins, byte opcode); +static void run_global_set(wasm_instance_t* ins, byte opcode); + +#if 0 +static void run_tabel_get(wasm_instance_t* ins, byte opcode); +static void run_tabel_set(wasm_instance_t* ins, byte opcode); +#endif + +static void run_i32_load(wasm_instance_t* ins, byte opcode); +static void run_f64_load(wasm_instance_t* ins, byte opcode); +static void run_i32_load8_u(wasm_instance_t* ins, byte opcode); +static void run_i32_load8_s(wasm_instance_t* ins, byte opcode); +static void run_i32_load16_u(wasm_instance_t* ins, byte opcode); +static void run_i32_load16_s(wasm_instance_t* ins, byte opcode); +static void run_i32_store(wasm_instance_t* ins, byte opcode); +static void run_f64_store(wasm_instance_t* ins, byte opcode); +static void run_i32_store8(wasm_instance_t* ins, byte opcode); +static void run_i32_store16(wasm_instance_t* ins, byte opcode); +static void run_i32_const(wasm_instance_t* ins, byte opcode); +static void run_f64_const(wasm_instance_t* ins, byte opcode); +static void run_i32_numeric(wasm_instance_t* ins, byte opcode); +static void run_f64_compare(wasm_instance_t* ins, byte opcode); +static void run_f64_compute(wasm_instance_t* ins, byte opcode); +static void run_f64_convert(wasm_instance_t* ins, byte opcode); +static void run_call(wasm_instance_t* ins, byte opcode); +static void run_call_indirect(wasm_instance_t* ins, byte opcode); +static void run_return(wasm_instance_t* ins, byte opcode); +static void run_block(wasm_instance_t* ins, byte opcode); +static void run_end(wasm_instance_t* ins, byte opcode); +static void run_br(wasm_instance_t* ins, byte opcode); +static void run_br_table(wasm_instance_t* ins, byte opcode); + +const struct wasm_inst_desc_t g_inst_desc[] = { + {WASM_OP_UNREACHABLE, WASM_INST_TYPE_NOARG, "unreachable", run_unreachable, + &wasm_jit_t::emit_unreachable}, + {WASM_OP_NOP, WASM_INST_TYPE_NOARG, "nop", run_nop, &wasm_jit_t::emit_nop}, + {WASM_OP_BLOCK, WASM_INST_TYPE_BLOCK, "block", run_block, + &wasm_jit_t::emit_block}, + {WASM_OP_LOOP, WASM_INST_TYPE_BLOCK, "loop", run_block, + &wasm_jit_t::emit_block}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_END, WASM_INST_TYPE_NOARG, "end", run_end, &wasm_jit_t::emit_end}, + {WASM_OP_BR, WASM_INST_TYPE_I32, "br", run_br, &wasm_jit_t::emit_br}, + {WASM_OP_BR_IF, WASM_INST_TYPE_I32, "br_if", run_br, + &wasm_jit_t::emit_br_if}, + {WASM_OP_BR_TABLE, WASM_INST_TYPE_BRTABLE, "br_tale", run_br_table, + &wasm_jit_t::emit_br_table}, + {WASM_OP_RETURN, WASM_INST_TYPE_NOARG, "return", run_return, + &wasm_jit_t::emit_return}, + {WASM_OP_CALL, WASM_INST_TYPE_I32, "call", run_call, + &wasm_jit_t::emit_call}, + {WASM_OP_CALL_INDIRECT, WASM_INST_TYPE_I32_I32, "call_indirect", + run_call_indirect, &wasm_jit_t::emit_call_indirect}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_DROP, WASM_INST_TYPE_NOARG, "drop", run_drop, + &wasm_jit_t::emit_drop}, + {WASM_OP_SELECT, WASM_INST_TYPE_NOARG, "select", run_select, + &wasm_jit_t::emit_select}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_LOCAL_GET, WASM_INST_TYPE_I32, "local.get", run_local_get, + &wasm_jit_t::emit_local_get}, + {WASM_OP_LOCAL_SET, WASM_INST_TYPE_I32, "local.set", run_local_set, + &wasm_jit_t::emit_local_set}, + {WASM_OP_LOCAL_TEE, WASM_INST_TYPE_I32, "local.tee", run_local_tee, + &wasm_jit_t::emit_local_tee}, + {WASM_OP_GLOBAL_GET, WASM_INST_TYPE_I32, "global.get", run_global_get, + &wasm_jit_t::emit_global_get}, + {WASM_OP_GLOBAL_SET, WASM_INST_TYPE_I32, "global.set", run_global_set, + &wasm_jit_t::emit_global_set}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_I32_LOAD, WASM_INST_TYPE_MEMARG, "i32.load", run_i32_load, + &wasm_jit_t::emit_i32_load}, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_LOAD, WASM_INST_TYPE_MEMARG, "f64.load", run_f64_load, + &wasm_jit_t::emit_f64_load}, + {WASM_OP_I32_LOAD8_S, WASM_INST_TYPE_MEMARG, "i32.load8_s", run_i32_load8_s, + &wasm_jit_t::emit_i32_load}, + {WASM_OP_I32_LOAD8_U, WASM_INST_TYPE_MEMARG, "i32.load8_u", run_i32_load8_u, + &wasm_jit_t::emit_i32_load}, + {WASM_OP_I32_LOAD16_S, WASM_INST_TYPE_MEMARG, "i32.load16_s", + run_i32_load16_s, &wasm_jit_t::emit_i32_load}, + {WASM_OP_I32_LOAD16_U, WASM_INST_TYPE_MEMARG, "i32.load16_u", + run_i32_load16_u, &wasm_jit_t::emit_i32_load}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_I32_STORE, WASM_INST_TYPE_MEMARG, "i32.store", run_i32_store, + &wasm_jit_t::emit_i32_store}, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_STORE, WASM_INST_TYPE_MEMARG, "f64.store", run_f64_store, + &wasm_jit_t::emit_f64_store}, + {WASM_OP_I32_STORE8, WASM_INST_TYPE_MEMARG, "i32.store8", run_i32_store8, + &wasm_jit_t::emit_i32_store}, + {WASM_OP_I32_STORE16, WASM_INST_TYPE_MEMARG, "i32.store16", run_i32_store16, + &wasm_jit_t::emit_i32_store}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_I32_CONST, WASM_INST_TYPE_S32, "i32.const", run_i32_const, + &wasm_jit_t::emit_i32_const}, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_CONST, WASM_INST_TYPE_F64, "f64.const", run_f64_const, + &wasm_jit_t::emit_f64_const}, + {WASM_OP_I32_EQZ, WASM_INST_TYPE_NOARG, "i32.eqz", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_EQ, WASM_INST_TYPE_NOARG, "i32.eq", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_NE, WASM_INST_TYPE_NOARG, "i32.ne", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_LT_S, WASM_INST_TYPE_NOARG, "i32.lt_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_LT_U, WASM_INST_TYPE_NOARG, "i32.lt_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_GT_S, WASM_INST_TYPE_NOARG, "i32.gt_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_GT_U, WASM_INST_TYPE_NOARG, "i32.gt_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_LE_S, WASM_INST_TYPE_NOARG, "i32.le_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_LE_U, WASM_INST_TYPE_NOARG, "i32.le_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_GE_S, WASM_INST_TYPE_NOARG, "i32.ge_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_GE_U, WASM_INST_TYPE_NOARG, "i32.ge_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_EQ, WASM_INST_TYPE_NOARG, "f64.eq", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_NE, WASM_INST_TYPE_NOARG, "f64.ne", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_LT, WASM_INST_TYPE_NOARG, "f64.lt", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_GT, WASM_INST_TYPE_NOARG, "f64.gt", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_LE, WASM_INST_TYPE_NOARG, "f64.le", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_GE, WASM_INST_TYPE_NOARG, "f64.ge", run_f64_compare, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_I32_CLZ, WASM_INST_TYPE_NOARG, "i32.clz", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_CTZ, WASM_INST_TYPE_NOARG, "i32.ctz", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_POPCNT, WASM_INST_TYPE_NOARG, "i32.popcnt", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_ADD, WASM_INST_TYPE_NOARG, "i32.add", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_SUB, WASM_INST_TYPE_NOARG, "i32.sub", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_MUL, WASM_INST_TYPE_NOARG, "i32.mul", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_DIV_S, WASM_INST_TYPE_NOARG, "i32.div_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_DIV_U, WASM_INST_TYPE_NOARG, "i32.div_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_REM_S, WASM_INST_TYPE_NOARG, "i32.rem_s", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_REM_U, WASM_INST_TYPE_NOARG, "i32.rem_u", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_AND, WASM_INST_TYPE_NOARG, "i32.and", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_OR, WASM_INST_TYPE_NOARG, "i32.or", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_XOR, WASM_INST_TYPE_NOARG, "i32.xor", run_i32_numeric, + &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_SHL, WASM_INST_TYPE_NOARG, "i32.shl", run_i32_numeric, + &wasm_jit_t::emit_i32_shift}, + {WASM_OP_I32_SHR_S, WASM_INST_TYPE_NOARG, "i32.shr_s", run_i32_numeric, + &wasm_jit_t::emit_i32_shift}, + {WASM_OP_I32_SHR_U, WASM_INST_TYPE_NOARG, "i32.shr_u", run_i32_numeric, + &wasm_jit_t::emit_i32_shift}, + {WASM_OP_I32_ROTL, WASM_INST_TYPE_NOARG, "i32.rotl", run_i32_numeric, + &wasm_jit_t::emit_i32_shift}, + {WASM_OP_I32_ROTR, WASM_INST_TYPE_NOARG, "i32.rotr", run_i32_numeric, + &wasm_jit_t::emit_i32_shift}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_ADD, WASM_INST_TYPE_NOARG, "f64.add", run_f64_compute, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_SUB, WASM_INST_TYPE_NOARG, "f64.sub", run_f64_compute, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_MUL, WASM_INST_TYPE_NOARG, "f64.mul", run_f64_compute, + &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_DIV, WASM_INST_TYPE_NOARG, "f64.div", run_f64_compute, + &wasm_jit_t::emit_f64_compute}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_I32_TRUNC_F64_S, WASM_INST_TYPE_NOARG, "i32.trunc_f64_s", + run_i32_numeric, &wasm_jit_t::emit_i32_convert}, + {WASM_OP_I32_TRUNC_F64_U, WASM_INST_TYPE_NOARG, "i32.trunc_f64_u", + run_i32_numeric, &wasm_jit_t::emit_i32_convert}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_F64_CONVERT_I32_S, WASM_INST_TYPE_NOARG, "f64.convert_i32_s", + run_f64_convert, &wasm_jit_t::emit_f64_compute}, + {WASM_OP_F64_CONVERT_I32_U, WASM_INST_TYPE_NOARG, "f64.convert_i32_u", + run_f64_convert, &wasm_jit_t::emit_f64_compute}, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + INVALID_INST, + {WASM_OP_I32_EXTEND8_S, WASM_INST_TYPE_NOARG, "i32.extend8_s", + run_i32_numeric, &wasm_jit_t::emit_i32_numeric}, + {WASM_OP_I32_EXTEND16_S, WASM_INST_TYPE_NOARG, "i32.extend16_s", + run_i32_numeric, &wasm_jit_t::emit_i32_numeric}, +}; + +static bool is_zero(wasm_value_t v, uint8_t type) { + switch (type) { + case WASM_TYPE_I32: + return v.val.i32 == 0; + case WASM_TYPE_F64: + return v.val.f64 == 0; + default: + break; + } + return v.val.ref == nullptr; +} + +// fancy ops +static inline uint32_t i32_clz(uint32_t x) { + uint32_t zeros = 0; + for (int i = 31; i >= 0; i--) { + if ((x & (1 << i)) == 0) { + zeros++; + } else { + break; + } + } + return zeros; +} + +static inline uint32_t i32_ctz(uint32_t x) { + uint32_t zeros = 0; + for (int i = 0; i < 32; i++) { + if ((x & (1 << i)) == 0) { + zeros++; + } else { + break; + } + } + return zeros; +} + +static inline uint32_t i32_popcnt(uint32_t x) { + uint32_t ones = 0; + for (int i = 31; i >= 0; i--) { + if ((x & (1 << i)) != 0) { + ones++; + } + } + return ones; +} + +static inline uint32_t i32_rotl(uint32_t x, uint32_t n) { + return (x << n) | (x >> (32 - n)); +} + +static inline uint32_t i32_rotr(uint32_t x, uint32_t n) { + return (x >> n) | (x << (32 - n)); +} + +static inline std::pair<bool, int32_t> i32_div_s(int32_t a, int32_t b) { + if (b == 0) { + return {false, 0}; + } + if (a == (int32_t)0x80000000 && b == (int32_t)0xffffffff) { + return {false, 0}; + } + return {true, a / b}; +} + +static inline std::pair<bool, int32_t> i32_rem_s(int32_t a, int32_t b) { + if (b == 0) { + return {false, 0}; + } + if (a == (int32_t)0x80000000 && b == (int32_t)0xffffffff) { + return {true, 0}; + } + return {true, a % b}; +} + +static inline std::pair<bool, uint32_t> i32_div_u(uint32_t a, uint32_t b) { + if (b == 0) { + return {false, 0}; + } + return {true, a / b}; +} + +static inline std::pair<bool, uint32_t> i32_rem_u(uint32_t a, uint32_t b) { + if (b == 0) { + return {false, 0}; + } + return {true, a % b}; +} + +static inline std::pair<bool, int32_t> i32_trunc_f64_s(double x) { + int type = std::fpclassify(x); + if (type == FP_NAN || type == FP_INFINITE) { + return {false, 0}; + } + if (x <= -2147483649.0 || x >= 2147483648.0) { + return {false, 0}; + } + return {true, x}; +} + +static inline std::pair<bool, uint32_t> i32_trunc_f64_u(double x) { + int type = std::fpclassify(x); + if (type == FP_NAN || type == FP_INFINITE) { + return {false, 0}; + } + if (x <= -1.0 || x >= 4294967296.0) { + return {false, 0}; + } + return {true, x}; +} + +template <typename T> +static inline bool check_access(wasm_instance_t* ins, + uint32_t offset, + uint32_t addend) { + uint32_t size = ins->memory_.size(); + return offset <= size && addend <= size && + offset + addend + sizeof(T) <= size; +} + +static void run_unreachable(wasm_instance_t* ins, byte opcode) { + ins->trap(WASM_OP_UNREACHABLE); +} + +static void run_nop(wasm_instance_t* ins, byte opcode) {} + +static void run_drop(wasm_instance_t* ins, byte opcode) { + ins->pop_value(); +} + +static void run_select(wasm_instance_t* ins, byte opcode) { + wasm_value_t c = ins->pop_value(); + wasm_value_t b = ins->pop_value(); + wasm_value_t a = ins->pop_value(); + if (is_zero(c, WASM_TYPE_I32) == false) { + ins->push_value(a); + } else { + ins->push_value(b); + } +} + +static void run_local_get(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + ins->push_value(ins->cur_frame_->locals_[idx]); +} + +static void run_local_set(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + ins->cur_frame_->locals_[idx] = ins->pop_value(); +} + +static void run_local_tee(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + wasm_value_t v = ins->value_stack_.back(); + ins->cur_frame_->locals_[idx] = v; +} + +static void run_global_get(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + ins->push_value(ins->globals_[idx]); +} + +static void run_global_set(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + ins->globals_[idx] = ins->pop_value(); +} + +#if 0 +static void run_tabel_get(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + wasm_value_t v; + v.val.ref = (void*)ins->table_[idx]; + ins->push_value(v); +} + +static void run_tabel_set(wasm_instance_t* ins, byte opcode) { + uint32_t idx = ins->read_u32leb(); + ins->table_[idx] = (wasm_func_t*)ins->pop_value().val.ref; +} +#endif + +static void run_i32_load(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint32_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + wasm_value_t v; + v.val.i32 = *(uint32_t*)(base + (offset + addend)); + ins->push_value(v); +} + +static void run_f64_load(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<double>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + wasm_value_t v; + v.val.f64 = *(double*)(base + (offset + addend)); + ins->push_value(v); +} + +static void run_i32_load8_u(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint8_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + uint8_t u8 = *(uint8_t*)(base + (offset + addend)); + wasm_value_t v; + v.val.i32 = (uint32_t)u8; + ins->push_value(v); +} + +static void run_i32_load8_s(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<int8_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + int8_t i8 = *(int8_t*)(base + (offset + addend)); + wasm_value_t v; + v.val.i32 = (uint32_t)(int32_t)i8; + ins->push_value(v); +} + +static void run_i32_load16_u(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint16_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + uint16_t u16 = *(uint16_t*)(base + (offset + addend)); + wasm_value_t v; + v.val.i32 = (uint32_t)u16; + ins->push_value(v); +} + +static void run_i32_load16_s(wasm_instance_t* ins, byte opcode) { + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<int16_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + int16_t i16 = *(int16_t*)(base + (offset + addend)); + wasm_value_t v; + v.val.i32 = (uint32_t)(int32_t)i16; + ins->push_value(v); +} + +static void run_i32_store(wasm_instance_t* ins, byte opcode) { + wasm_value_t v = ins->pop_value(); + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint32_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + *(uint32_t*)(base + (offset + addend)) = v.val.i32; +} + +static void run_f64_store(wasm_instance_t* ins, byte opcode) { + wasm_value_t v = ins->pop_value(); + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<double>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + *(double*)(base + (offset + addend)) = v.val.f64; +} + +static void run_i32_store8(wasm_instance_t* ins, byte opcode) { + wasm_value_t v = ins->pop_value(); + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint8_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + *(uint8_t*)(base + (offset + addend)) = (uint8_t)v.val.i32; +} + +static void run_i32_store16(wasm_instance_t* ins, byte opcode) { + wasm_value_t v = ins->pop_value(); + uint32_t addend = ins->pop_value().val.i32; + ins->read_u32leb(); + uint32_t offset = ins->read_u32leb(); + if (check_access<uint16_t>(ins, offset, addend) == false) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + byte* base = ins->memory_.data(); + *(uint16_t*)(base + (offset + addend)) = (uint16_t)v.val.i32; +} + +static void run_i32_const(wasm_instance_t* ins, byte opcode) { + uint32_t x = ins->read_i32leb(); + wasm_value_t v; + v.val.i32 = x; + ins->push_value(v); +} + +static void run_f64_const(wasm_instance_t* ins, byte opcode) { + double x = ins->read_double(); + wasm_value_t v; + v.val.f64 = x; + ins->push_value(v); +} + +static void run_i32_numeric(wasm_instance_t* ins, byte opcode) { + wasm_value_t a; + wasm_value_t b; + wasm_value_t result; + + b = ins->pop_value(); + switch (opcode) { + case WASM_OP_I32_EQZ: + result.val.i32 = (b.val.i32 == 0); + break; + case WASM_OP_I32_EQ: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 == b.val.i32); + break; + case WASM_OP_I32_NE: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 != b.val.i32); + break; + case WASM_OP_I32_LT_S: + a = ins->pop_value(); + result.val.i32 = ((int32_t)a.val.i32 < (int32_t)b.val.i32); + break; + case WASM_OP_I32_LT_U: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 < b.val.i32); + break; + case WASM_OP_I32_GT_S: + a = ins->pop_value(); + result.val.i32 = ((int32_t)a.val.i32 > (int32_t)b.val.i32); + break; + case WASM_OP_I32_GT_U: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 > b.val.i32); + break; + case WASM_OP_I32_LE_S: + a = ins->pop_value(); + result.val.i32 = ((int32_t)a.val.i32 <= (int32_t)b.val.i32); + break; + case WASM_OP_I32_LE_U: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 <= b.val.i32); + break; + case WASM_OP_I32_GE_S: + a = ins->pop_value(); + result.val.i32 = ((int32_t)a.val.i32 >= (int32_t)b.val.i32); + break; + case WASM_OP_I32_GE_U: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 >= b.val.i32); + break; + case WASM_OP_I32_CLZ: + result.val.i32 = i32_clz(b.val.i32); + break; + case WASM_OP_I32_CTZ: + result.val.i32 = i32_ctz(b.val.i32); + break; + case WASM_OP_I32_POPCNT: + result.val.i32 = i32_popcnt(b.val.i32); + break; + case WASM_OP_I32_ADD: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 + b.val.i32); + break; + case WASM_OP_I32_SUB: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 - b.val.i32); + break; + case WASM_OP_I32_MUL: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 * b.val.i32); + break; + case WASM_OP_I32_DIV_S: { + a = ins->pop_value(); + auto r = i32_div_s((int32_t)a.val.i32, (int32_t)b.val.i32); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_DIV_U: { + a = ins->pop_value(); + auto r = i32_div_u((int32_t)a.val.i32, (int32_t)b.val.i32); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_REM_S: { + a = ins->pop_value(); + auto r = i32_rem_s((int32_t)a.val.i32, (int32_t)b.val.i32); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_REM_U: { + a = ins->pop_value(); + auto r = i32_rem_u((int32_t)a.val.i32, (int32_t)b.val.i32); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_AND: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 & b.val.i32); + break; + case WASM_OP_I32_OR: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 | b.val.i32); + break; + case WASM_OP_I32_XOR: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 ^ b.val.i32); + break; + case WASM_OP_I32_SHL: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 << b.val.i32); + break; + case WASM_OP_I32_SHR_S: + a = ins->pop_value(); + result.val.i32 = ((int32_t)a.val.i32 >> b.val.i32); + break; + case WASM_OP_I32_SHR_U: + a = ins->pop_value(); + result.val.i32 = (a.val.i32 >> b.val.i32); + break; + case WASM_OP_I32_ROTL: + a = ins->pop_value(); + result.val.i32 = i32_rotl(a.val.i32, b.val.i32); + break; + case WASM_OP_I32_ROTR: + a = ins->pop_value(); + result.val.i32 = i32_rotr(a.val.i32, b.val.i32); + break; + case WASM_OP_I32_TRUNC_F64_S: { + auto r = i32_trunc_f64_s(b.val.f64); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_TRUNC_F64_U: { + auto r = i32_trunc_f64_u(b.val.f64); + if (r.first == false) { + ins->trap(WASM_TRAP_REASON_SIGFPE); + return; + } + result.val.i32 = r.second; + break; + } + case WASM_OP_I32_EXTEND8_S: + result.val.i32 = (int32_t)(int8_t)b.val.i32; + break; + case WASM_OP_I32_EXTEND16_S: + result.val.i32 = (int32_t)(int16_t)b.val.i32; + break; + } + ins->push_value(result); +} + +static void run_f64_compare(wasm_instance_t* ins, byte opcode) { + wasm_value_t a; + wasm_value_t b; + wasm_value_t result; + + b = ins->pop_value(); + a = ins->pop_value(); + switch (opcode) { + case WASM_OP_F64_LT: + result.val.i32 = (a.val.f64 < b.val.f64); + break; + case WASM_OP_F64_GT: + result.val.i32 = (a.val.f64 > b.val.f64); + break; + case WASM_OP_F64_LE: + result.val.i32 = (a.val.f64 <= b.val.f64); + break; + case WASM_OP_F64_GE: + result.val.i32 = (a.val.f64 >= b.val.f64); + break; + case WASM_OP_F64_EQ: + result.val.i32 = (a.val.f64 == b.val.f64); + break; + case WASM_OP_F64_NE: + result.val.i32 = (a.val.f64 != b.val.f64); + break; + } + ins->push_value(result); +} + +static void run_f64_compute(wasm_instance_t* ins, byte opcode) { + wasm_value_t a; + wasm_value_t b; + wasm_value_t result; + + b = ins->pop_value(); + a = ins->pop_value(); + switch (opcode) { + case WASM_OP_F64_ADD: + result.val.f64 = (a.val.f64 + b.val.f64); + break; + case WASM_OP_F64_SUB: + result.val.f64 = (a.val.f64 - b.val.f64); + break; + case WASM_OP_F64_MUL: + result.val.f64 = (a.val.f64 * b.val.f64); + break; + case WASM_OP_F64_DIV: + result.val.f64 = (a.val.f64 / b.val.f64); + break; + } + ins->push_value(result); +} + +static void run_f64_convert(wasm_instance_t* ins, byte opcode) { + wasm_value_t b; + wasm_value_t result; + + b = ins->pop_value(); + switch (opcode) { + case WASM_OP_F64_CONVERT_I32_S: + result.val.f64 = (int32_t)b.val.i32; + break; + case WASM_OP_F64_CONVERT_I32_U: + result.val.f64 = b.val.i32; + break; + } + ins->push_value(result); +} + +static void run_call(wasm_instance_t* ins, byte opcode) { + uint32_t funcidx = ins->read_u32leb(); + ins->push_frame(&ins->module_->funcs_[funcidx]); +} + +bool is_same_type(wasm_func_decl_t* s, wasm_func_decl_t* t) { + if (s->args_.size() != t->args_.size()) { + return false; + } + if (memcmp(s->args_.data(), t->args_.data(), s->args_.size()) != 0) { + return false; + } + if (s->ret_.size() != t->ret_.size()) { + return false; + } + if (memcmp(s->ret_.data(), t->ret_.data(), s->ret_.size()) != 0) { + return false; + } + return true; +} + +static void run_call_indirect(wasm_instance_t* ins, byte opcode) { + ins->read_u32leb(); + uint32_t typeidx = ins->read_u32leb(); + wasm_value_t v = ins->pop_value(); + if (v.val.i32 >= ins->table_.size() || + typeidx >= ins->module_->sigs_.size()) { + ins->trap(WASM_TRAP_REASON_OOB); + return; + } + wasm_func_t* f = ins->table_[v.val.i32]; + if (f == nullptr) { + ins->trap(WASM_TRAP_REASON_NULLFUNCREF); + return; + } + if (is_same_type(&ins->module_->sigs_[typeidx], f->sig_) == false) { + ins->trap(WASM_TRAP_REASON_TYPEERR); + return; + } + ins->push_frame(ins->table_[v.val.i32]); +} + +static void run_return(wasm_instance_t* ins, byte opcode) { + ins->pop_frame(); + if (ins->frames_.empty()) { + ins->trap(WASM_TRAP_REASON_FUNCEND); + } +} + +static void run_block(wasm_instance_t* ins, byte opcode) { + // read the blocktype byte and go + ins->read_byte(); +} + +static void run_end(wasm_instance_t* ins, byte opcode) { + // only the OP_END for the outermost function matters + if (ins->cur_frame_->pc_.ptr == ins->cur_frame_->pc_.end) { + ins->pop_frame(); + if (ins->frames_.empty()) { + ins->trap(WASM_TRAP_REASON_FUNCEND); + } + } +} + +static void run_br(wasm_instance_t* ins, byte opcode) { + if (opcode == WASM_OP_BR_IF) { + wasm_value_t v = ins->pop_value(); + if (is_zero(v, WASM_TYPE_I32) == true) { + ins->cur_frame_->pc_.ptr += sizeof(uint32_t); + return; + } + } + uint32_t to_off = *(uint32_t*)(ins->cur_frame_->pc_.ptr); + ins->branch(to_off); +} + +static void run_br_table(wasm_instance_t* ins, byte opcode) { + uint32_t num_cases = ins->read_u32leb(); + uint32_t* cases = (uint32_t*)(ins->cur_frame_->pc_.ptr); + wasm_value_t v = ins->pop_value(); + uint32_t to_off; + uint32_t index = std::min(v.val.i32, num_cases); + to_off = cases[index]; + ins->branch(to_off); +} diff --git a/weerun_jit.cpp b/weerun_jit.cpp new file mode 100644 index 0000000..ece5b4f --- /dev/null +++ b/weerun_jit.cpp @@ -0,0 +1,1726 @@ +#include <array> +#include <cstdlib> +#include <cstring> +#include <iostream> +#include <map> +#include <utility> +#include <vector> + +#include "weerun_jit.hpp" + +#define JIT_V(type, i) \ + (wasm_jit_val_t) { wasm_jit_type_t::type, (i) } + +#define JIT_V_INVALID JIT_V(INVALID, 0) +#define JIT_V_CALLER JIT_V(CALLER_DATA, 0) +#define JIT_V_INTER JIT_V(INTERMEDIATE, 0) +#define JIT_V_LOCAL(i) JIT_V(LOCAL_VAL, (int32_t)(i)) +#define JIT_V_STACK(i) JIT_V(STACK_VAL, (int32_t)(i)) +#define JIT_V_GLOBAL_BASE JIT_V(GLOBAL_BASE, 0) +#define JIT_V_MEMORY_BASE JIT_V(MEMORY_BASE, 0) +#define JIT_V_MEMORY_SIZE JIT_V(MEMORY_SIZE, 0) + +const static int32_t sysv_args[] = {reg::rdi, reg::rsi, reg::rdx, + reg::rcx, reg::r8, reg::r9}; + +inline Xbyak::Reg64 wasm_jit_t::to_xbyak_r64(int32_t index) { + const static Xbyak::Reg64 xbyak_regs[] = {rax, rdx, rcx, rdi, rsi, r8, r9, + r10, r11, rbx, r12, r13, r14, r15}; + return xbyak_regs[index]; +} + +inline Xbyak::Reg32 wasm_jit_t::to_xbyak_r32(int32_t index) { + const static Xbyak::Reg32 xbyak_regs[] = {eax, edx, ecx, edi, esi, + r8d, r9d, r10d, r11d, ebx, + r12d, r13d, r14d, r15d}; + return xbyak_regs[index]; +} + +inline Xbyak::Reg16 wasm_jit_t::to_xbyak_r16(int32_t index) { + const static Xbyak::Reg16 xbyak_regs[] = { + ax, dx, cx, di, si, r8w, r9w, r10w, r11w, bx, r12w, r13w, r14w, r15w}; + return xbyak_regs[index]; +} + +inline Xbyak::Reg8 wasm_jit_t::to_xbyak_r8(int32_t index) { + const static Xbyak::Reg8 xbyak_regs[] = { + al, dl, cl, dil, sil, r8b, r9b, r10b, r11b, bl, r12b, r13b, r14b, r15b}; + return xbyak_regs[index]; +} + +inline Xbyak::Xmm wasm_jit_t::to_xbyak_xmm(int32_t index) { + const static Xbyak::Xmm xbyak_regs[] = { + xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, + xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15}; + return xbyak_regs[index - reg::xmm0]; +} + +// stack layout: +// return address (-1) +// RBP --> saved rbp (0) +// space for rbx,r12-r15 (1, +5) +// locals (6, +num_locals) +// wasm stack (6+num_locals, +max_stack) +// RSP --> + +// function layout +// F1: +// prologue (changed from nop after jitting body) +// body (first generated) +// F1E: +// epilogue (last generated) + +// loop layout +// OP_LOOP +// F1L1: +// OP_WHATEVER +// OP_BR -> L_1 (jmp to F1L1T0) +// OP_WHATEVER +// OP_BR -> L_1 (jmp to F1L2T1) +// OP_END +// (jmp to F1L1E) +// F1L1T0: +// (restore context and jmp to F1L1) +// F1L2T1: +// (restore context and jmp to F1L1) +// F1L1E: +// OP_WHATEVER + +// block layout +// OP_BLOCK +// OP_WHATEVER +// OP_BR -> B_2 (F1B2 not generated, jmp to F1L2T0) +// OP_WHATEVER +// OP_BR -> B_2 (F1B2 not generated, jmp to F1L2T1) +// OP_END +// (jmp to F1L2E) +// F1L2T0: +// (restore context and jmp to F1L2E) +// F1L2T1: +// (restore context and jmp to F1L2E) +// F1L2E: +// OP_WHATEVER + +// br_table layout +// OP_BR_TABLE +// jmp [table_base + table_index*8] +// .c1: +// jmp F1L1T1 +// .c2 +// jmp F1L2T1 +// .c3 +// jmp F1L1T1 + +// table content: .c1, .c2, .c3 + +void wasm_jit_ctx_t::init(wasm_jit_t* jit, wasm_func_t* f) { + reg_ = {JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_CALLER, JIT_V_CALLER, JIT_V_CALLER, + JIT_V_CALLER, JIT_V_CALLER, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, JIT_V_INVALID, + JIT_V_INVALID, JIT_V_INVALID}; + int num_args = f->sig_->args_.size(); + int num_locals = jit->local_types_.size(); + stack_valid_.resize(num_locals + 6, false); + stack_loc_.clear(); + local_loc_.resize(num_locals); + int num_r64 = 0; + int num_f64 = 0; + int num_stack_r64 = 0; + int num_stack_f64 = 0; + for (uint8_t arg : f->sig_->args_) { + if (arg != WASM_TYPE_F64) { + if (num_r64 < 6) { + num_r64++; + } else { + num_stack_r64++; + } + } else { + if (num_f64 < 8) { + num_f64++; + } else { + num_stack_f64++; + } + } + } + int stack_arg_index = num_stack_r64 + num_stack_f64 + 1; + for (int i = num_args - 1; i >= 0; i--) { + uint8_t arg = f->sig_->args_[i]; + if (arg != WASM_TYPE_F64) { + if (num_stack_r64 > 0) { + local_loc_[i] = {reg::on_stack, i + 6}; + jit->mov(jit->rax, jit->qword[jit->rbp + (stack_arg_index * 0x8)]); + jit->rbp_save_r(i + 6, reg::rax); + stack_arg_index--; + num_stack_r64--; + local_loc_[i] = {reg::on_stack, i + 6}; + } else { + num_r64--; + local_loc_[i] = {reg::in_reg, sysv_args[num_r64]}; + reg_[sysv_args[num_r64]] = JIT_V_LOCAL(i); + } + } else { + if (num_stack_f64 > 0) { + local_loc_[i] = {reg::on_stack, i + 6}; + jit->mov(jit->rax, jit->qword[jit->rbp + (stack_arg_index * 0x8)]); + jit->rbp_save_r(i + 6, reg::rax); + stack_arg_index--; + num_stack_f64--; + local_loc_[i] = {reg::on_stack, i + 6}; + } else { + num_f64--; + local_loc_[i] = {reg::in_reg, reg::xmm0 + num_f64}; + reg_[reg::xmm0 + num_f64] = JIT_V_LOCAL(i); + } + } + } + bool r10_clear = false; + bool xmm8_clear = false; + for (int i = num_args; i < num_locals; i++) { + local_loc_[i] = {reg::on_stack, i + 6}; + if (jit->local_types_[i] != WASM_TYPE_F64) { + if (r10_clear == false) { + jit->xor_(jit->r10, jit->r10); + r10_clear = true; + } + jit->rbp_save_r(i + 6, reg::r10); + } else { + if (xmm8_clear == false) { + jit->xorpd(jit->xmm8, jit->xmm8); + xmm8_clear = true; + } + jit->rbp_save_r(i + 6, reg::xmm8); + } + } + std::memset(reg_age_.data(), 0, 30 * sizeof(uint32_t)); + age_ = 0; +} + +const static size_t memory_off = 0x0; +const static size_t global_off = 0x8; +const static size_t table_off = 0x10; +const static size_t memory_size_off = 0x18; +const static size_t table_size_off = 0x20; +const static size_t trap_off = 0x28; +const static size_t f64_const_off = 0x30; + +void trap() { + std::cout << "!trap" << std::endl; + std::exit(-1); +} + +wasm_jit_t::wasm_jit_t(uint64_t code_size) + : CodeGenerator(code_size), enable_check_(true) { + size_t pos = getSize(); + endbr64(); + push(rbp); + mov(rbp, rsp); + push(rbx); + push(r12); + push(r13); + push(r14); + push(r15); + sub(rsp, 0x12345678); + max_prologue_size_ = getSize() - pos; + reset(); +} + +typedef void (*run_void_t)(uint8_t* f, + uint64_t* reg, + uint64_t* stack, + size_t num_stack); +typedef uint64_t (*run_rax_t)(uint8_t* f, + uint64_t* reg, + uint64_t* stack, + size_t num_stack); +typedef double (*run_xmm_t)(uint8_t* f, + uint64_t* reg, + uint64_t* stack, + size_t num_stack); + +// r_type 0:void 1:rax 2:xmm0 +void wasm_jit_t::run_fn(uint32_t index, wasm_value_t* args, wasm_value_t* r) { + wasm_func_decl_t* sig = mod_->funcs_[index].sig_; + size_t num_args = sig->args_.size(); + uint8_t* arg_types = sig->args_.data(); + std::vector<uint64_t> stack; + std::array<uint64_t, 14> reg; // 6 r + 6 xmm + size_t num_r64 = 0; + size_t num_f64 = 0; + for (size_t i = 0; i < num_args; i++) { + if (arg_types[i] != WASM_TYPE_F64) { + if (num_r64 < 6) { + reg[num_r64] = args[i].val.i64; + num_r64++; + } else { + stack.push_back(args[i].val.i64); + } + } else { + if (num_f64 < 8) { + reg[6 + num_f64] = args[i].val.i64; + num_f64++; + } else { + stack.push_back(args[i].val.i64); + } + } + } + uint8_t* f = f_addr_[index]; + if (sig->ret_.empty() == true) { + run_void_t run_void = (run_void_t)run_fn_; + run_void(f, reg.data(), stack.data(), stack.size()); + } else if (sig->ret_[0] != WASM_TYPE_F64) { + run_rax_t run_rax = (run_rax_t)run_fn_; + r->val.i64 = run_rax(f, reg.data(), stack.data(), stack.size()); + } else { + run_xmm_t run_xmm = (run_xmm_t)run_fn_; + r->val.f64 = run_xmm(f, reg.data(), stack.data(), stack.size()); + } +} + +void wasm_jit_t::compile_instance(wasm_instance_t* ins) { + ins_ = ins; + mod_ = ins->module_; + f_addr_.resize(mod_->funcs_.size()); + + dq((uint64_t)ins->memory_.data()); + dq((uint64_t)ins->globals_.data()); + dq((uint64_t)ins->jit_table_.data()); + dq((uint64_t)ins->memory_.size()); + dq((uint64_t)ins->jit_table_.size()); + dq((uint64_t)trap); + + // f64 consts needed by i32.trunc, copied from GDB... + dq(0x7fffffffffffffff); + dq(0x0000000000000000); + dq(0x7fefffffffffffff); + dq(0x41e0000000000000); + dq(0xc1e0000000200000); + dq(0x41f0000000000000); + dq(0xbff0000000000000); + + L("trap"); + push(rax); + emit_mov_r_rip(reg::rax, trap_off); + xchg(qword[rsp], rax); // push address of trap() and preserve rax + ret(); // jump to trap() + + emit_runtime_functions(); + int num_funcs = mod_->funcs_.size(); + for (int i = mod_->num_import_funcs_; i < num_funcs; i++) { + compile_function(i); + } + + // fill jit table + for (wasm_elem_decl_t& elem : mod_->elems_) { + wasm_jit_table_entry_t* p = &ins_->jit_table_[elem.offset_]; + for (uint32_t funcidx : elem.funcidx_) { + *p = {mod_->funcs_[funcidx].typeid_, f_addr_[funcidx]}; + p++; + } + } +} + +void wasm_jit_t::emit_runtime_functions() { + align(8); + size_t num_rt = mod_->num_import_funcs_; + for (size_t i = 0; i < num_rt; i++) { + wasm_func_t* f = &mod_->funcs_[i]; + f_addr_[i] = (uint8_t*)f->run_jit_; + + size_t offset = getSize(); + dq((uint64_t)f->run_jit_); + L("F" + std::to_string(i)); + emit_lea_r_rip(reg::r10, offset); + jmp(qword[r10]); + } + align(16); + + // rdi: f + // rsi: reg + // rdx: stack + // rcx: num_stack + run_fn_ = const_cast<uint8_t*>(getCurr()); + inLocalLabel(); + endbr64(); + push(rbp); + mov(rbp, rsp); + test(rcx, 0x1); + je(".no_padding"); + sub(rsp, 0x8); + L(".no_padding"); + lea(r8, qword[rdx + rcx * 8]); + L(".push_stack"); + test(rcx, rcx); + je(".no_stack"); + sub(r8, 0x8); + mov(rax, qword[r8]); + push(rax); + dec(rcx); + jmp(".push_stack"); + L(".no_stack"); + mov(r10, rdi); + mov(rax, rsi); + mov(rdi, qword[rax]); + mov(rsi, qword[rax + 0x8]); + mov(rdx, qword[rax + 0x10]); + mov(rcx, qword[rax + 0x18]); + mov(r8, qword[rax + 0x20]); + mov(r9, qword[rax + 0x28]); + movsd(xmm0, qword[rax + 0x30]); + movsd(xmm1, qword[rax + 0x38]); + movsd(xmm2, qword[rax + 0x40]); + movsd(xmm3, qword[rax + 0x48]); + movsd(xmm4, qword[rax + 0x50]); + movsd(xmm5, qword[rax + 0x58]); + movsd(xmm6, qword[rax + 0x60]); + movsd(xmm7, qword[rax + 0x68]); + call(r10); + leave(); + ret(); + outLocalLabel(); +} + +void wasm_jit_t::compile_function(uint32_t index) { + f_ = &mod_->funcs_[index]; + funcidx_ = index; + int num_f_locals = 0; + local_types_.clear(); + for (uint8_t t : f_->sig_->args_) { + local_types_.push_back(t); + } + for (wasm_local_decl_t decl : f_->locals_) { + for (int i = 0; i < (int)decl.count_; i++) { + local_types_.push_back(decl.type_); + } + num_f_locals += decl.count_; + } + num_locals_ = f_->sig_->args_.size() + num_f_locals; + + rsp_sub_ = ((num_locals_ + 6) - 1) * 0x8; + if (rsp_sub_ % 16 == 8) { + rsp_sub_ += 8; + } + used_callee_ = {0, 0, 0, 0, 0}; + + buf_.start = buf_.ptr = f_->code_.data(); + buf_.end = buf_.start + f_->code_.size(); + next_bi_ = 0; + stop_ = 0; + + // save space for prologue + size_t start_off = getSize(); + nop(max_prologue_size_, false); + size_t body_off = getSize(); + uint8_t* body_pos = const_cast<uint8_t*>(getCurr()); + + // generate function body + ctx_.init(this, f_); + block_stack_.push_back({0, next_bi_++}); + while (stop_ != 1) { + opcode_ = read_u8(&buf_); + const wasm_inst_desc_t* desc = &g_inst_desc[opcode_]; + if (desc->emit == nullptr) { + __asm__("int3"); + } + (this->*desc->emit)(); + } + block_stack_.clear(); + size_t end_off = getSize(); + L("F" + std::to_string(funcidx_) + "E"); + + // generate prologue + setSize(start_off); + endbr64(); + push(rbp); + mov(rbp, rsp); + for (int32_t i = 0; i < 5; i++) { + if (used_callee_[i] != 0) { + push(to_xbyak_r64(reg::rbx + i)); + rsp_sub_ -= 0x8; + } + } + sub(rsp, rsp_sub_); + size_t prologue_size = getSize() - start_off; + size_t gap_size = max_prologue_size_ - prologue_size; + for (size_t i = 0; i < prologue_size; i++) { + body_pos--; + *body_pos = *(body_pos - gap_size); + } + f_addr_[funcidx_] = body_pos; + setSize(start_off); + nop(gap_size); + setSize(body_off - prologue_size); + L("F" + std::to_string(funcidx_)); + + // generate epilogue + setSize(end_off); + add(rsp, rsp_sub_); + for (int32_t i = 4; i >= 0; i--) { + if (used_callee_[i] != 0) { + pop(to_xbyak_r64(reg::rbx + i)); + } + } + pop(rbp); + ret(); +} + +int32_t wasm_jit_t::alloc_r(wasm_jit_val_t usage, uint8_t type) { + int32_t start, end; + if (type != WASM_TYPE_F64) { + start = reg::rax; + end = reg::xmm0; + } else { + start = reg::xmm0; + end = reg::num_r; + } + uint32_t min_age = UINT32_MAX; + int32_t min_r = start; + for (int32_t r = start; r < end; r++) { + if (ctx_.reg_[r].type == wasm_jit_type_t::INVALID) { + acquire_r(r, usage); + return r; + } + if (ctx_.reg_age_[r] < min_age) { + min_age = ctx_.reg_age_[r]; + min_r = r; + } + } + acquire_r(min_r, usage); + return min_r; +} + +void wasm_jit_t::acquire_r(int32_t index, wasm_jit_val_t usage) { + wasm_jit_val_t old_usage = ctx_.reg_[index]; + int32_t s; + switch (old_usage.type) { + case wasm_jit_type_t::CALLER_DATA: + used_callee_[index - reg::rbx] = 1; + break; + case wasm_jit_type_t::LOCAL_VAL: + s = old_usage.index + 6; + rbp_save_r(s, index); + ctx_.local_loc_[old_usage.index] = {reg::on_stack, s}; + break; + case wasm_jit_type_t::STACK_VAL: + s = alloc_stk(); + rbp_save_r(s, index); + ctx_.stack_loc_[old_usage.index] = {reg::on_stack, s}; + break; + default: + break; + } + ctx_.reg_[index] = usage; + ctx_.reg_age_[index] = ctx_.age_++; +} + +void wasm_jit_t::use_r(int32_t index, wasm_jit_val_t usage) { + ctx_.reg_[index] = usage; + ctx_.reg_age_[index] = ctx_.age_++; +} + +void wasm_jit_t::release_r(int32_t index) { + ctx_.reg_[index] = JIT_V_INVALID; +} + +int32_t wasm_jit_t::alloc_stk() { + int stack_size = ctx_.stack_valid_.size(); + for (int i = (int)(num_locals_ + 6); i < stack_size; i++) { + if (ctx_.stack_valid_[i] == false) { + ctx_.stack_valid_[i] = true; + return i; + } + } + // grow stack + ctx_.stack_valid_.push_back(false); + // new stack_size is stack_size +1 + // and we need sub rsp, 8*(stack_size-1) (rbp is saved) + uint32_t new_rsp_sub = 8 * ((stack_size + 1) - 1); + if (new_rsp_sub % 16 == 8) { + new_rsp_sub += 8; + } + rsp_sub_ = std::max(rsp_sub_, new_rsp_sub); + return stack_size; +} + +void wasm_jit_t::release_stk(int32_t index) { + ctx_.stack_valid_[index] = false; +} + +void wasm_jit_t::acquire_stk(int32_t index) { + ctx_.stack_valid_[index] = true; +} + +wasm_jit_loc_t wasm_jit_t::peek_wasm_stk(uint32_t depth) { + return ctx_.stack_loc_[ctx_.stack_loc_.size() - depth - 1]; +} + +wasm_jit_loc_t wasm_jit_t::pop_wasm_stk() { + wasm_jit_loc_t result = ctx_.stack_loc_.back(); + ctx_.stack_loc_.pop_back(); + return result; +} + +void wasm_jit_t::rbp_load_r(int32_t index, int32_t r, uint8_t type) { + if (type != WASM_TYPE_F64) { + if (type != WASM_TYPE_I32) { + mov(to_xbyak_r64(r), qword[rbp - (index * 8)]); + } else { + mov(to_xbyak_r32(r), dword[rbp - (index * 8)]); + } + } else { + movsd(to_xbyak_xmm(r), qword[rbp - (index * 8)]); + } + release_stk(index); +} + +void wasm_jit_t::rbp_save_r(int32_t index, int32_t r) { + if (r < reg::xmm0) { + mov(qword[rbp - (index * 8)], to_xbyak_r64(r)); + } else { + movsd(qword[rbp - (index * 8)], to_xbyak_xmm(r)); + } + acquire_stk(index); +} + +int32_t wasm_jit_t::pop_r(uint8_t type) { + wasm_jit_loc_t loc = pop_wasm_stk(); + if (loc.type == reg::in_reg) { + use_r(loc.index, JIT_V_INTER); + return loc.index; + } + int32_t r = alloc_r(JIT_V_INTER, type); + rbp_load_r(loc.index, r, type); + return r; +} + +void wasm_jit_t::pop_r(int32_t index, uint8_t type) { + wasm_jit_loc_t loc = peek_wasm_stk(0); + if (loc.type == reg::in_reg && loc.index == index) { + pop_wasm_stk(); + use_r(loc.index, JIT_V_INTER); + return; + } + acquire_r(index, JIT_V_INTER); + // target may be moved + loc = pop_wasm_stk(); + if (loc.type == reg::in_reg) { + if (type != WASM_TYPE_F64) { + if (type != WASM_TYPE_I32) { + mov(to_xbyak_r64(index), to_xbyak_r64(loc.index)); + } else { + mov(to_xbyak_r32(index), to_xbyak_r32(loc.index)); + } + } else { + movsd(to_xbyak_xmm(index), to_xbyak_xmm(loc.index)); + } + release_r(loc.index); + return; + } + rbp_load_r(loc.index, index, type); +} + +int32_t wasm_jit_t::pop_binop_r32_r32(oo_op_t binop) { + wasm_jit_loc_t a_loc = peek_wasm_stk(1); + int32_t a; + if (a_loc.type == reg::on_stack) { + // move a to register and check b's location + a = alloc_r(JIT_V_INTER, WASM_TYPE_I32); + rbp_load_r(a_loc.index, a, WASM_TYPE_I32); + } else { + // no register allocation needed + a = a_loc.index; + use_r(a, JIT_V_INTER); + } + wasm_jit_loc_t b_loc = pop_wasm_stk(); + pop_wasm_stk(); + if (b_loc.type == reg::in_reg) { + // ra = op(ra, rb) + (this->*binop)(to_xbyak_r32(a), to_xbyak_r32(b_loc.index)); + release_r(b_loc.index); + } else { + // ra = op(ra, mb) + (this->*binop)(to_xbyak_r32(a), dword[rbp - (b_loc.index * 8)]); + release_stk(b_loc.index); + } + return a; +} + +int32_t wasm_jit_t::pop_binop_xmm_xmm(xo_op_t binop) { + wasm_jit_loc_t a_loc = peek_wasm_stk(1); + int32_t a; + if (a_loc.type == reg::on_stack) { + // move a to register and check b's location + a = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + rbp_load_r(a_loc.index, a, WASM_TYPE_F64); + } else { + // no register allocation needed + a = a_loc.index; + use_r(a, JIT_V_INTER); + } + wasm_jit_loc_t b_loc = pop_wasm_stk(); + pop_wasm_stk(); + if (b_loc.type == reg::in_reg) { + // ra = op(ra, rb) + (this->*binop)(to_xbyak_xmm(a), to_xbyak_xmm(b_loc.index)); + release_r(b_loc.index); + } else { + // ra = op(ra, mb) + (this->*binop)(to_xbyak_xmm(a), dword[rbp - (b_loc.index * 8)]); + release_stk(b_loc.index); + } + return a; +} + +void wasm_jit_t::push_r(int32_t index) { + ctx_.stack_loc_.push_back({reg::in_reg, index}); + ctx_.reg_[index] = JIT_V_STACK(ctx_.stack_loc_.size() - 1); +} + +int32_t wasm_jit_t::alloc_special(wasm_jit_type_t t, size_t off) { + for (int32_t i = 0; i < reg::num_r; i++) { + if (ctx_.reg_[i].type == t) { + return i; + } + } + int32_t r = alloc_r({t, 0}, WASM_TYPE_I64); + emit_mov_r_rip(r, off); + return r; +} + +int32_t wasm_jit_t::alloc_global_base() { + return alloc_special(wasm_jit_type_t::GLOBAL_BASE, global_off); +} + +int32_t wasm_jit_t::alloc_memory_base() { + return alloc_special(wasm_jit_type_t::MEMORY_BASE, memory_off); +} + +int32_t wasm_jit_t::alloc_memory_size() { + return alloc_special(wasm_jit_type_t::MEMORY_SIZE, memory_size_off); +} + +void wasm_jit_t::emit_lea_r_rip(int32_t r, size_t dest_offset) { + size_t pos = getSize(); + lea(to_xbyak_r64(r), ptr[rip - 0x12345678]); + size_t src_offset = getSize(); + setSize(pos); + lea(to_xbyak_r64(r), ptr[rip - (int32_t)(src_offset - dest_offset)]); + if (getSize() != src_offset) { + throw std::runtime_error("Generated wrong rip addressing LEA"); + } +} + +void wasm_jit_t::emit_mov_r_rip(int32_t r, size_t dest_offset) { + size_t pos = getSize(); + mov(to_xbyak_r64(r), ptr[rip - 0x12345678]); + size_t src_offset = getSize(); + setSize(pos); + mov(to_xbyak_r64(r), ptr[rip - (int32_t)(src_offset - dest_offset)]); + if (getSize() != src_offset) { + throw std::runtime_error("Generated wrong rip addressing MOV"); + } +} + +void wasm_jit_t::emit_unreachable() { + ud2(); +} + +void wasm_jit_t::emit_nop() {} + +void wasm_jit_t::emit_drop() { + wasm_jit_loc_t loc = pop_wasm_stk(); + if (loc.type == reg::in_reg) { + release_r(loc.index); + } else { + release_stk(loc.index); + } +} + +void wasm_jit_t::emit_select() { + int32_t c = pop_r(WASM_TYPE_I32); + int32_t b = pop_r(WASM_TYPE_I32); + int32_t a = pop_r(WASM_TYPE_I32); + test(to_xbyak_r32(c), to_xbyak_r32(c)); + mov(to_xbyak_r32(c), to_xbyak_r32(b)); + cmovne(to_xbyak_r32(c), to_xbyak_r32(a)); + release_r(a); + release_r(b); + push_r(c); +} + +void wasm_jit_t::emit_local_get() { + uint32_t idx = read_u32leb(&buf_); + uint8_t type = local_types_[idx]; + wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx]; + if (local_loc->type == reg::in_reg) { + // r -> (m, r) + rbp_save_r(idx + 6, local_loc->index); + push_r(local_loc->index); + *local_loc = {reg::on_stack, (int32_t)idx + 6}; + return; + } + // m -> (m, r) + int32_t r = alloc_r(JIT_V_INTER, type); + rbp_load_r(local_loc->index, r, type); + push_r(r); +} + +void wasm_jit_t::emit_local_set() { + uint32_t idx = read_u32leb(&buf_); + uint8_t type = local_types_[idx]; + wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx]; + wasm_jit_loc_t stack_loc = pop_wasm_stk(); + if (local_loc->type == reg::in_reg) { + if (stack_loc.type == reg::in_reg) { + // r -> r + use_r(stack_loc.index, JIT_V_LOCAL(idx)); + release_r(local_loc->index); + local_loc->index = stack_loc.index; + } else { + // m -> r + rbp_load_r(stack_loc.index, local_loc->index, type); + } + return; + } + if (stack_loc.type == reg::in_reg) { + // r -> m + rbp_save_r(local_loc->index, stack_loc.index); + release_r(stack_loc.index); + } else { + // m -> m, move local to r + int32_t r = alloc_r(JIT_V_LOCAL(idx), type); + rbp_load_r(stack_loc.index, r, type); + *local_loc = {reg::on_stack, r}; + } +} + +void wasm_jit_t::emit_local_tee() { + uint32_t idx = read_u32leb(&buf_); + uint8_t type = local_types_[idx]; + wasm_jit_loc_t* local_loc = &ctx_.local_loc_[idx]; + wasm_jit_loc_t stack_loc = peek_wasm_stk(0); + if (local_loc->type == reg::in_reg) { + if (stack_loc.type == reg::in_reg) { + // r -> r + if (type != WASM_TYPE_F64) { + mov(to_xbyak_r64(local_loc->index), to_xbyak_r64(stack_loc.index)); + } else { + mov(to_xbyak_xmm(local_loc->index), to_xbyak_xmm(stack_loc.index)); + } + } else { + // m -> r, need to remark stack as valid + rbp_load_r(stack_loc.index, local_loc->index, type); + acquire_stk(stack_loc.index); + } + return; + } + if (stack_loc.type == reg::in_reg) { + // r -> m + rbp_save_r(local_loc->index, stack_loc.index); + } else { + // m -> m, move local to r, and need to remark stack as valid + int32_t r = alloc_r(JIT_V_LOCAL(idx), type); + rbp_load_r(stack_loc.index, r, type); + acquire_stk(stack_loc.index); + *local_loc = {reg::on_stack, r}; + } +} + +// globals are always in memory +void wasm_jit_t::emit_global_get() { + uint32_t idx = read_u32leb(&buf_); + uint8_t type = mod_->globals_[idx].type_.type_; + int32_t r = alloc_global_base(); + if (type != WASM_TYPE_F64) { + if (type != WASM_TYPE_I32) { + mov(to_xbyak_r64(r), qword[to_xbyak_r64(r) + (idx * 8)]); + push_r(r); + } else { + mov(to_xbyak_r32(r), dword[to_xbyak_r64(r) + (idx * 8)]); + push_r(r); + } + } else { + int32_t s = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + movsd(to_xbyak_xmm(s), qword[to_xbyak_r64(r) + (idx * 8)]); + push_r(s); + release_r(r); + } +} + +void wasm_jit_t::emit_global_set() { + uint32_t idx = read_u32leb(&buf_); + uint8_t type = mod_->globals_[idx].type_.type_; + int32_t r = alloc_global_base(); + // load global base must happen before here or stack loc will change + wasm_jit_loc_t stack_loc = pop_wasm_stk(); + int32_t s; + if (stack_loc.type == reg::in_reg) { + // r -> m + s = stack_loc.index; + } else { + // m -> m + s = alloc_r(JIT_V_INTER, type); + rbp_load_r(stack_loc.index, s, type); + } + if (type != WASM_TYPE_F64) { + if (type != WASM_TYPE_I32) { + mov(qword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_r64(s)); + } else { + mov(dword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_r32(s)); + } + } else { + movsd(qword[to_xbyak_r64(r) + (idx * 8)], to_xbyak_xmm(s)); + } + release_r(s); +} + +void wasm_jit_t::emit_i32_load() { + read_u32leb(&buf_); + uint32_t addend = read_u32leb(&buf_); + uint32_t v_size = 4; + switch (opcode_) { + case WASM_OP_I32_LOAD16_S: + case WASM_OP_I32_LOAD16_U: + v_size = 2; + break; + case WASM_OP_I32_LOAD8_S: + case WASM_OP_I32_LOAD8_U: + v_size = 1; + break; + default: + break; + } + int32_t offset = pop_r(WASM_TYPE_I32); + int32_t m = alloc_memory_base(); + Xbyak::RegExp e; + if (enable_check_ == true) { + int32_t mem_size = alloc_memory_size(); + inLocalLabel(); + cmp(to_xbyak_r32(mem_size), addend); + jae(".L0"); + call("trap"); + L(".L0"); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L1"); + call("trap"); + L(".L1"); + add(to_xbyak_r32(offset), addend); + push(to_xbyak_r64(offset)); + add(to_xbyak_r32(offset), v_size); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L2"); + call("trap"); + L(".L2"); + outLocalLabel(); + pop(to_xbyak_r64(offset)); + e = to_xbyak_r64(m) + to_xbyak_r64(offset); + } else { + e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend; + } + switch (opcode_) { + case WASM_OP_I32_LOAD16_S: + movsx(to_xbyak_r32(offset), word[e]); + break; + case WASM_OP_I32_LOAD16_U: + mov(to_xbyak_r16(offset), word[e]); + and_(to_xbyak_r32(offset), 0xFFFF); + break; + case WASM_OP_I32_LOAD8_S: + movsx(to_xbyak_r32(offset), byte[e]); + break; + case WASM_OP_I32_LOAD8_U: + mov(to_xbyak_r8(offset), byte[e]); + and_(to_xbyak_r32(offset), 0xFF); + break; + default: + mov(to_xbyak_r32(offset), dword[e]); + break; + } + push_r(offset); +} + +void wasm_jit_t::emit_f64_load() { + read_u32leb(&buf_); + uint32_t addend = read_u32leb(&buf_); + int32_t xmm = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + int32_t offset = pop_r(WASM_TYPE_I32); + int32_t m = alloc_memory_base(); + Xbyak::RegExp e; + if (enable_check_ == true) { + int32_t mem_size = alloc_memory_size(); + inLocalLabel(); + cmp(to_xbyak_r32(mem_size), addend); + jae(".L0"); + call("trap"); + L(".L0"); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L1"); + call("trap"); + L(".L1"); + add(to_xbyak_r32(offset), addend); + push(to_xbyak_r64(offset)); + add(to_xbyak_r32(offset), sizeof(double)); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L2"); + call("trap"); + L(".L2"); + outLocalLabel(); + pop(to_xbyak_r64(offset)); + e = to_xbyak_r64(m) + to_xbyak_r64(offset); + } else { + e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend; + } + movsd(to_xbyak_xmm(xmm), qword[e]); + push_r(xmm); + release_r(offset); +} + +void wasm_jit_t::emit_i32_store() { + read_u32leb(&buf_); + uint32_t addend = read_u32leb(&buf_); + uint32_t v_size = 4; + switch (opcode_) { + case WASM_OP_I32_STORE16: + v_size = 2; + break; + case WASM_OP_I32_STORE8: + v_size = 1; + break; + default: + break; + } + int32_t v = pop_r(WASM_TYPE_I32); + int32_t offset = pop_r(WASM_TYPE_I32); + int32_t m = alloc_memory_base(); + Xbyak::RegExp e; + int32_t mem_size; + if (enable_check_ == true) { + mem_size = alloc_memory_size(); + inLocalLabel(); + cmp(to_xbyak_r32(mem_size), addend); + jae(".L0"); + call("trap"); + L(".L0"); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L1"); + call("trap"); + L(".L1"); + add(to_xbyak_r32(offset), addend); + push(to_xbyak_r64(offset)); + add(to_xbyak_r32(offset), v_size); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L2"); + call("trap"); + L(".L2"); + outLocalLabel(); + pop(to_xbyak_r64(offset)); + e = to_xbyak_r64(m) + to_xbyak_r64(offset); + } else { + e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend; + } + switch (opcode_) { + case WASM_OP_I32_STORE16: + mov(word[e], to_xbyak_r16(v)); + break; + case WASM_OP_I32_STORE8: + mov(byte[e], to_xbyak_r8(v)); + break; + default: + mov(dword[e], to_xbyak_r32(v)); + break; + } + release_r(offset); + release_r(v); +} + +void wasm_jit_t::emit_f64_store() { + read_u32leb(&buf_); + uint32_t addend = read_u32leb(&buf_); + int32_t v = pop_r(WASM_TYPE_F64); + int32_t offset = pop_r(WASM_TYPE_I32); + int32_t m = alloc_memory_base(); + Xbyak::RegExp e; + int32_t mem_size; + if (enable_check_ == true) { + mem_size = alloc_memory_size(); + inLocalLabel(); + cmp(to_xbyak_r32(mem_size), addend); + jae(".L0"); + call("trap"); + L(".L0"); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L1"); + call("trap"); + L(".L1"); + add(to_xbyak_r32(offset), addend); + push(to_xbyak_r64(offset)); + add(to_xbyak_r32(offset), sizeof(double)); + cmp(to_xbyak_r32(mem_size), to_xbyak_r32(offset)); + jae(".L2"); + call("trap"); + L(".L2"); + outLocalLabel(); + pop(to_xbyak_r64(offset)); + movsxd(to_xbyak_r64(offset), to_xbyak_r32(offset)); + e = to_xbyak_r64(m) + to_xbyak_r64(offset); + } else { + e = to_xbyak_r64(m) + to_xbyak_r64(offset) + (int32_t)addend; + } + movsd(qword[e], to_xbyak_xmm(v)); + release_r(offset); + release_r(v); +} + +void wasm_jit_t::emit_i32_numeric() { + static o_op_t setcc[] = {&wasm_jit_t::sete, &wasm_jit_t::setne, + &wasm_jit_t::setl, &wasm_jit_t::setb, + &wasm_jit_t::setg, &wasm_jit_t::seta, + &wasm_jit_t::setle, &wasm_jit_t::setbe, + &wasm_jit_t::setge, &wasm_jit_t::setae}; + static oo_op_t numeric[] = { + &wasm_jit_t::add, &wasm_jit_t::sub, nullptr, nullptr, + nullptr, nullptr, nullptr, &wasm_jit_t::and_, + &wasm_jit_t::or_, &wasm_jit_t::xor_}; + int32_t b; + int32_t a; + switch (opcode_) { + case WASM_OP_I32_EQZ: + b = pop_r(WASM_TYPE_I32); + test(to_xbyak_r32(b), to_xbyak_r32(b)); + sete(to_xbyak_r8(b)); + movsx(to_xbyak_r32(b), to_xbyak_r8(b)); + push_r(b); + break; + case WASM_OP_I32_EQ: + case WASM_OP_I32_NE: + case WASM_OP_I32_LT_S: + case WASM_OP_I32_LT_U: + case WASM_OP_I32_GT_S: + case WASM_OP_I32_GT_U: + case WASM_OP_I32_LE_S: + case WASM_OP_I32_LE_U: + case WASM_OP_I32_GE_S: + case WASM_OP_I32_GE_U: + a = pop_binop_r32_r32(static_cast<oo_op_t>(&wasm_jit_t::cmp)); + (this->*setcc[opcode_ - WASM_OP_I32_EQ])(to_xbyak_r8(a)); + movsx(to_xbyak_r32(a), to_xbyak_r8(a)); + push_r(a); + break; + case WASM_OP_I32_CLZ: + // https://stackoverflow.com/questions/9353973/implementation-of-builtin-clz + inLocalLabel(); + b = pop_r(WASM_TYPE_I32); + test(to_xbyak_r32(b), to_xbyak_r32(b)); + je(".clz_zero"); + bsr(to_xbyak_r32(b), to_xbyak_r32(b)); + xor_(to_xbyak_r32(b), 31); + jmp(".clz_done"); + L(".clz_zero"); + mov(to_xbyak_r32(b), 32); + L(".clz_done"); + push_r(b); + outLocalLabel(); + break; + case WASM_OP_I32_CTZ: + inLocalLabel(); + b = pop_r(WASM_TYPE_I32); + test(to_xbyak_r32(b), to_xbyak_r32(b)); + je(".ctz_zero"); + bsf(to_xbyak_r32(b), to_xbyak_r32(b)); + jmp(".ctz_done"); + L(".ctz_zero"); + mov(to_xbyak_r32(b), 32); + L(".ctz_done"); + push_r(b); + outLocalLabel(); + push_r(b); + break; + case WASM_OP_I32_POPCNT: + b = pop_r(WASM_TYPE_I32); + popcnt(to_xbyak_r32(b), to_xbyak_r32(b)); + push_r(b); + break; + case WASM_OP_I32_ADD: + case WASM_OP_I32_SUB: + case WASM_OP_I32_AND: + case WASM_OP_I32_OR: + case WASM_OP_I32_XOR: + a = pop_binop_r32_r32(numeric[opcode_ - WASM_OP_I32_ADD]); + push_r(a); + break; + case WASM_OP_I32_MUL: + pop_r(reg::rdx, WASM_TYPE_I32); + pop_r(reg::rax, WASM_TYPE_I32); + imul(edx); + release_r(reg::rdx); + push_r(reg::rax); + break; + case WASM_OP_I32_DIV_S: + acquire_r(reg::rdx, JIT_V_INTER); + b = pop_r(WASM_TYPE_I32); + pop_r(reg::rax, WASM_TYPE_I32); + if (enable_check_ == true) { + // see i32_div_s() at weerun_inst.cpp:372 + inLocalLabel(); + test(to_xbyak_r32(b), to_xbyak_r32(b)); + jne(".L0"); + call("trap"); + L(".L0"); + cmp(eax, 0x80000000); + jne(".L1"); + cmp(to_xbyak_r32(b), 0xffffffff); + jne(".L1"); + call("trap"); + L(".L1"); + outLocalLabel(); + } + cdq(); + idiv(to_xbyak_r32(b)); + release_r(b); + release_r(reg::rdx); + push_r(reg::rax); + break; + case WASM_OP_I32_DIV_U: + acquire_r(reg::rdx, JIT_V_INTER); + b = pop_r(WASM_TYPE_I32); + pop_r(reg::rax, WASM_TYPE_I32); + if (enable_check_ == true) { + // see i32_div_s() at weerun_inst.cpp:372 + inLocalLabel(); + test(to_xbyak_r32(b), to_xbyak_r32(b)); + jne(".L0"); + call("trap"); + L(".L0"); + outLocalLabel(); + } + xor_(rdx, rdx); + div(to_xbyak_r32(b)); + release_r(b); + release_r(reg::rdx); + push_r(reg::rax); + break; + case WASM_OP_I32_REM_S: + inLocalLabel(); + acquire_r(reg::rdx, JIT_V_INTER); + b = pop_r(WASM_TYPE_I32); + pop_r(reg::rax, WASM_TYPE_I32); + if (enable_check_ == true) { + // see i32_div_s() at weerun_inst.cpp:372 + test(to_xbyak_r32(b), to_xbyak_r32(b)); + jne(".L0"); + call("trap"); + L(".L0"); + cmp(eax, 0x80000000); + jne(".L1"); + cmp(to_xbyak_r32(b), 0xffffffff); + jne(".L1"); + xor_(rdx, rdx); + jmp(".L2"); + } + L(".L1"); + cdq(); + idiv(to_xbyak_r32(b)); + L(".L2"); + release_r(b); + release_r(reg::rax); + push_r(reg::rdx); + outLocalLabel(); + break; + case WASM_OP_I32_REM_U: + acquire_r(reg::rdx, JIT_V_INTER); + b = pop_r(WASM_TYPE_I32); + pop_r(reg::rax, WASM_TYPE_I32); + if (enable_check_ == true) { + // see i32_div_s() at weerun_inst.cpp:372 + inLocalLabel(); + test(to_xbyak_r64(b), to_xbyak_r64(b)); + jne(".L0"); + call("trap"); + L(".L0"); + outLocalLabel(); + } + xor_(rdx, rdx); + div(to_xbyak_r32(b)); + release_r(b); + release_r(reg::rax); + push_r(reg::rdx); + break; + case WASM_OP_I32_EXTEND16_S: + b = pop_r(WASM_TYPE_I32); + movsx(to_xbyak_r32(b), to_xbyak_r16(b)); + push_r(b); + break; + case WASM_OP_I32_EXTEND8_S: + b = pop_r(WASM_TYPE_I32); + movsx(to_xbyak_r32(b), to_xbyak_r8(b)); + push_r(b); + break; + default: + throw std::runtime_error("Opcode not implemented"); + } +} + +void wasm_jit_t::emit_i32_shift() { + static or8_op_t shift[] = {&wasm_jit_t::shl, &wasm_jit_t::sar, + &wasm_jit_t::shr, &wasm_jit_t::rol, + &wasm_jit_t::ror}; + pop_r(reg::rcx, WASM_TYPE_I32); + and_(ecx, 0x1F); + int32_t a = pop_r(WASM_TYPE_I32); + (this->*shift[opcode_ - WASM_OP_I32_SHL])(to_xbyak_r32(a), cl); + push_r(a); + release_r(reg::rcx); +} + +void wasm_jit_t::emit_i32_const() { + uint32_t x = read_i32leb(&buf_); + int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_I32); + mov(to_xbyak_r32(r), x); + push_r(r); +} + +void wasm_jit_t::emit_call_internal(wasm_func_decl_t* sig, + int is_direct, + int index) { + int num_r64 = 0; + int num_f64 = 0; + int num_stack_r64 = 0; + int num_stack_f64 = 0; + int num_args = sig->args_.size(); + int32_t arg_size = 0; + for (uint8_t arg : sig->args_) { + if (arg != WASM_TYPE_F64) { + if (num_r64 < 6) { + num_r64++; + } else { + num_stack_r64++; + } + } else { + if (num_f64 < 8) { + num_f64++; + } else { + num_stack_f64++; + } + } + } + for (int32_t r = reg::rax; r < reg::rbx; r++) { + acquire_r(r, JIT_V_INVALID); + } + for (int32_t r = reg::xmm0; r < reg::num_r; r++) { + acquire_r(r, JIT_V_INVALID); + } + if (is_direct != 1) { + pop_r(reg::r10, WASM_TYPE_I32); + if (enable_check_ == true) { + // check function type + inLocalLabel(); + emit_mov_r_rip(reg::rax, table_size_off); + cmp(r10, rax); + jb(".L0"); + call("trap"); + L(".L0"); + shl(r10, 1); + emit_mov_r_rip(reg::rax, table_off); + mov(r11, qword[rax + r10 * 8]); + cmp(r11, index); + je(".L1"); + call("trap"); + L(".L1"); + outLocalLabel(); + } else { + shl(r10, 1); + } + } + arg_size = num_stack_f64 + num_stack_r64; + if (arg_size % 2 == 1) { + sub(rsp, 0x8); + arg_size++; + } + for (int i = num_args - 1; i >= 0; i--) { + if (sig->args_[i] != WASM_TYPE_F64) { + if (num_stack_r64 > 0) { + wasm_jit_loc_t loc = pop_wasm_stk(); + if (loc.type == reg::in_reg) { + push(to_xbyak_r64(loc.index)); + release_r(loc.index); + } else { + rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64); + push(to_xbyak_r64(reg::rax)); + } + num_stack_r64--; + } else { + num_r64--; + pop_r(sysv_args[num_r64], WASM_TYPE_I64); + } + } else { + if (num_stack_f64 > 0) { + wasm_jit_loc_t loc = pop_wasm_stk(); + if (loc.type == reg::in_reg) { + sub(rsp, 0x8); + movsd(qword[rsp], to_xbyak_xmm(loc.index)); + release_r(loc.index); + } else { + rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64); + push(to_xbyak_r64(reg::rax)); + } + num_stack_f64--; + } else { + num_f64--; + pop_r(reg::xmm0 + num_f64, WASM_TYPE_F64); + } + } + } + if (is_direct == 1) { + std::string f_label = "F" + std::to_string(index); + call(f_label); + } else { + emit_mov_r_rip(reg::rax, table_off); + call(qword[rax + r10 * 8 + 8]); + } + if (arg_size != 0) { + add(rsp, arg_size * 8); + } + if (sig->ret_.empty() == false) { + if (sig->ret_[0] != WASM_TYPE_F64) { + push_r(reg::rax); + } else { + push_r(reg::xmm0); + } + } +} + +void wasm_jit_t::emit_call() { + uint32_t funcidx = read_u32leb(&buf_); + wasm_func_t* f = &mod_->funcs_[funcidx]; + emit_call_internal(f->sig_, 1, funcidx); +} + +void wasm_jit_t::emit_call_indirect() { + read_u32leb(&buf_); + uint32_t typeidx = read_u32leb(&buf_); + emit_call_internal(&mod_->sigs_[typeidx], 0, typeidx); +} + +void wasm_jit_t::emit_pop_result() { + if (f_->sig_->ret_.empty() == false) { + if (f_->sig_->ret_[0] != WASM_TYPE_F64) { + pop_r(reg::rax, f_->sig_->ret_[0]); + } else { + pop_r(reg::xmm0, f_->sig_->ret_[0]); + } + } +} + +void wasm_jit_t::emit_return() { + emit_pop_result(); + jmp("F" + std::to_string(funcidx_) + "E", T_NEAR); +} + +void wasm_jit_t::emit_block() { + read_u8(&buf_); + if (opcode_ == WASM_OP_LOOP) { + block_stack_.push_back({1, next_bi_, ctx_}); + L("F" + std::to_string(funcidx_) + "L" + std::to_string(next_bi_++)); + } else { + block_stack_.push_back({0, next_bi_}); + next_bi_++; + } +} + +void wasm_jit_t::emit_end() { + block_t* b = &block_stack_.back(); + wasm_jit_ctx_t saved_ctx = ctx_; + std::string label("F" + std::to_string(funcidx_) + "L" + + std::to_string(b->index)); + std::string end_label(label + "E"); + int num_brs = b->br_ctxs.size(); + if (num_brs > 0) { + jmp(end_label, T_NEAR); + for (int i = 0; i < num_brs; i++) { + L(label + "T" + std::to_string(i)); + if (b->loop == 0) { + restore_state(&b->br_ctxs[i], &ctx_); + // let last one fall through + if (i < num_brs - 1) { + jmp(end_label, T_NEAR); + } + } else { + restore_state(&b->br_ctxs[i], &b->saved_ctx); + jmp(label, T_NEAR); + } + ctx_ = saved_ctx; + } + } + L(end_label); + block_stack_.pop_back(); + if (block_stack_.empty() == true) { + emit_pop_result(); + stop_ = 1; + return; + } +} + +void wasm_jit_t::emit_br() { + uint32_t depth = read_u32leb(&buf_); + block_t* b = (&block_stack_.back()) - depth; + uint32_t t = b->br_ctxs.size(); + jmp("F" + std::to_string(funcidx_) + "L" + std::to_string(b->index) + "T" + + std::to_string(t), + T_NEAR); + b->br_ctxs.push_back(ctx_); +} + +void wasm_jit_t::emit_br_if() { + uint32_t depth = read_u32leb(&buf_); + block_t* b = (&block_stack_.back()) - depth; + uint32_t t = b->br_ctxs.size(); + int32_t r = pop_r(WASM_TYPE_I32); + test(to_xbyak_r32(r), to_xbyak_r32(r)); + jne("F" + std::to_string(funcidx_) + "L" + std::to_string(b->index) + "T" + + std::to_string(t), + T_NEAR); + b->br_ctxs.push_back(ctx_); +} + +void wasm_jit_t::restore_state(wasm_jit_ctx_t* from, wasm_jit_ctx_t* to) { + wasm_jit_ctx_t tmp_to = *to; // to may be curent context + ctx_ = *from; + int num_wasm_local = ctx_.local_loc_.size(); + int num_wasm_stack = ctx_.stack_loc_.size(); + int num_wasm_stack_dst = tmp_to.stack_loc_.size(); + if (num_wasm_stack < num_wasm_stack_dst) { + throw std::runtime_error("jmp dst have more stack variables"); + } + acquire_r(reg::rax, JIT_V_INVALID); // use rax for m -> m + // save all stack variables + if (num_wasm_stack_dst != 0) { + sub(rsp, num_wasm_stack_dst * 0x8); + } + for (int i = 0; i < num_wasm_stack_dst; i++) { + wasm_jit_loc_t loc = ctx_.stack_loc_[i]; + if (loc.type == reg::in_reg) { + if (loc.index < reg::xmm0) { + // r -> m + mov(qword[rsp + (i * 0x8)], to_xbyak_r64(loc.index)); + } else { + // xmm -> m + movsd(qword[rsp + (i * 0x8)], to_xbyak_xmm(loc.index)); + } + } else { + // m -> m + rbp_load_r(loc.index, reg::rax, WASM_TYPE_I64); + mov(qword[rsp + (i * 0x8)], rax); + } + } + // save all local variables, local variables have fixed stack pos + for (int i = 0; i < num_wasm_local; i++) { + wasm_jit_loc_t loc = ctx_.local_loc_[i]; + if (loc.type == reg::in_reg) { + rbp_save_r(i + 6, loc.index); + } + } + // restore stack variables + for (int i = 0; i < num_wasm_stack_dst; i++) { + wasm_jit_loc_t loc = tmp_to.stack_loc_[i]; + if (loc.type == reg::in_reg) { + if (loc.index < reg::xmm0) { + // r -> m + mov(to_xbyak_r64(loc.index), qword[rsp + (i * 0x8)]); + } else { + // xmm -> m + movsd(to_xbyak_xmm(loc.index), qword[rsp + (i * 0x8)]); + } + } else { + // m -> m + mov(rax, qword[rsp + (i * 0x8)]); + rbp_save_r(loc.index, reg::rax); + } + } + if (num_wasm_stack_dst != 0) { + add(rsp, num_wasm_stack_dst * 0x8); + } + // restore local variables + for (int i = 0; i < num_wasm_local; i++) { + wasm_jit_loc_t loc = tmp_to.local_loc_[i]; + if (loc.type == reg::in_reg) { + rbp_load_r(i + 6, loc.index, local_types_[i]); + } + } + // restore special register values + for (int i = 0; i < reg::num_r; i++) { + switch (tmp_to.reg_[i].type) { + case wasm_jit_type_t::GLOBAL_BASE: + emit_mov_r_rip(i, global_off); + break; + case wasm_jit_type_t::MEMORY_BASE: + emit_mov_r_rip(i, memory_off); + break; + case wasm_jit_type_t::MEMORY_SIZE: + emit_mov_r_rip(i, memory_size_off); + break; + default: + break; + } + } +} + +// reimplement code generated by GDB, I don't know how it works... +void wasm_jit_t::emit_i32_convert() { + inLocalLabel(); + int32_t x0i = pop_r(WASM_TYPE_F64); + int32_t x1i = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + Xbyak::Xmm x0 = to_xbyak_xmm(x0i); + Xbyak::Xmm x1 = to_xbyak_xmm(x1i); + int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_I64); + movapd(x1, x0); + emit_lea_r_rip(r, f64_const_off); + andpd(x1, xword[to_xbyak_r64(r)]); + ucomisd(x1, qword[to_xbyak_r64(r) + 0x10]); + ja(".trap"); + ucomisd(x1, x1); + jp(".trap"); + movsd(x1, qword[to_xbyak_r64(r) + + (opcode_ == WASM_OP_I32_TRUNC_F64_S ? 0x20 : 0x30)]); + comisd(x1, x0); + jae(".trap"); + comisd(x0, qword[to_xbyak_r64(r) + + (opcode_ == WASM_OP_I32_TRUNC_F64_S ? 0x18 : 0x28)]); + jae(".trap"); + if (opcode_ == WASM_OP_I32_TRUNC_F64_S) { + cvttsd2si(to_xbyak_r32(r), x0); + } else { + cvttsd2si(to_xbyak_r64(r), x0); + } + jmp(".safe"); + L(".trap"); + call("trap"); + L(".safe"); + push_r(r); + release_r(x0i); + release_r(x1i); + outLocalLabel(); +} + +void wasm_jit_t::emit_f64_const() { + uint64_t x = *(uint64_t*)(buf_.ptr); + buf_.ptr += sizeof(uint64_t); + int32_t s = alloc_r(JIT_V_INTER, WASM_TYPE_I64); + int32_t r = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + mov(to_xbyak_r64(s), x); + push(to_xbyak_r64(s)); + movsd(to_xbyak_xmm(r), qword[rsp]); + add(rsp, 0x8); + release_r(s); + push_r(r); +} + +void wasm_jit_t::emit_f64_compute() { + static o_op_t setcc[] = {&wasm_jit_t::sete, &wasm_jit_t::setne, + &wasm_jit_t::setb, &wasm_jit_t::seta, + &wasm_jit_t::setbe, &wasm_jit_t::setae}; + static xo_op_t fnumeric[] = {&wasm_jit_t::addsd, &wasm_jit_t::subsd, + &wasm_jit_t::mulsd, &wasm_jit_t::divsd}; + int32_t b; + int32_t a; + int32_t r; + switch (opcode_) { + case WASM_OP_F64_EQ: + case WASM_OP_F64_NE: + case WASM_OP_F64_LT: + case WASM_OP_F64_GT: + case WASM_OP_F64_LE: + case WASM_OP_F64_GE: + b = pop_r(WASM_TYPE_F64); + a = pop_r(WASM_TYPE_F64); + r = alloc_r(JIT_V_INTER, WASM_TYPE_I64); + comisd(to_xbyak_xmm(a), to_xbyak_xmm(b)); + (this->*setcc[opcode_ - WASM_OP_F64_EQ])(to_xbyak_r8(r)); + movsx(to_xbyak_r32(r), to_xbyak_r8(r)); + release_r(b); + release_r(a); + push_r(r); + break; + case WASM_OP_F64_ADD: + case WASM_OP_F64_SUB: + case WASM_OP_F64_MUL: + case WASM_OP_F64_DIV: + a = pop_binop_xmm_xmm(fnumeric[opcode_ - WASM_OP_F64_ADD]); + push_r(a); + break; + case WASM_OP_F64_CONVERT_I32_S: + b = pop_r(WASM_TYPE_I32); + r = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + cvtsi2sd(to_xbyak_xmm(r), to_xbyak_r32(b)); + push_r(r); + release_r(b); + break; + case WASM_OP_F64_CONVERT_I32_U: + b = pop_r(WASM_TYPE_I64); + r = alloc_r(JIT_V_INTER, WASM_TYPE_F64); + mov(to_xbyak_r64(b), to_xbyak_r64(b)); + cvtsi2sd(to_xbyak_xmm(r), to_xbyak_r64(b)); + push_r(r); + release_r(b); + break; + } +} + +void wasm_jit_t::emit_br_table() { + uint32_t num_cases = read_u32leb(&buf_); + std::map<uint32_t, size_t> dst_offsets; // depth -> offset + std::vector<uint32_t> table_offsets; // table element -> offset + inLocalLabel(); + int32_t a = pop_r(WASM_TYPE_I32); + int32_t b = alloc_r(JIT_V_INTER, WASM_TYPE_I64); + mov(to_xbyak_r32(b), num_cases); + cmp(to_xbyak_r32(a), to_xbyak_r32(b)); + // use default case as the last one + cmovae(to_xbyak_r32(a), to_xbyak_r32(b)); + size_t lea_pos = getSize(); + lea(to_xbyak_r64(b), qword[rip + 0x12345678]); + size_t start_offset = getSize(); + movsxd(to_xbyak_r64(a), dword[to_xbyak_r64(b) + to_xbyak_r64(a) * 4]); + add(to_xbyak_r64(a), to_xbyak_r64(b)); + db(0x3e); // disable endbr64 + jmp(to_xbyak_r32(a)); + align(4); + size_t end_offset = getSize(); + setSize(lea_pos); + lea(to_xbyak_r64(b), qword[rip + (int)(end_offset - start_offset)]); + if (getSize() != start_offset) { + throw std::runtime_error("Generated wrong rip addressing LEA"); + } + // alloc space for offsets + table_offsets.resize(num_cases + 1); + setSize(end_offset + 4 * (num_cases + 1)); + // also takes care of default case + for (uint32_t i = 0; i <= num_cases; i++) { + uint32_t depth = read_u32leb(&buf_); + auto result = dst_offsets.find(depth); + if (result == dst_offsets.end()) { + dst_offsets[depth] = getSize(); + table_offsets[i] = getSize(); + block_t* b = (&block_stack_.back()) - depth; + uint32_t t = b->br_ctxs.size(); + std::string jmp_label = "F" + std::to_string(funcidx_) + "L" + + std::to_string(b->index) + "T" + + std::to_string(t); + jmp(jmp_label); + b->br_ctxs.push_back(ctx_); + } else { + table_offsets[i] = result->second; + } + } + size_t inst_end_offset = getSize(); + setSize(end_offset); + for (uint32_t i = 0; i <= num_cases; i++) { + dd((uint32_t)(table_offsets[i] - end_offset)); + } + setSize(inst_end_offset); + release_r(a); + release_r(b); + outLocalLabel(); +} diff --git a/weerun_jit.hpp b/weerun_jit.hpp new file mode 100644 index 0000000..509f02c --- /dev/null +++ b/weerun_jit.hpp @@ -0,0 +1,216 @@ +#pragma once + +#include <array> +#include <map> +#include <utility> +#include <vector> + +#include "weerun.hpp" + +#include <xbyak/xbyak.h> +#include <xbyak/xbyak_bin2hex.h> + +namespace reg { +enum reg { + rax = 0, + rdx = 1, + rcx = 2, + rdi = 3, + rsi = 4, + r8 = 5, + r9 = 6, + r10 = 7, + r11 = 8, + // callee-saved: + rbx = 9, + r12 = 10, + r13 = 11, + r14 = 12, + r15 = 13, + + xmm0 = 14, + xmm1 = 15, + xmm2 = 16, + xmm3 = 17, + xmm4 = 18, + xmm5 = 19, + xmm6 = 20, + xmm7 = 21, + xmm8 = 22, + xmm9 = 23, + xmm10 = 24, + xmm11 = 25, + xmm12 = 26, + xmm13 = 27, + xmm14 = 28, + xmm15 = 29, + + num_r = 30 +}; + +const int32_t in_reg = 0; +const int32_t on_stack = 1; +} // namespace reg + +struct wasm_jit_loc_t { + int32_t type; // 0:in register, 1:on stack + int32_t index; // register index or [rbp-8*index] + + bool operator==(const wasm_jit_loc_t& rhs) { + return type == rhs.type && index == rhs.index; + } +}; + +enum class wasm_jit_type_t : int32_t { + INVALID, + CALLER_DATA, + INTERMEDIATE, + LOCAL_VAL, // index = local variable index + STACK_VAL, // index = stack index + GLOBAL_BASE, + MEMORY_BASE, + MEMORY_SIZE, +}; + +struct wasm_jit_val_t { + wasm_jit_type_t type; + int32_t index; + + bool operator==(const wasm_jit_val_t& rhs) { + return type == rhs.type && index == rhs.index; + } + bool operator!=(const wasm_jit_val_t& rhs) { + return type != rhs.type || index != rhs.index; + } +}; + +struct wasm_jit_ctx_t { + std::array<wasm_jit_val_t, 30> reg_; // reg content + std::array<uint32_t, 30> reg_age_; // reg content + uint32_t age_; + std::vector<uint8_t> stack_valid_; // stack valid? + + std::vector<wasm_jit_loc_t> stack_loc_; // location of wasm stack values + std::vector<wasm_jit_loc_t> local_loc_; // location of wasm local values + + void init(wasm_jit_t* jit, wasm_func_t* f); +}; + +struct wasm_jit_t : public Xbyak::CodeGenerator { + wasm_module_t* mod_; + wasm_instance_t* ins_; + int max_prologue_size_; + bool enable_check_; + std::vector<uint8_t*> f_addr_; + uint8_t* run_fn_; // call helper function + + // current function info + wasm_func_t* f_; + uint32_t funcidx_; + uint32_t num_locals_; + std::vector<uint8_t> local_types_; + uint32_t rsp_sub_; + std::array<uint8_t, 5> used_callee_; + + // decoder info + uint32_t opcode_; + buffer_t buf_; + uint32_t next_bi_; + uint32_t stop_; + + // register allocation context + wasm_jit_ctx_t ctx_; + + // branch info + struct block_t { + uint32_t loop; + uint32_t index; + wasm_jit_ctx_t saved_ctx; // for loop, we need to save context early + std::vector<wasm_jit_ctx_t> br_ctxs; // brs' cpntext + }; + std::vector<block_t> block_stack_; + + wasm_jit_t(uint64_t code_size); + + void compile_instance(wasm_instance_t* ins); + void emit_runtime_functions(); + void compile_function(uint32_t index); + void run_fn(uint32_t index, wasm_value_t* args, wasm_value_t* r); + + Xbyak::Reg64 to_xbyak_r64(int32_t index); + Xbyak::Reg32 to_xbyak_r32(int32_t index); + Xbyak::Reg16 to_xbyak_r16(int32_t index); + Xbyak::Reg8 to_xbyak_r8(int32_t index); + Xbyak::Xmm to_xbyak_xmm(int32_t index); + + int32_t alloc_r(wasm_jit_val_t usage, uint8_t type); + void acquire_r(int32_t index, wasm_jit_val_t usage); + void use_r(int32_t index, wasm_jit_val_t usage); + void release_r(int32_t index); // mark a register as invalid + + int32_t alloc_stk(); + void release_stk(int32_t index); + void acquire_stk(int32_t index); + + inline wasm_jit_loc_t peek_wasm_stk(uint32_t depth); + inline wasm_jit_loc_t pop_wasm_stk(); + + int32_t pop_r(uint8_t type); // pop to a 32bit register + void pop_r(int32_t index, uint8_t type); // pop to the given 32bit register + void push_r(int32_t index); // push a register + + void restore_state(wasm_jit_ctx_t* from, wasm_jit_ctx_t* to); + + typedef void (CodeGenerator::*oo_op_t)(const Xbyak::Operand&, + const Xbyak::Operand&); + typedef void (CodeGenerator::*or8_op_t)(const Xbyak::Operand&, + const Xbyak::Reg8&); + typedef void (CodeGenerator::*o_op_t)(const Xbyak::Operand&); + typedef void (CodeGenerator::*xo_op_t)(const Xbyak::Xmm&, + const Xbyak::Operand&); + + int32_t pop_binop_r32_r32(oo_op_t binop); + int32_t pop_binop_xmm_xmm(xo_op_t binop); + + void rbp_load_r(int32_t index, int32_t r, uint8_t type); + void rbp_save_r(int32_t index, int32_t r); + + int32_t alloc_special(wasm_jit_type_t t, + size_t off); // load global base to a register + int32_t alloc_global_base(); // load global base to a register + int32_t alloc_memory_base(); // load memory base to a register + int32_t alloc_memory_size(); // load memory size to a register + + void emit_lea_r_rip(int32_t r, size_t dest_offset); + void emit_mov_r_rip(int32_t r, size_t dest_offset); + void emit_call_internal(wasm_func_decl_t* sig, int is_direct, int index); + void emit_pop_result(); + + void emit_unreachable(); + void emit_nop(); + void emit_drop(); + void emit_select(); + void emit_local_get(); + void emit_local_set(); + void emit_local_tee(); + void emit_global_get(); + void emit_global_set(); + void emit_i32_load(); + void emit_f64_load(); + void emit_i32_store(); + void emit_f64_store(); + void emit_i32_const(); + void emit_f64_const(); + void emit_i32_numeric(); + void emit_i32_shift(); + void emit_i32_convert(); + void emit_f64_compute(); + void emit_call(); + void emit_call_indirect(); + void emit_return(); + void emit_block(); + void emit_end(); + void emit_br(); + void emit_br_if(); + void emit_br_table(); +}; diff --git a/weerun_parse.cpp b/weerun_parse.cpp new file mode 100644 index 0000000..2e2a5df --- /dev/null +++ b/weerun_parse.cpp @@ -0,0 +1,394 @@ +#include <algorithm> +#include <csignal> +#include <cstdlib> +#include <cstring> +#include <vector> + +#include "weerun.hpp" +#include "weerun_jit.hpp" + +template <typename T> +T decode(buffer_t* buf); + +template <typename T> +std::vector<T> decode_vector(buffer_t* buf); + +void parse_custom_section(wasm_module_t* module, buffer_t* buf); +void parse_type_section(wasm_module_t* module, buffer_t* buf); +void parse_import_section(wasm_module_t* module, buffer_t* buf); +void parse_function_section(wasm_module_t* module, buffer_t* buf); +void parse_table_section(wasm_module_t* module, buffer_t* buf); +void parse_memory_section(wasm_module_t* module, buffer_t* buf); +void parse_global_section(wasm_module_t* module, buffer_t* buf); +void parse_export_section(wasm_module_t* module, buffer_t* buf); +void parse_start_section(wasm_module_t* module, buffer_t* buf); +void parse_element_section(wasm_module_t* module, buffer_t* buf); +void parse_code_section(wasm_module_t* module, buffer_t* buf); +void parse_data_section(wasm_module_t* module, buffer_t* buf); + +extern "C" wasm_module_t* parse(buffer_t* buf) { + buf->ptr += 8; // magic and version + wasm_module_t* module = new wasm_module_t(); + module->num_import_funcs_ = 0; + module->have_start_ = false; + while (buf->ptr != buf->end) { + byte type = read_u8(buf); + switch (type) { + case 0: + parse_custom_section(module, buf); + break; + case WASM_SECT_TYPE: + parse_type_section(module, buf); + break; + case WASM_SECT_IMPORT: + parse_import_section(module, buf); + break; + case WASM_SECT_FUNCTION: + parse_function_section(module, buf); + break; + case WASM_SECT_TABLE: + parse_table_section(module, buf); + break; + case WASM_SECT_MEMORY: + parse_memory_section(module, buf); + break; + case WASM_SECT_GLOBAL: + parse_global_section(module, buf); + break; + case WASM_SECT_EXPORT: + parse_export_section(module, buf); + break; + case WASM_SECT_START: + parse_start_section(module, buf); + break; + case WASM_SECT_ELEMENT: + parse_element_section(module, buf); + break; + case WASM_SECT_CODE: + parse_code_section(module, buf); + break; + case WASM_SECT_DATA: + parse_data_section(module, buf); + break; + default: + assert(0); + } + } + return module; +} + +wasm_instance_t* active_instance; +uint32_t jit = 1; + +extern "C" wasm_typed_value_t run(const byte* start, + const byte* end, + uint32_t num_args, + wasm_value_t* args) { + buffer_t onstack_buf = {start, start, end}; + wasm_module_t* module = parse(&onstack_buf); + wasm_instance_t* instance = module->create_instance(); + wasm_value_t result; + if (jit != 0) { + result = + instance->run_jit(std::vector<wasm_value_t>(args, args + num_args)); + } else { + result = instance->run(std::vector<wasm_value_t>(args, args + num_args)); + } + wasm_typed_value_t tr = {module->funcs_[module->main_index_].sig_->ret_[0], + result}; + delete instance; + delete module; + return tr; +} + +void parse_custom_section(wasm_module_t* module, buffer_t* buf) { + (void)module; + uint32_t size = read_u32leb(buf); + const byte* section_end = buf->ptr + size; + std::string name = decode<std::string>(buf); + buf->ptr = section_end; + return; +} + +void parse_type_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + module->sigs_ = decode_vector<wasm_func_decl_t>(buf); +} + +void parse_import_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<wasm_import_decl_t> imports = + decode_vector<wasm_import_decl_t>(buf); + // create imported functions + for (wasm_import_decl_t& imp : imports) { + switch (imp.type_) { + case wasm_import_decl_t::type::FUNCTION: { + std::string name = imp.module_ + "." + imp.name_; + auto result = g_runtime_funcs.find(name); + if (result == g_runtime_funcs.end()) { + std::cout << "error: " << name << " cannot be imported"; + throw std::runtime_error(name + " not found"); + } + wasm_func_t f; + f.sig_ = &module->sigs_[imp.funcindex_]; + f.typeid_ = imp.funcindex_; + f.run_ = result->second.run_; + f.run_jit_ = result->second.run_jit_; + module->funcs_.push_back(f); + module->num_import_funcs_++; + break; + } + default: + break; + } + } +} + +void parse_function_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<uint32_t> funcidxs = decode_vector<uint32_t>(buf); + // create function objects + for (uint32_t func : funcidxs) { + wasm_func_t f; + f.sig_ = &module->sigs_[func]; + f.typeid_ = func; + f.run_ = nullptr; + module->funcs_.push_back(f); + } +} + +void parse_table_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<wasm_table_decl_t> tables = decode_vector<wasm_table_decl_t>(buf); + module->table_ = tables[0]; +} + +void parse_memory_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<wasm_memory_decl_t> memories = + decode_vector<wasm_memory_decl_t>(buf); + module->mem_limits_ = memories[0]; +} + +void parse_global_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + module->globals_ = decode_vector<wasm_global_t>(buf); +} + +void parse_export_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<wasm_export_t> exps = decode_vector<wasm_export_t>(buf); + // we assume that the module only exports a main function + module->main_index_ = exps[0].idx_; +} + +void parse_start_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + module->have_start_ = true; + module->start_index_ = read_u32leb(buf); +} + +void parse_element_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + module->elems_ = decode_vector<wasm_elem_decl_t>(buf); +} + +std::vector<wasm_code_decl_t> decode_vector_code_decl(buffer_t* buf, + wasm_module_t* module); + +void parse_code_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + std::vector<wasm_code_decl_t> codes = decode_vector_code_decl(buf, module); + // start from the first non-imported functions + uint32_t funcidx = module->num_import_funcs_; + for (wasm_code_decl_t& code : codes) { + module->funcs_[funcidx].locals_ = code.locals_; + module->funcs_[funcidx].code_ = code.code_; + funcidx++; + } +} + +void parse_data_section(wasm_module_t* module, buffer_t* buf) { + read_u32leb(buf); + module->datas_ = decode_vector<wasm_data_decl_t>(buf); +} + +wasm_instance_t* wasm_module_t::create_instance() { + wasm_instance_t* instance = new wasm_instance_t(); + instance->module_ = this; + + // initialize memory using data + instance->memory_.resize(mem_limits_.init_ * wasm_page_size, 0); + for (wasm_data_decl_t& data : datas_) { + byte* mem = instance->memory_.data(); + std::memcpy(mem + data.offset_, data.data_.data(), data.data_.size()); + } + + // initialize global variables + instance->globals_.resize(globals_.size()); + for (uint32_t i = 0; i < globals_.size(); i++) { + switch (globals_[i].type_.type_) { + case WASM_TYPE_I32: + instance->globals_[i].val.i32 = globals_[i].val_.i32; + break; + case WASM_TYPE_F64: + instance->globals_[i].val.f64 = globals_[i].val_.f64; + break; + default: + instance->globals_[i].val.ref = globals_[i].val_.ref; + break; + } + } + + // initialize table + instance->table_.resize(table_.init_, nullptr); + for (wasm_elem_decl_t& elem : elems_) { + instance->ensure_table(elem.offset_ + elem.funcidx_.size()); + wasm_func_t** p = &instance->table_[elem.offset_]; + for (uint32_t funcidx : elem.funcidx_) { + *p = &funcs_[funcidx]; + p++; + } + } + instance->jit_table_.resize(instance->table_.size(), {-1, nullptr}); + return instance; +} + +void wasm_instance_t::push_value(wasm_value_t v) { + value_stack_.push_back(v); +} + +wasm_value_t wasm_instance_t::pop_value() { + wasm_value_t result = value_stack_.back(); + value_stack_.pop_back(); + return result; +} + +void wasm_instance_t::branch(uint32_t to_off) { + cur_frame_->pc_.ptr = cur_frame_->pc_.start + to_off; +} + +void wasm_instance_t::push_frame(wasm_func_t* f) { + if (f->run_ != nullptr) { + // runtime functions + f->run_(this); + return; + } + + // create a frame for function f + wasm_stack_frame_t frame; + frame.f_ = f; + + // locals contains arguments and f's own locals + uint32_t num_args = f->sig_->args_.size(); + frame.locals_.resize(num_args); + // move argument from stack + for (int i = num_args - 1; i >= 0; i--) { + frame.locals_[i] = pop_value(); + } + // initialize locals + for (wasm_local_decl_t& local : f->locals_) { + wasm_value_t v; + switch (local.type_) { + case WASM_TYPE_I32: + v.val.i32 = 0; + break; + case WASM_TYPE_F64: + v.val.f64 = 0; + break; + case WASM_TYPE_EXTERNREF: + v.val.ref = nullptr; + } + for (uint32_t i = 0; i < local.count_; i++) { + frame.locals_.push_back(v); + } + } + + // set pc to the start of function bytecode + frame.pc_.start = frame.pc_.ptr = f->code_.data(); + frame.pc_.end = frame.pc_.start + f->code_.size(); + frames_.push_back(frame); + + // update current frame + cur_frame_ = &frames_.back(); +} + +void wasm_instance_t::pop_frame() { + // pop the from when a funtcion reaches the end + frames_.pop_back(); + cur_frame_ = &frames_.back(); +} + +wasm_value_t wasm_instance_t::run(std::vector<wasm_value_t> args) { + if (module_->have_start_ == true) { + run_function(module_->start_index_); + } + // create the frame for main() + for (wasm_value_t& v : args) { + value_stack_.push_back(v); + } + active_instance = this; + run_function(module_->main_index_); + // return the value on stack; + return value_stack_.back(); +} + +wasm_value_t wasm_instance_t::run_jit(std::vector<wasm_value_t> args) { + wasm_jit_t jit(1 << 20); // 1M code size + jit.compile_instance(this); + + active_instance = this; + if (module_->have_start_ == true) { + jit.run_fn(module_->start_index_, nullptr, nullptr); + } + wasm_value_t r; + jit.run_fn(module_->main_index_, args.data(), &r); + return r; +} + +void wasm_instance_t::run_function(uint32_t funcidx) { + trapped = WASM_TRAP_REASON_NOTRAP; + push_frame(&module_->funcs_[funcidx]); + + // start interpretation + while (trapped == WASM_TRAP_REASON_NOTRAP) { + byte opcode = read_u8(&cur_frame_->pc_); + const wasm_inst_desc_t* desc = &g_inst_desc[opcode]; + desc->run(this, opcode); + } + + if (trapped != WASM_TRAP_REASON_FUNCEND) { + std::cout << "!trap" << std::endl; + std::exit(0); + } +} + +void wasm_instance_t::trap(uint32_t reason) { + trapped = reason; +} + +uint32_t wasm_instance_t::read_u32leb() { + return ::read_u32leb(&cur_frame_->pc_); +} + +int32_t wasm_instance_t::read_i32leb() { + return ::read_i32leb(&cur_frame_->pc_); +} + +double wasm_instance_t::read_double() { + double result = *(double*)(cur_frame_->pc_.ptr); + cur_frame_->pc_.ptr += sizeof(double); + return result; +} + +byte wasm_instance_t::read_byte() { + byte result = *(byte*)(cur_frame_->pc_.ptr); + cur_frame_->pc_.ptr += sizeof(byte); + return result; +} + +void wasm_instance_t::ensure_table(uint32_t offset) { + if (table_.size() < offset) { + table_.resize(offset, nullptr); + } +} diff --git a/weerun_runtime.cpp b/weerun_runtime.cpp new file mode 100644 index 0000000..e499670 --- /dev/null +++ b/weerun_runtime.cpp @@ -0,0 +1,300 @@ +#include <cmath> +#include <cstdio> +#include <ctime> +#include <iostream> +#include <map> +#include <string> +#include <unordered_map> +#include <vector> + +#include "weerun.hpp" + +void trap(); + +std::unordered_map<std::string, wasm_rt_func_t> g_runtime_funcs; + +static void weewasm_puti(wasm_instance_t* ins) { + wasm_value_t v = ins->pop_value(); + std::printf("%d", (int32_t)v.val.i32); +} + +static void weewasm_putd(wasm_instance_t* ins) { + wasm_value_t v = ins->pop_value(); + std::printf("%f", v.val.f64); +} + +static void weewasm_puts(wasm_instance_t* ins) { + wasm_value_t size = ins->pop_value(); + wasm_value_t start = ins->pop_value(); + const byte* base = ins->memory_.data() + start.val.i32; + std::cout << std::string(base, base + size.val.i32); +} + +static void weewasm_puti_jit(int32_t v) { + std::printf("%d", v); +} + +static void weewasm_putd_jit(double v) { + std::printf("%f", v); +} + +static void weewasm_puts_jit(uint32_t start, uint32_t size) { + const byte* base = active_instance->memory_.data() + start; + std::cout << std::string(base, base + size); +} + +static inline wasm_key_t convert_key(wasm_externref_t* ref) { + union { + uint64_t i64; + double f64; + void* ptr; + } u; + if (ref == nullptr) { + return {WASM_EXTERN_NULL, 0}; + } + switch (ref->type_) { + case WASM_EXTERN_BOXI32: + u.i64 = ((wasm_e_box_t*)ref)->i32_; + break; + case WASM_EXTERN_BOXF64: + u.f64 = ((wasm_e_box_t*)ref)->f64_; + break; + default: + u.ptr = (void*)ref; + break; + } + return {ref->type_, u.i64}; +} + +static void weewasm_obj_new(wasm_instance_t* ins) { + wasm_value_t v; + v.val.ref = (void*)(new wasm_e_object_t()); + ins->push_value(v); +} + +static void weewasm_obj_box_i32(wasm_instance_t* ins) { + wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32); + wasm_value_t x = ins->pop_value(); + obj->i32_ = (int32_t)x.val.i32; + wasm_value_t v; + v.val.ref = (void*)(obj); + ins->push_value(v); +} + +static void weewasm_obj_box_f64(wasm_instance_t* ins) { + wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64); + wasm_value_t x = ins->pop_value(); + obj->f64_ = x.val.f64; + wasm_value_t v; + v.val.ref = (void*)(obj); + ins->push_value(v); +} + +static void weewasm_obj_get(wasm_instance_t* ins) { + wasm_value_t key = ins->pop_value(); + wasm_value_t o = ins->pop_value(); + if (key.val.ref == nullptr || o.val.ref == nullptr) { + ins->trap(WASM_TRAP_REASON_NULLEXTERNREF); + return; + } + wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref; + if (obj->type_ != WASM_EXTERN_OBJECT) { + ins->trap(WASM_TRAP_REASON_BADOBJECT); + return; + } + wasm_value_t v; + auto result = obj->map_.find(convert_key((wasm_externref_t*)key.val.ref)); + if (result == obj->map_.end()) { + v.val.ref = nullptr; + } else { + v.val.ref = (void*)result->second; + } + ins->push_value(v); + return; +} + +static void weewasm_obj_set(wasm_instance_t* ins) { + wasm_value_t value = ins->pop_value(); + wasm_value_t key = ins->pop_value(); + wasm_value_t o = ins->pop_value(); + if (key.val.ref == nullptr || o.val.ref == nullptr) { + ins->trap(WASM_TRAP_REASON_NULLEXTERNREF); + return; + } + wasm_e_object_t* obj = (wasm_e_object_t*)o.val.ref; + if (obj->type_ != WASM_EXTERN_OBJECT) { + ins->trap(WASM_TRAP_REASON_BADOBJECT); + return; + } + obj->map_[convert_key((wasm_externref_t*)key.val.ref)] = + (wasm_externref_t*)value.val.ref; + return; +} + +static void weewasm_i32_unbox(wasm_instance_t* ins) { + wasm_value_t value = ins->pop_value(); + wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref; + if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) { + ins->trap(WASM_TRAP_REASON_BADOBJECT); + return; + } + wasm_value_t v; + v.val.i32 = (uint32_t)box->i32_; + ins->push_value(v); + return; +} + +static void weewasm_f64_unbox(wasm_instance_t* ins) { + wasm_value_t value = ins->pop_value(); + wasm_e_box_t* box = (wasm_e_box_t*)value.val.ref; + if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) { + ins->trap(WASM_TRAP_REASON_BADOBJECT); + return; + } + wasm_value_t v; + v.val.f64 = box->f64_; + ins->push_value(v); + return; +} + +static void weewasm_obj_eq(wasm_instance_t* ins) { + wasm_value_t rhs = ins->pop_value(); + wasm_value_t lhs = ins->pop_value(); + wasm_value_t v; + v.val.i32 = (convert_key((wasm_externref_t*)lhs.val.ref) == + convert_key((wasm_externref_t*)rhs.val.ref)) + ? 1 + : 0; + ins->push_value(v); +} + +static wasm_e_object_t* weewasm_obj_new_jit() { + return new wasm_e_object_t(); +} + +static wasm_e_box_t* weewasm_obj_box_i32_jit(int32_t v) { + wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXI32); + obj->i32_ = v; + return obj; +} + +static wasm_e_box_t* weewasm_obj_box_f64_jit(double v) { + wasm_e_box_t* obj = new wasm_e_box_t(WASM_EXTERN_BOXF64); + obj->f64_ = v; + return obj; +} + +static wasm_externref_t* weewasm_obj_get_jit(wasm_e_object_t* obj, + wasm_externref_t* key) { + if (key == nullptr || obj == nullptr) { + trap(); + } + if (obj->type_ != WASM_EXTERN_OBJECT) { + trap(); + } + auto result = obj->map_.find(convert_key(key)); + if (result == obj->map_.end()) { + return nullptr; + } + return result->second; +} + +static void weewasm_obj_set_jit(wasm_e_object_t* obj, + wasm_externref_t* key, + wasm_externref_t* value) { + if (key == nullptr || obj == nullptr) { + trap(); + } + if (obj->type_ != WASM_EXTERN_OBJECT) { + trap(); + } + obj->map_[convert_key(key)] = value; +} + +static int32_t weewasm_i32_unbox_jit(wasm_e_box_t* box) { + if (box == nullptr || box->type_ != WASM_EXTERN_BOXI32) { + trap(); + } + return box->i32_; +} + +static double weewasm_f64_unbox_jit(wasm_e_box_t* box) { + if (box == nullptr || box->type_ != WASM_EXTERN_BOXF64) { + trap(); + } + return box->f64_; +} + +static uint32_t weewasm_obj_eq_jit(wasm_externref_t* lhs, + wasm_externref_t* rhs) { + return (convert_key(lhs) == convert_key(rhs)) ? 1 : 0; +} + +extern "C" void init_runtime() { + g_runtime_funcs["weewasm.puti"] = {weewasm_puti, (void*)weewasm_puti_jit}; + g_runtime_funcs["weewasm.putd"] = {weewasm_putd, (void*)weewasm_putd_jit}; + g_runtime_funcs["weewasm.puts"] = {weewasm_puts, (void*)weewasm_puts_jit}; + g_runtime_funcs["weewasm.obj.new"] = {weewasm_obj_new, + (void*)weewasm_obj_new_jit}; + g_runtime_funcs["weewasm.obj.box_i32"] = {weewasm_obj_box_i32, + (void*)weewasm_obj_box_i32_jit}; + g_runtime_funcs["weewasm.obj.box_f64"] = {weewasm_obj_box_f64, + (void*)weewasm_obj_box_f64_jit}; + g_runtime_funcs["weewasm.obj.get"] = {weewasm_obj_get, + (void*)weewasm_obj_get_jit}; + g_runtime_funcs["weewasm.obj.set"] = {weewasm_obj_set, + (void*)weewasm_obj_set_jit}; + g_runtime_funcs["weewasm.i32.unbox"] = {weewasm_i32_unbox, + (void*)weewasm_i32_unbox_jit}; + g_runtime_funcs["weewasm.f64.unbox"] = {weewasm_f64_unbox, + (void*)weewasm_f64_unbox_jit}; + g_runtime_funcs["weewasm.obj.eq"] = {weewasm_obj_eq, + (void*)weewasm_obj_eq_jit}; +} + +static void libc_sin(wasm_instance_t* ins) { + wasm_value_t x = ins->pop_value(); + x.val.f64 = std::sin(x.val.f64); + ins->push_value(x); +} + +static void libc_cos(wasm_instance_t* ins) { + wasm_value_t x = ins->pop_value(); + x.val.f64 = std::cos(x.val.f64); + ins->push_value(x); +} + +static void libc_rand(wasm_instance_t* ins) { + wasm_value_t x; + x.val.i32 = std::rand(); + ins->push_value(x); +} + +static void libc_time(wasm_instance_t* ins) { + wasm_value_t x; + x.val.i32 = std::time(nullptr); + ins->push_value(x); +} + +static void libc_srand(wasm_instance_t* ins) { + wasm_value_t x = ins->pop_value(); + std::srand(x.val.i32); +} + +int32_t libc_time_jit() { + return std::time(nullptr); +} + +extern "C" void init_libc_runtime() { + static std::vector<wasm_func_decl_t> func_decls; + func_decls.push_back({{WASM_TYPE_F64}, {WASM_TYPE_F64}}); + func_decls.push_back({{}, {WASM_TYPE_I32}}); + func_decls.push_back({{WASM_TYPE_I32}, {}}); + g_runtime_funcs["libc.sin"] = { + libc_sin, (void*)static_cast<double (*)(double)>(std::sin)}; + g_runtime_funcs["libc.cos"] = { + libc_cos, (void*)static_cast<double (*)(double)>(std::cos)}; + g_runtime_funcs["libc.rand"] = {libc_rand, (void*)std::rand}; + g_runtime_funcs["libc.time"] = {libc_time, (void*)libc_time_jit}; + g_runtime_funcs["libc.srand"] = {libc_srand, (void*)std::srand}; +} diff --git a/weewasm.h b/weewasm.h new file mode 100644 index 0000000..c8c2305 --- /dev/null +++ b/weewasm.h @@ -0,0 +1,102 @@ +#pragma once + +#define WASM_MAGIC 0x6d736100u +#define WASM_VERSION 1 + +// Section constants +#define WASM_SECT_TYPE 1 +#define WASM_SECT_IMPORT 2 +#define WASM_SECT_FUNCTION 3 +#define WASM_SECT_TABLE 4 +#define WASM_SECT_MEMORY 5 +#define WASM_SECT_GLOBAL 6 +#define WASM_SECT_EXPORT 7 +#define WASM_SECT_START 8 +#define WASM_SECT_ELEMENT 9 +#define WASM_SECT_CODE 10 +#define WASM_SECT_DATA 11 + +// Opcode constants +#define WASM_OP_UNREACHABLE 0x00 /* "unreachable" */ +#define WASM_OP_NOP 0x01 /* "nop" */ +#define WASM_OP_BLOCK 0x02 /* "block" BLOCKT */ +#define WASM_OP_LOOP 0x03 /* "loop" BLOCKT */ +#define WASM_OP_END 0x0B /* "end" */ +#define WASM_OP_BR 0x0C /* "br" LABEL */ +#define WASM_OP_BR_IF 0x0D /* "br_if" LABEL */ +#define WASM_OP_BR_TABLE 0x0E /* "br_table" LABELS */ +#define WASM_OP_RETURN 0x0F /* "return" */ +#define WASM_OP_CALL 0x10 /* "call" FUNC */ +#define WASM_OP_CALL_INDIRECT 0x11 /* "call_indirect" SIG_TABLE */ +#define WASM_OP_DROP 0x1A /* "drop" */ +#define WASM_OP_SELECT 0x1B /* "select" */ +#define WASM_OP_LOCAL_GET 0x20 /* "local.get" LOCAL */ +#define WASM_OP_LOCAL_SET 0x21 /* "local.set" LOCAL */ +#define WASM_OP_LOCAL_TEE 0x22 /* "local.tee" LOCAL */ +#define WASM_OP_GLOBAL_GET 0x23 /* "global.get" GLOBAL */ +#define WASM_OP_GLOBAL_SET 0x24 /* "global.set" GLOBAL */ +#define WASM_OP_I32_LOAD 0x28 /* "i32.load" MEMARG */ +#define WASM_OP_F64_LOAD 0x2B /* "f64.load" MEMARG */ +#define WASM_OP_I32_LOAD8_S 0x2C /* "i32.load8_s" MEMARG */ +#define WASM_OP_I32_LOAD8_U 0x2D /* "i32.load8_u" MEMARG */ +#define WASM_OP_I32_LOAD16_S 0x2E /* "i32.load16_s" MEMARG */ +#define WASM_OP_I32_LOAD16_U 0x2F /* "i32.load16_u" MEMARG */ +#define WASM_OP_I32_STORE 0x36 /* "i32.store" MEMARG */ +#define WASM_OP_F64_STORE 0x39 /* "f64.store" MEMARG */ +#define WASM_OP_I32_STORE8 0x3A /* "i32.store8" MEMARG */ +#define WASM_OP_I32_STORE16 0x3B /* "i32.store16" MEMARG */ +#define WASM_OP_I32_CONST 0x41 /* "i32.const" I32 */ +#define WASM_OP_F64_CONST 0x44 /* "f64.const" F64 */ +#define WASM_OP_I32_EQZ 0x45 /* "i32.eqz" */ +#define WASM_OP_I32_EQ 0x46 /* "i32.eq" */ +#define WASM_OP_I32_NE 0x47 /* "i32.ne" */ +#define WASM_OP_I32_LT_S 0x48 /* "i32.lt_s" */ +#define WASM_OP_I32_LT_U 0x49 /* "i32.lt_u" */ +#define WASM_OP_I32_GT_S 0x4A /* "i32.gt_s" */ +#define WASM_OP_I32_GT_U 0x4B /* "i32.gt_u" */ +#define WASM_OP_I32_LE_S 0x4C /* "i32.le_s" */ +#define WASM_OP_I32_LE_U 0x4D /* "i32.le_u" */ +#define WASM_OP_I32_GE_S 0x4E /* "i32.ge_s" */ +#define WASM_OP_I32_GE_U 0x4F /* "i32.ge_u" */ +#define WASM_OP_F64_EQ 0x61 /* "f64.eq" */ +#define WASM_OP_F64_NE 0x62 /* "f64.ne" */ +#define WASM_OP_F64_LT 0x63 /* "f64.lt" */ +#define WASM_OP_F64_GT 0x64 /* "f64.gt" */ +#define WASM_OP_F64_LE 0x65 /* "f64.le" */ +#define WASM_OP_F64_GE 0x66 /* "f64.ge" */ +#define WASM_OP_I32_CLZ 0x67 /* "i32.clz" */ +#define WASM_OP_I32_CTZ 0x68 /* "i32.ctz" */ +#define WASM_OP_I32_POPCNT 0x69 /* "i32.popcnt" */ +#define WASM_OP_I32_ADD 0x6A /* "i32.add" */ +#define WASM_OP_I32_SUB 0x6B /* "i32.sub" */ +#define WASM_OP_I32_MUL 0x6C /* "i32.mul" */ +#define WASM_OP_I32_DIV_S 0x6D /* "i32.div_s" */ +#define WASM_OP_I32_DIV_U 0x6E /* "i32.div_u" */ +#define WASM_OP_I32_REM_S 0x6F /* "i32.rem_s" */ +#define WASM_OP_I32_REM_U 0x70 /* "i32.rem_u" */ +#define WASM_OP_I32_AND 0x71 /* "i32.and" */ +#define WASM_OP_I32_OR 0x72 /* "i32.or" */ +#define WASM_OP_I32_XOR 0x73 /* "i32.xor" */ +#define WASM_OP_I32_SHL 0x74 /* "i32.shl" */ +#define WASM_OP_I32_SHR_S 0x75 /* "i32.shr_s" */ +#define WASM_OP_I32_SHR_U 0x76 /* "i32.shr_u" */ +#define WASM_OP_I32_ROTL 0x77 /* "i32.rotl" */ +#define WASM_OP_I32_ROTR 0x78 /* "i32.rotr" */ +#define WASM_OP_F64_ADD 0xA0 /* "f64.add" */ +#define WASM_OP_F64_SUB 0xA1 /* "f64.sub" */ +#define WASM_OP_F64_MUL 0xA2 /* "f64.mul" */ +#define WASM_OP_F64_DIV 0xA3 /* "f64.div" */ +#define WASM_OP_I32_TRUNC_F64_S 0xAA /* "i32.trunc_f64_s" */ +#define WASM_OP_I32_TRUNC_F64_U 0xAB /* "i32.trunc_f64_u" */ +#define WASM_OP_F64_CONVERT_I32_S 0xB7 /* "f64.convert_i32_s" */ +#define WASM_OP_F64_CONVERT_I32_U 0xB8 /* "f64.convert_i32_u" */ +#define WASM_OP_I32_EXTEND8_S 0xC0 /* "i32.extend8_s" */ +#define WASM_OP_I32_EXTEND16_S 0xC1 /* "i32.extend16_s" */ + +#define WASM_OP_JMP 0xF0 /* "jmp" */ +#define WASM_OP_JMP_IF 0xF1 /* "jmp_if */ +#define WASM_OP_JMP_TABLE 0xF2 /* jmp_table */ + +#define WEEWASM_INTRINSIC_PUTI 0x01 +#define WEEWASM_INTRINSIC_PUTD 0x02 +#define WEEWASM_INTRINSIC_PUTS 0x03 diff --git a/xbyak/COPYRIGHT b/xbyak/COPYRIGHT new file mode 100644 index 0000000..55da9ce --- /dev/null +++ b/xbyak/COPYRIGHT @@ -0,0 +1,27 @@ +
+Copyright (c) 2007 MITSUNARI Shigeo
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this
+list of conditions and the following disclaimer.
+Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+Neither the name of the copyright owner nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/xbyak/xbyak.h b/xbyak/xbyak.h new file mode 100644 index 0000000..e080708 --- /dev/null +++ b/xbyak/xbyak.h @@ -0,0 +1,2951 @@ +#pragma once +#ifndef XBYAK_XBYAK_H_ +#define XBYAK_XBYAK_H_ +/*! + @file xbyak.h + @brief Xbyak ; JIT assembler for x86(IA32)/x64 by C++ + @author herumi + @url https://github.com/herumi/xbyak + @note modified new BSD license + http://opensource.org/licenses/BSD-3-Clause +*/ +#if (not +0) && !defined(XBYAK_NO_OP_NAMES) // trick to detect whether 'not' is operator or not + #define XBYAK_NO_OP_NAMES +#endif + +#include <stdio.h> // for debug print +#include <assert.h> +#include <list> +#include <string> +#include <algorithm> +#ifndef NDEBUG +#include <iostream> +#endif + +// #define XBYAK_DISABLE_AVX512 + +#if !defined(XBYAK_USE_MMAP_ALLOCATOR) && !defined(XBYAK_DONT_USE_MMAP_ALLOCATOR) + #define XBYAK_USE_MMAP_ALLOCATOR +#endif +#if !defined(__GNUC__) || defined(__MINGW32__) + #undef XBYAK_USE_MMAP_ALLOCATOR +#endif + +#ifdef __GNUC__ + #define XBYAK_GNUC_PREREQ(major, minor) ((__GNUC__) * 100 + (__GNUC_MINOR__) >= (major) * 100 + (minor)) +#else + #define XBYAK_GNUC_PREREQ(major, minor) 0 +#endif + +// This covers -std=(gnu|c)++(0x|11|1y), -stdlib=libc++, and modern Microsoft. +#if ((defined(_MSC_VER) && (_MSC_VER >= 1600)) || defined(_LIBCPP_VERSION) ||\ + ((__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__))) + #include <unordered_set> + #define XBYAK_STD_UNORDERED_SET std::unordered_set + #include <unordered_map> + #define XBYAK_STD_UNORDERED_MAP std::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::unordered_multimap + +/* + Clang/llvm-gcc and ICC-EDG in 'GCC-mode' always claim to be GCC 4.2, using + libstdcxx 20070719 (from GCC 4.2.1, the last GPL 2 version). +*/ +#elif XBYAK_GNUC_PREREQ(4, 5) || (XBYAK_GNUC_PREREQ(4, 2) && __GLIBCXX__ >= 20070719) || defined(__INTEL_COMPILER) || defined(__llvm__) + #include <tr1/unordered_set> + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set + #include <tr1/unordered_map> + #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap + +#elif defined(_MSC_VER) && (_MSC_VER >= 1500) && (_MSC_VER < 1600) + #include <unordered_set> + #define XBYAK_STD_UNORDERED_SET std::tr1::unordered_set + #include <unordered_map> + #define XBYAK_STD_UNORDERED_MAP std::tr1::unordered_map + #define XBYAK_STD_UNORDERED_MULTIMAP std::tr1::unordered_multimap + +#else + #include <set> + #define XBYAK_STD_UNORDERED_SET std::set + #include <map> + #define XBYAK_STD_UNORDERED_MAP std::map + #define XBYAK_STD_UNORDERED_MULTIMAP std::multimap +#endif +#ifdef _WIN32 + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include <windows.h> + #include <malloc.h> + #ifdef _MSC_VER + #define XBYAK_TLS __declspec(thread) + #else + #define XBYAK_TLS __thread + #endif +#elif defined(__GNUC__) + #include <unistd.h> + #include <sys/mman.h> + #include <stdlib.h> + #define XBYAK_TLS __thread +#endif +#if defined(__APPLE__) && !defined(XBYAK_DONT_USE_MAP_JIT) + #define XBYAK_USE_MAP_JIT + #include <sys/sysctl.h> + #ifndef MAP_JIT + #define MAP_JIT 0x800 + #endif +#endif +#if !defined(_MSC_VER) || (_MSC_VER >= 1600) + #include <stdint.h> +#endif + +// MFD_CLOEXEC defined only linux 3.17 or later. +// Android wraps the memfd_create syscall from API version 30. +#if !defined(MFD_CLOEXEC) || (defined(__ANDROID__) && __ANDROID_API__ < 30) + #undef XBYAK_USE_MEMFD +#endif + +#if defined(_WIN64) || defined(__MINGW64__) || (defined(__CYGWIN__) && defined(__x86_64__)) + #define XBYAK64_WIN +#elif defined(__x86_64__) + #define XBYAK64_GCC +#endif +#if !defined(XBYAK64) && !defined(XBYAK32) + #if defined(XBYAK64_GCC) || defined(XBYAK64_WIN) + #define XBYAK64 + #else + #define XBYAK32 + #endif +#endif + +#if (__cplusplus >= 201103) || (defined(_MSC_VER) && _MSC_VER >= 1900) + #undef XBYAK_TLS + #define XBYAK_TLS thread_local + #define XBYAK_VARIADIC_TEMPLATE + #define XBYAK_NOEXCEPT noexcept +#else + #define XBYAK_NOEXCEPT throw() +#endif + +// require c++14 or later +// Visual Studio 2017 version 15.0 or later +// g++-6 or later +#if ((__cplusplus >= 201402L) && !(!defined(__clang__) && defined(__GNUC__) && (__GNUC__ <= 5))) || (defined(_MSC_VER) && _MSC_VER >= 1910) + #define XBYAK_CONSTEXPR constexpr +#else + #define XBYAK_CONSTEXPR +#endif + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4514) /* remove inline function */ + #pragma warning(disable : 4786) /* identifier is too long */ + #pragma warning(disable : 4503) /* name is too long */ + #pragma warning(disable : 4127) /* constant expresison */ +#endif + +// disable -Warray-bounds because it may be a bug of gcc. https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104603 +#if defined(__GNUC__) && !defined(__clang__) + #define XBYAK_DISABLE_WARNING_ARRAY_BOUNDS + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Warray-bounds" +#endif + +namespace Xbyak { + +enum { + DEFAULT_MAX_CODE_SIZE = 4096, + VERSION = 0x6670 /* 0xABCD = A.BC(.D) */ +}; + +#ifndef MIE_INTEGER_TYPE_DEFINED +#define MIE_INTEGER_TYPE_DEFINED +// for backward compatibility +typedef uint64_t uint64; +typedef int64_t sint64; +typedef uint32_t uint32; +typedef uint16_t uint16; +typedef uint8_t uint8; +#endif + +#ifndef MIE_ALIGN + #ifdef _MSC_VER + #define MIE_ALIGN(x) __declspec(align(x)) + #else + #define MIE_ALIGN(x) __attribute__((aligned(x))) + #endif +#endif +#ifndef MIE_PACK // for shufps + #define MIE_PACK(x, y, z, w) ((x) * 64 + (y) * 16 + (z) * 4 + (w)) +#endif + +enum { + ERR_NONE = 0, + ERR_BAD_ADDRESSING, + ERR_CODE_IS_TOO_BIG, + ERR_BAD_SCALE, + ERR_ESP_CANT_BE_INDEX, + ERR_BAD_COMBINATION, + ERR_BAD_SIZE_OF_REGISTER, + ERR_IMM_IS_TOO_BIG, + ERR_BAD_ALIGN, + ERR_LABEL_IS_REDEFINED, + ERR_LABEL_IS_TOO_FAR, + ERR_LABEL_IS_NOT_FOUND, + ERR_CODE_ISNOT_COPYABLE, + ERR_BAD_PARAMETER, + ERR_CANT_PROTECT, + ERR_CANT_USE_64BIT_DISP, + ERR_OFFSET_IS_TOO_BIG, + ERR_MEM_SIZE_IS_NOT_SPECIFIED, + ERR_BAD_MEM_SIZE, + ERR_BAD_ST_COMBINATION, + ERR_OVER_LOCAL_LABEL, // not used + ERR_UNDER_LOCAL_LABEL, + ERR_CANT_ALLOC, + ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW, + ERR_BAD_PROTECT_MODE, + ERR_BAD_PNUM, + ERR_BAD_TNUM, + ERR_BAD_VSIB_ADDRESSING, + ERR_CANT_CONVERT, + ERR_LABEL_ISNOT_SET_BY_L, + ERR_LABEL_IS_ALREADY_SET_BY_L, + ERR_BAD_LABEL_STR, + ERR_MUNMAP, + ERR_OPMASK_IS_ALREADY_SET, + ERR_ROUNDING_IS_ALREADY_SET, + ERR_K0_IS_INVALID, + ERR_EVEX_IS_INVALID, + ERR_SAE_IS_INVALID, + ERR_ER_IS_INVALID, + ERR_INVALID_BROADCAST, + ERR_INVALID_OPMASK_WITH_MEMORY, + ERR_INVALID_ZERO, + ERR_INVALID_RIP_IN_AUTO_GROW, + ERR_INVALID_MIB_ADDRESS, + ERR_X2APIC_IS_NOT_SUPPORTED, + ERR_NOT_SUPPORTED, + ERR_SAME_REGS_ARE_INVALID, + ERR_INTERNAL // Put it at last. +}; + +inline const char *ConvertErrorToString(int err) +{ + static const char *errTbl[] = { + "none", + "bad addressing", + "code is too big", + "bad scale", + "esp can't be index", + "bad combination", + "bad size of register", + "imm is too big", + "bad align", + "label is redefined", + "label is too far", + "label is not found", + "code is not copyable", + "bad parameter", + "can't protect", + "can't use 64bit disp(use (void*))", + "offset is too big", + "MEM size is not specified", + "bad mem size", + "bad st combination", + "over local label", + "under local label", + "can't alloc", + "T_SHORT is not supported in AutoGrow", + "bad protect mode", + "bad pNum", + "bad tNum", + "bad vsib addressing", + "can't convert", + "label is not set by L()", + "label is already set by L()", + "bad label string", + "err munmap", + "opmask is already set", + "rounding is already set", + "k0 is invalid", + "evex is invalid", + "sae(suppress all exceptions) is invalid", + "er(embedded rounding) is invalid", + "invalid broadcast", + "invalid opmask with memory", + "invalid zero", + "invalid rip in AutoGrow", + "invalid mib address", + "x2APIC is not supported", + "not supported", + "same regs are invalid", + "internal error" + }; + assert(ERR_INTERNAL + 1 == sizeof(errTbl) / sizeof(*errTbl)); + return err <= ERR_INTERNAL ? errTbl[err] : "unknown err"; +} + +#ifdef XBYAK_NO_EXCEPTION +namespace local { + +inline int& GetErrorRef() { + static XBYAK_TLS int err = 0; + return err; +} + +inline void SetError(int err) { + if (local::GetErrorRef()) return; // keep the first err code + local::GetErrorRef() = err; +} + +} // local + +inline void ClearError() { + local::GetErrorRef() = 0; +} +inline int GetError() { return Xbyak::local::GetErrorRef(); } + +#define XBYAK_THROW(err) { Xbyak::local::SetError(err); return; } +#define XBYAK_THROW_RET(err, r) { Xbyak::local::SetError(err); return r; } + +#else +class Error : public std::exception { + int err_; +public: + explicit Error(int err) : err_(err) + { + if (err_ < 0 || err_ > ERR_INTERNAL) { + err_ = ERR_INTERNAL; + } + } + operator int() const { return err_; } + const char *what() const XBYAK_NOEXCEPT + { + return ConvertErrorToString(err_); + } +}; + +// dummy functions +inline void ClearError() { } +inline int GetError() { return 0; } + +inline const char *ConvertErrorToString(const Error& err) +{ + return err.what(); +} + +#define XBYAK_THROW(err) { throw Error(err); } +#define XBYAK_THROW_RET(err, r) { throw Error(err); } + +#endif + +inline void *AlignedMalloc(size_t size, size_t alignment) +{ +#ifdef __MINGW32__ + return __mingw_aligned_malloc(size, alignment); +#elif defined(_WIN32) + return _aligned_malloc(size, alignment); +#else + void *p; + int ret = posix_memalign(&p, alignment, size); + return (ret == 0) ? p : 0; +#endif +} + +inline void AlignedFree(void *p) +{ +#ifdef __MINGW32__ + __mingw_aligned_free(p); +#elif defined(_MSC_VER) + _aligned_free(p); +#else + free(p); +#endif +} + +template<class To, class From> +inline const To CastTo(From p) XBYAK_NOEXCEPT +{ + return (const To)(size_t)(p); +} +namespace inner { + +static const size_t ALIGN_PAGE_SIZE = 4096; + +inline bool IsInDisp8(uint32_t x) { return 0xFFFFFF80 <= x || x <= 0x7F; } +inline bool IsInInt32(uint64_t x) { return ~uint64_t(0x7fffffffu) <= x || x <= 0x7FFFFFFFU; } + +inline uint32_t VerifyInInt32(uint64_t x) +{ +#if defined(XBYAK64) && !defined(__ILP32__) + if (!IsInInt32(x)) XBYAK_THROW_RET(ERR_OFFSET_IS_TOO_BIG, 0) +#endif + return static_cast<uint32_t>(x); +} + +enum LabelMode { + LasIs, // as is + Labs, // absolute + LaddTop // (addr + top) for mov(reg, label) with AutoGrow +}; + +} // inner + +/* + custom allocator +*/ +struct Allocator { + explicit Allocator(const std::string& = "") {} // same interface with MmapAllocator + virtual uint8_t *alloc(size_t size) { return reinterpret_cast<uint8_t*>(AlignedMalloc(size, inner::ALIGN_PAGE_SIZE)); } + virtual void free(uint8_t *p) { AlignedFree(p); } + virtual ~Allocator() {} + /* override to return false if you call protect() manually */ + virtual bool useProtect() const { return true; } +}; + +#ifdef XBYAK_USE_MMAP_ALLOCATOR +#ifdef XBYAK_USE_MAP_JIT +namespace util { + +inline int getMacOsVersionPure() +{ + char buf[64]; + size_t size = sizeof(buf); + int err = sysctlbyname("kern.osrelease", buf, &size, NULL, 0); + if (err != 0) return 0; + char *endp; + int major = strtol(buf, &endp, 10); + if (*endp != '.') return 0; + return major; +} + +inline int getMacOsVersion() +{ + static const int version = getMacOsVersionPure(); + return version; +} + +} // util +#endif +class MmapAllocator : public Allocator { + struct Allocation { + size_t size; +#if defined(XBYAK_USE_MEMFD) + // fd_ is only used with XBYAK_USE_MEMFD. We keep the file open + // during the lifetime of each allocation in order to support + // checkpoint/restore by unprivileged users. + int fd; +#endif + }; + const std::string name_; // only used with XBYAK_USE_MEMFD + typedef XBYAK_STD_UNORDERED_MAP<uintptr_t, Allocation> AllocationList; + AllocationList allocList_; +public: + explicit MmapAllocator(const std::string& name = "xbyak") : name_(name) {} + uint8_t *alloc(size_t size) + { + const size_t alignedSizeM1 = inner::ALIGN_PAGE_SIZE - 1; + size = (size + alignedSizeM1) & ~alignedSizeM1; +#if defined(MAP_ANONYMOUS) + int mode = MAP_PRIVATE | MAP_ANONYMOUS; +#elif defined(MAP_ANON) + int mode = MAP_PRIVATE | MAP_ANON; +#else + #error "not supported" +#endif +#if defined(XBYAK_USE_MAP_JIT) + const int mojaveVersion = 18; + if (util::getMacOsVersion() >= mojaveVersion) mode |= MAP_JIT; +#endif + int fd = -1; +#if defined(XBYAK_USE_MEMFD) + fd = memfd_create(name_.c_str(), MFD_CLOEXEC); + if (fd != -1) { + mode = MAP_SHARED; + if (ftruncate(fd, size) != 0) { + close(fd); + XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) + } + } +#endif + void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, mode, fd, 0); + if (p == MAP_FAILED) { + if (fd != -1) close(fd); + XBYAK_THROW_RET(ERR_CANT_ALLOC, 0) + } + assert(p); + Allocation &alloc = allocList_[(uintptr_t)p]; + alloc.size = size; +#if defined(XBYAK_USE_MEMFD) + alloc.fd = fd; +#endif + return (uint8_t*)p; + } + void free(uint8_t *p) + { + if (p == 0) return; + AllocationList::iterator i = allocList_.find((uintptr_t)p); + if (i == allocList_.end()) XBYAK_THROW(ERR_BAD_PARAMETER) + if (munmap((void*)i->first, i->second.size) < 0) XBYAK_THROW(ERR_MUNMAP) +#if defined(XBYAK_USE_MEMFD) + if (i->second.fd != -1) close(i->second.fd); +#endif + allocList_.erase(i); + } +}; +#else +typedef Allocator MmapAllocator; +#endif + +class Address; +class Reg; + +class Operand { + static const uint8_t EXT8BIT = 0x20; + unsigned int idx_:6; // 0..31 + EXT8BIT = 1 if spl/bpl/sil/dil + unsigned int kind_:10; + unsigned int bit_:14; +protected: + unsigned int zero_:1; + unsigned int mask_:3; + unsigned int rounding_:3; + void setIdx(int idx) { idx_ = idx; } +public: + enum Kind { + NONE = 0, + MEM = 1 << 0, + REG = 1 << 1, + MMX = 1 << 2, + FPU = 1 << 3, + XMM = 1 << 4, + YMM = 1 << 5, + ZMM = 1 << 6, + OPMASK = 1 << 7, + BNDREG = 1 << 8, + TMM = 1 << 9 + }; + enum Code { +#ifdef XBYAK64 + RAX = 0, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15, + R8D = 8, R9D, R10D, R11D, R12D, R13D, R14D, R15D, + R8W = 8, R9W, R10W, R11W, R12W, R13W, R14W, R15W, + R8B = 8, R9B, R10B, R11B, R12B, R13B, R14B, R15B, + SPL = 4, BPL, SIL, DIL, +#endif + EAX = 0, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + AX = 0, CX, DX, BX, SP, BP, SI, DI, + AL = 0, CL, DL, BL, AH, CH, DH, BH + }; + XBYAK_CONSTEXPR Operand() : idx_(0), kind_(0), bit_(0), zero_(0), mask_(0), rounding_(0) { } + XBYAK_CONSTEXPR Operand(int idx, Kind kind, int bit, bool ext8bit = 0) + : idx_(static_cast<uint8_t>(idx | (ext8bit ? EXT8BIT : 0))) + , kind_(kind) + , bit_(bit) + , zero_(0), mask_(0), rounding_(0) + { + assert((bit_ & (bit_ - 1)) == 0); // bit must be power of two + } + XBYAK_CONSTEXPR Kind getKind() const { return static_cast<Kind>(kind_); } + XBYAK_CONSTEXPR int getIdx() const { return idx_ & (EXT8BIT - 1); } + XBYAK_CONSTEXPR bool isNone() const { return kind_ == 0; } + XBYAK_CONSTEXPR bool isMMX() const { return is(MMX); } + XBYAK_CONSTEXPR bool isXMM() const { return is(XMM); } + XBYAK_CONSTEXPR bool isYMM() const { return is(YMM); } + XBYAK_CONSTEXPR bool isZMM() const { return is(ZMM); } + XBYAK_CONSTEXPR bool isTMM() const { return is(TMM); } + XBYAK_CONSTEXPR bool isXMEM() const { return is(XMM | MEM); } + XBYAK_CONSTEXPR bool isYMEM() const { return is(YMM | MEM); } + XBYAK_CONSTEXPR bool isZMEM() const { return is(ZMM | MEM); } + XBYAK_CONSTEXPR bool isOPMASK() const { return is(OPMASK); } + XBYAK_CONSTEXPR bool isBNDREG() const { return is(BNDREG); } + XBYAK_CONSTEXPR bool isREG(int bit = 0) const { return is(REG, bit); } + XBYAK_CONSTEXPR bool isMEM(int bit = 0) const { return is(MEM, bit); } + XBYAK_CONSTEXPR bool isFPU() const { return is(FPU); } + XBYAK_CONSTEXPR bool isExt8bit() const { return (idx_ & EXT8BIT) != 0; } + XBYAK_CONSTEXPR bool isExtIdx() const { return (getIdx() & 8) != 0; } + XBYAK_CONSTEXPR bool isExtIdx2() const { return (getIdx() & 16) != 0; } + XBYAK_CONSTEXPR bool hasEvex() const { return isZMM() || isExtIdx2() || getOpmaskIdx() || getRounding(); } + XBYAK_CONSTEXPR bool hasRex() const { return isExt8bit() || isREG(64) || isExtIdx(); } + XBYAK_CONSTEXPR bool hasZero() const { return zero_; } + XBYAK_CONSTEXPR int getOpmaskIdx() const { return mask_; } + XBYAK_CONSTEXPR int getRounding() const { return rounding_; } + void setKind(Kind kind) + { + if ((kind & (XMM|YMM|ZMM|TMM)) == 0) return; + kind_ = kind; + bit_ = kind == XMM ? 128 : kind == YMM ? 256 : kind == ZMM ? 512 : 8192; + } + // err if MMX/FPU/OPMASK/BNDREG + void setBit(int bit); + void setOpmaskIdx(int idx, bool /*ignore_idx0*/ = true) + { + if (mask_) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) + mask_ = idx; + } + void setRounding(int idx) + { + if (rounding_) XBYAK_THROW(ERR_ROUNDING_IS_ALREADY_SET) + rounding_ = idx; + } + void setZero() { zero_ = true; } + // ah, ch, dh, bh? + bool isHigh8bit() const + { + if (!isBit(8)) return false; + if (isExt8bit()) return false; + const int idx = getIdx(); + return AH <= idx && idx <= BH; + } + // any bit is accetable if bit == 0 + XBYAK_CONSTEXPR bool is(int kind, uint32_t bit = 0) const + { + return (kind == 0 || (kind_ & kind)) && (bit == 0 || (bit_ & bit)); // cf. you can set (8|16) + } + XBYAK_CONSTEXPR bool isBit(uint32_t bit) const { return (bit_ & bit) != 0; } + XBYAK_CONSTEXPR uint32_t getBit() const { return bit_; } + const char *toString() const + { + const int idx = getIdx(); + if (kind_ == REG) { + if (isExt8bit()) { + static const char *tbl[4] = { "spl", "bpl", "sil", "dil" }; + return tbl[idx - 4]; + } + static const char *tbl[4][16] = { + { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b" }, + { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }, + { "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d" }, + { "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" }, + }; + return tbl[bit_ == 8 ? 0 : bit_ == 16 ? 1 : bit_ == 32 ? 2 : 3][idx]; + } else if (isOPMASK()) { + static const char *tbl[8] = { "k0", "k1", "k2", "k3", "k4", "k5", "k6", "k7" }; + return tbl[idx]; + } else if (isTMM()) { + static const char *tbl[8] = { + "tmm0", "tmm1", "tmm2", "tmm3", "tmm4", "tmm5", "tmm6", "tmm7" + }; + return tbl[idx]; + } else if (isZMM()) { + static const char *tbl[32] = { + "zmm0", "zmm1", "zmm2", "zmm3", "zmm4", "zmm5", "zmm6", "zmm7", "zmm8", "zmm9", "zmm10", "zmm11", "zmm12", "zmm13", "zmm14", "zmm15", + "zmm16", "zmm17", "zmm18", "zmm19", "zmm20", "zmm21", "zmm22", "zmm23", "zmm24", "zmm25", "zmm26", "zmm27", "zmm28", "zmm29", "zmm30", "zmm31" + }; + return tbl[idx]; + } else if (isYMM()) { + static const char *tbl[32] = { + "ymm0", "ymm1", "ymm2", "ymm3", "ymm4", "ymm5", "ymm6", "ymm7", "ymm8", "ymm9", "ymm10", "ymm11", "ymm12", "ymm13", "ymm14", "ymm15", + "ymm16", "ymm17", "ymm18", "ymm19", "ymm20", "ymm21", "ymm22", "ymm23", "ymm24", "ymm25", "ymm26", "ymm27", "ymm28", "ymm29", "ymm30", "ymm31" + }; + return tbl[idx]; + } else if (isXMM()) { + static const char *tbl[32] = { + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", + "xmm16", "xmm17", "xmm18", "xmm19", "xmm20", "xmm21", "xmm22", "xmm23", "xmm24", "xmm25", "xmm26", "xmm27", "xmm28", "xmm29", "xmm30", "xmm31" + }; + return tbl[idx]; + } else if (isMMX()) { + static const char *tbl[8] = { "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7" }; + return tbl[idx]; + } else if (isFPU()) { + static const char *tbl[8] = { "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7" }; + return tbl[idx]; + } else if (isBNDREG()) { + static const char *tbl[4] = { "bnd0", "bnd1", "bnd2", "bnd3" }; + return tbl[idx]; + } + XBYAK_THROW_RET(ERR_INTERNAL, 0); + } + 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_; } + bool operator==(const Operand& rhs) const; + bool operator!=(const Operand& rhs) const { return !operator==(rhs); } + const Address& getAddress() const; + const Reg& getReg() const; +}; + +inline void Operand::setBit(int bit) +{ + if (bit != 8 && bit != 16 && bit != 32 && bit != 64 && bit != 128 && bit != 256 && bit != 512 && bit != 8192) goto ERR; + if (isBit(bit)) return; + if (is(MEM | OPMASK)) { + bit_ = bit; + return; + } + if (is(REG | XMM | YMM | ZMM | TMM)) { + int idx = getIdx(); + // err if converting ah, bh, ch, dh + if (isREG(8) && (4 <= idx && idx < 8) && !isExt8bit()) goto ERR; + Kind kind = REG; + switch (bit) { + case 8: + if (idx >= 16) goto ERR; +#ifdef XBYAK32 + if (idx >= 4) goto ERR; +#else + if (4 <= idx && idx < 8) idx |= EXT8BIT; +#endif + break; + case 16: + case 32: + case 64: + if (idx >= 16) goto ERR; + break; + case 128: kind = XMM; break; + case 256: kind = YMM; break; + case 512: kind = ZMM; break; + case 8192: kind = TMM; break; + } + idx_ = idx; + kind_ = kind; + bit_ = bit; + if (bit >= 128) return; // keep mask_ and rounding_ + mask_ = 0; + rounding_ = 0; + return; + } +ERR: + XBYAK_THROW(ERR_CANT_CONVERT) +} + +class Label; + +struct Reg8; +struct Reg16; +struct Reg32; +#ifdef XBYAK64 +struct Reg64; +#endif +class Reg : public Operand { +public: + XBYAK_CONSTEXPR Reg() { } + XBYAK_CONSTEXPR Reg(int idx, Kind kind, int bit = 0, bool ext8bit = false) : Operand(idx, kind, bit, ext8bit) { } + // convert to Reg8/Reg16/Reg32/Reg64/XMM/YMM/ZMM + Reg changeBit(int bit) const { Reg r(*this); r.setBit(bit); return r; } + uint8_t getRexW() const { return isREG(64) ? 8 : 0; } + uint8_t getRexR() const { return isExtIdx() ? 4 : 0; } + uint8_t getRexX() const { return isExtIdx() ? 2 : 0; } + uint8_t getRexB() const { return isExtIdx() ? 1 : 0; } + uint8_t getRex(const Reg& base = Reg()) const + { + uint8_t rex = getRexW() | getRexR() | base.getRexW() | base.getRexB(); + if (rex || isExt8bit() || base.isExt8bit()) rex |= 0x40; + return rex; + } + Reg8 cvt8() const; + Reg16 cvt16() const; + Reg32 cvt32() const; +#ifdef XBYAK64 + Reg64 cvt64() const; +#endif +}; + +inline const Reg& Operand::getReg() const +{ + assert(!isMEM()); + return static_cast<const Reg&>(*this); +} + +struct Reg8 : public Reg { + explicit XBYAK_CONSTEXPR Reg8(int idx = 0, bool ext8bit = false) : Reg(idx, Operand::REG, 8, ext8bit) { } +}; + +struct Reg16 : public Reg { + explicit XBYAK_CONSTEXPR Reg16(int idx = 0) : Reg(idx, Operand::REG, 16) { } +}; + +struct Mmx : public Reg { + explicit XBYAK_CONSTEXPR Mmx(int idx = 0, Kind kind = Operand::MMX, int bit = 64) : Reg(idx, kind, bit) { } +}; + +struct EvexModifierRounding { + enum { + T_RN_SAE = 1, + T_RD_SAE = 2, + T_RU_SAE = 3, + T_RZ_SAE = 4, + T_SAE = 5 + }; + explicit XBYAK_CONSTEXPR EvexModifierRounding(int rounding) : rounding(rounding) {} + int rounding; +}; +struct EvexModifierZero{ XBYAK_CONSTEXPR EvexModifierZero() {}}; + +struct Xmm : public Mmx { + explicit XBYAK_CONSTEXPR Xmm(int idx = 0, Kind kind = Operand::XMM, int bit = 128) : Mmx(idx, kind, bit) { } + XBYAK_CONSTEXPR Xmm(Kind kind, int idx) : Mmx(idx, kind, kind == XMM ? 128 : kind == YMM ? 256 : 512) { } + Xmm operator|(const EvexModifierRounding& emr) const { Xmm r(*this); r.setRounding(emr.rounding); return r; } + Xmm copyAndSetIdx(int idx) const { Xmm ret(*this); ret.setIdx(idx); return ret; } + Xmm copyAndSetKind(Operand::Kind kind) const { Xmm ret(*this); ret.setKind(kind); return ret; } +}; + +struct Ymm : public Xmm { + explicit XBYAK_CONSTEXPR Ymm(int idx = 0, Kind kind = Operand::YMM, int bit = 256) : Xmm(idx, kind, bit) { } + Ymm operator|(const EvexModifierRounding& emr) const { Ymm r(*this); r.setRounding(emr.rounding); return r; } +}; + +struct Zmm : public Ymm { + explicit XBYAK_CONSTEXPR Zmm(int idx = 0) : Ymm(idx, Operand::ZMM, 512) { } + Zmm operator|(const EvexModifierRounding& emr) const { Zmm r(*this); r.setRounding(emr.rounding); return r; } +}; + +#ifdef XBYAK64 +struct Tmm : public Reg { + explicit XBYAK_CONSTEXPR Tmm(int idx = 0, Kind kind = Operand::TMM, int bit = 8192) : Reg(idx, kind, bit) { } +}; +#endif + +struct Opmask : public Reg { + explicit XBYAK_CONSTEXPR Opmask(int idx = 0) : Reg(idx, Operand::OPMASK, 64) {} +}; + +struct BoundsReg : public Reg { + explicit XBYAK_CONSTEXPR BoundsReg(int idx = 0) : Reg(idx, Operand::BNDREG, 128) {} +}; + +template<class T>T operator|(const T& x, const Opmask& k) { T r(x); r.setOpmaskIdx(k.getIdx()); return r; } +template<class T>T operator|(const T& x, const EvexModifierZero&) { T r(x); r.setZero(); return r; } +template<class T>T operator|(const T& x, const EvexModifierRounding& emr) { T r(x); r.setRounding(emr.rounding); return r; } + +struct Fpu : public Reg { + explicit XBYAK_CONSTEXPR Fpu(int idx = 0) : Reg(idx, Operand::FPU, 32) { } +}; + +struct Reg32e : public Reg { + explicit XBYAK_CONSTEXPR Reg32e(int idx, int bit) : Reg(idx, Operand::REG, bit) {} +}; +struct Reg32 : public Reg32e { + explicit XBYAK_CONSTEXPR Reg32(int idx = 0) : Reg32e(idx, 32) {} +}; +#ifdef XBYAK64 +struct Reg64 : public Reg32e { + explicit XBYAK_CONSTEXPR Reg64(int idx = 0) : Reg32e(idx, 64) {} +}; +struct RegRip { + int64_t disp_; + const Label* label_; + bool isAddr_; + explicit XBYAK_CONSTEXPR RegRip(int64_t disp = 0, const Label* label = 0, bool isAddr = false) : disp_(disp), label_(label), isAddr_(isAddr) {} + friend const RegRip operator+(const RegRip& r, int disp) { + return RegRip(r.disp_ + disp, r.label_, r.isAddr_); + } + friend const RegRip operator-(const RegRip& r, int disp) { + return RegRip(r.disp_ - disp, r.label_, r.isAddr_); + } + friend const RegRip operator+(const RegRip& r, int64_t disp) { + return RegRip(r.disp_ + disp, r.label_, r.isAddr_); + } + friend const RegRip operator-(const RegRip& r, int64_t disp) { + return RegRip(r.disp_ - disp, r.label_, r.isAddr_); + } + friend const RegRip operator+(const RegRip& r, const Label& label) { + if (r.label_ || r.isAddr_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegRip()); + return RegRip(r.disp_, &label); + } + friend const RegRip operator+(const RegRip& r, const void *addr) { + if (r.label_ || r.isAddr_) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegRip()); + return RegRip(r.disp_ + (int64_t)addr, 0, true); + } +}; +#endif + +inline Reg8 Reg::cvt8() const +{ + Reg r = changeBit(8); return Reg8(r.getIdx(), r.isExt8bit()); +} + +inline Reg16 Reg::cvt16() const +{ + return Reg16(changeBit(16).getIdx()); +} + +inline Reg32 Reg::cvt32() const +{ + return Reg32(changeBit(32).getIdx()); +} + +#ifdef XBYAK64 +inline Reg64 Reg::cvt64() const +{ + return Reg64(changeBit(64).getIdx()); +} +#endif + +#ifndef XBYAK_DISABLE_SEGMENT +// not derived from Reg +class Segment { + int idx_; +public: + enum { + es, cs, ss, ds, fs, gs + }; + explicit XBYAK_CONSTEXPR Segment(int idx) : idx_(idx) { assert(0 <= idx_ && idx_ < 6); } + int getIdx() const { return idx_; } + const char *toString() const + { + static const char tbl[][3] = { + "es", "cs", "ss", "ds", "fs", "gs" + }; + return tbl[idx_]; + } +}; +#endif + +class RegExp { +public: +#ifdef XBYAK64 + enum { i32e = 32 | 64 }; +#else + enum { i32e = 32 }; +#endif + XBYAK_CONSTEXPR RegExp(size_t disp = 0) : scale_(0), disp_(disp) { } + XBYAK_CONSTEXPR RegExp(const Reg& r, int scale = 1) + : scale_(scale) + , disp_(0) + { + if (!r.isREG(i32e) && !r.is(Reg::XMM|Reg::YMM|Reg::ZMM|Reg::TMM)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + if (scale == 0) return; + if (scale != 1 && scale != 2 && scale != 4 && scale != 8) XBYAK_THROW(ERR_BAD_SCALE) + if (r.getBit() >= 128 || scale != 1) { // xmm/ymm is always index + index_ = r; + } else { + base_ = r; + } + } + bool isVsib(int bit = 128 | 256 | 512) const { return index_.isBit(bit); } + RegExp optimize() const + { + RegExp exp = *this; + // [reg * 2] => [reg + reg] + if (index_.isBit(i32e) && !base_.getBit() && scale_ == 2) { + exp.base_ = index_; + exp.scale_ = 1; + } + return exp; + } + bool operator==(const RegExp& rhs) const + { + return base_ == rhs.base_ && index_ == rhs.index_ && disp_ == rhs.disp_ && scale_ == rhs.scale_; + } + const Reg& getBase() const { return base_; } + const Reg& getIndex() const { return index_; } + int getScale() const { return scale_; } + size_t getDisp() const { return disp_; } + XBYAK_CONSTEXPR void verify() const + { + if (base_.getBit() >= 128) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + if (index_.getBit() && index_.getBit() <= 64) { + if (index_.getIdx() == Operand::ESP) XBYAK_THROW(ERR_ESP_CANT_BE_INDEX) + if (base_.getBit() && base_.getBit() != index_.getBit()) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + } + } + friend RegExp operator+(const RegExp& a, const RegExp& b); + friend RegExp operator-(const RegExp& e, size_t disp); + uint8_t getRex() const + { + uint8_t rex = index_.getRexX() | base_.getRexB(); + return rex ? uint8_t(rex | 0x40) : 0; + } +private: + /* + [base_ + index_ * scale_ + disp_] + base : Reg32e, index : Reg32e(w/o esp), Xmm, Ymm + */ + Reg base_; + Reg index_; + int scale_; + size_t disp_; +}; + +inline RegExp operator+(const RegExp& a, const RegExp& b) +{ + if (a.index_.getBit() && b.index_.getBit()) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp()) + RegExp ret = a; + if (!ret.index_.getBit()) { ret.index_ = b.index_; ret.scale_ = b.scale_; } + if (b.base_.getBit()) { + if (ret.base_.getBit()) { + if (ret.index_.getBit()) XBYAK_THROW_RET(ERR_BAD_ADDRESSING, RegExp()) + // base + base => base + index * 1 + ret.index_ = b.base_; + // [reg + esp] => [esp + reg] + if (ret.index_.getIdx() == Operand::ESP) std::swap(ret.base_, ret.index_); + ret.scale_ = 1; + } else { + ret.base_ = b.base_; + } + } + ret.disp_ += b.disp_; + return ret; +} +inline RegExp operator*(const Reg& r, int scale) +{ + return RegExp(r, scale); +} +inline RegExp operator*(int scale, const Reg& r) +{ + return r * scale; +} +inline RegExp operator-(const RegExp& e, size_t disp) +{ + RegExp ret = e; + ret.disp_ -= disp; + return ret; +} + +// 2nd parameter for constructor of CodeArray(maxSize, userPtr, alloc) +void *const AutoGrow = (void*)1; //-V566 +void *const DontSetProtectRWE = (void*)2; //-V566 + +class CodeArray { + enum Type { + USER_BUF = 1, // use userPtr(non alignment, non protect) + ALLOC_BUF, // use new(alignment, protect) + AUTO_GROW // automatically move and grow memory if necessary + }; + CodeArray(const CodeArray& rhs); + void operator=(const CodeArray&); + bool isAllocType() const { return type_ == ALLOC_BUF || type_ == AUTO_GROW; } + struct AddrInfo { + size_t codeOffset; // position to write + size_t jmpAddr; // value to write + int jmpSize; // size of jmpAddr + inner::LabelMode mode; + AddrInfo(size_t _codeOffset, size_t _jmpAddr, int _jmpSize, inner::LabelMode _mode) + : codeOffset(_codeOffset), jmpAddr(_jmpAddr), jmpSize(_jmpSize), mode(_mode) {} + uint64_t getVal(const uint8_t *top) const + { + uint64_t disp = (mode == inner::LaddTop) ? jmpAddr + size_t(top) : (mode == inner::LasIs) ? jmpAddr : jmpAddr - size_t(top); + if (jmpSize == 4) disp = inner::VerifyInInt32(disp); + return disp; + } + }; + typedef std::list<AddrInfo> AddrInfoList; + AddrInfoList addrInfoList_; + const Type type_; +#ifdef XBYAK_USE_MMAP_ALLOCATOR + MmapAllocator defaultAllocator_; +#else + Allocator defaultAllocator_; +#endif + Allocator *alloc_; +protected: + size_t maxSize_; + uint8_t *top_; + size_t size_; + bool isCalledCalcJmpAddress_; + + bool useProtect() const { return alloc_->useProtect(); } + /* + allocate new memory and copy old data to the new area + */ + void growMemory() + { + const size_t newSize = (std::max<size_t>)(DEFAULT_MAX_CODE_SIZE, maxSize_ * 2); + uint8_t *newTop = alloc_->alloc(newSize); + if (newTop == 0) XBYAK_THROW(ERR_CANT_ALLOC) + for (size_t i = 0; i < size_; i++) newTop[i] = top_[i]; + alloc_->free(top_); + top_ = newTop; + maxSize_ = newSize; + } + /* + calc jmp address for AutoGrow mode + */ + void calcJmpAddress() + { + if (isCalledCalcJmpAddress_) return; + for (AddrInfoList::const_iterator i = addrInfoList_.begin(), ie = addrInfoList_.end(); i != ie; ++i) { + uint64_t disp = i->getVal(top_); + rewrite(i->codeOffset, disp, i->jmpSize); + } + isCalledCalcJmpAddress_ = true; + } +public: + enum ProtectMode { + PROTECT_RW = 0, // read/write + PROTECT_RWE = 1, // read/write/exec + PROTECT_RE = 2 // read/exec + }; + explicit CodeArray(size_t maxSize, void *userPtr = 0, Allocator *allocator = 0) + : type_(userPtr == AutoGrow ? AUTO_GROW : (userPtr == 0 || userPtr == DontSetProtectRWE) ? ALLOC_BUF : USER_BUF) + , alloc_(allocator ? allocator : (Allocator*)&defaultAllocator_) + , maxSize_(maxSize) + , top_(type_ == USER_BUF ? reinterpret_cast<uint8_t*>(userPtr) : alloc_->alloc((std::max<size_t>)(maxSize, 1))) + , size_(0) + , isCalledCalcJmpAddress_(false) + { + if (maxSize_ > 0 && top_ == 0) XBYAK_THROW(ERR_CANT_ALLOC) + if ((type_ == ALLOC_BUF && userPtr != DontSetProtectRWE && useProtect()) && !setProtectMode(PROTECT_RWE, false)) { + alloc_->free(top_); + XBYAK_THROW(ERR_CANT_PROTECT) + } + } + virtual ~CodeArray() + { + if (isAllocType()) { + if (useProtect()) setProtectModeRW(false); + alloc_->free(top_); + } + } + bool setProtectMode(ProtectMode mode, bool throwException = true) + { + bool isOK = protect(top_, maxSize_, mode); + if (isOK) return true; + if (throwException) XBYAK_THROW_RET(ERR_CANT_PROTECT, false) + return false; + } + bool setProtectModeRE(bool throwException = true) { return setProtectMode(PROTECT_RE, throwException); } + bool setProtectModeRW(bool throwException = true) { return setProtectMode(PROTECT_RW, throwException); } + void resetSize() + { + size_ = 0; + addrInfoList_.clear(); + isCalledCalcJmpAddress_ = false; + } + void db(int code) + { + if (size_ >= maxSize_) { + if (type_ == AUTO_GROW) { + growMemory(); + } else { + XBYAK_THROW(ERR_CODE_IS_TOO_BIG) + } + } + top_[size_++] = static_cast<uint8_t>(code); + } + void db(const uint8_t *code, size_t codeSize) + { + for (size_t i = 0; i < codeSize; i++) db(code[i]); + } + void db(uint64_t code, size_t codeSize) + { + if (codeSize > 8) XBYAK_THROW(ERR_BAD_PARAMETER) + for (size_t i = 0; i < codeSize; i++) db(static_cast<uint8_t>(code >> (i * 8))); + } + void dw(uint32_t code) { db(code, 2); } + void dd(uint32_t code) { db(code, 4); } + void dq(uint64_t code) { db(code, 8); } + const uint8_t *getCode() const { return top_; } + template<class F> + const F getCode() const { return reinterpret_cast<F>(top_); } + const uint8_t *getCurr() const { return &top_[size_]; } + template<class F> + const F getCurr() const { return reinterpret_cast<F>(&top_[size_]); } + size_t getSize() const { return size_; } + void setSize(size_t size) + { + if (size > maxSize_) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG) + size_ = size; + } + void dump() const + { + const uint8_t *p = getCode(); + size_t bufSize = getSize(); + size_t remain = bufSize; + for (int i = 0; i < 4; i++) { + size_t disp = 16; + if (remain < 16) { + disp = remain; + } + for (size_t j = 0; j < 16; j++) { + if (j < disp) { + printf("%02X", p[i * 16 + j]); + } + } + putchar('\n'); + remain -= disp; + if (remain == 0) { + break; + } + } + } + /* + @param offset [in] offset from top + @param disp [in] offset from the next of jmp + @param size [in] write size(1, 2, 4, 8) + */ + void rewrite(size_t offset, uint64_t disp, size_t size) + { + assert(offset < maxSize_); + if (size != 1 && size != 2 && size != 4 && size != 8) XBYAK_THROW(ERR_BAD_PARAMETER) + uint8_t *const data = top_ + offset; + for (size_t i = 0; i < size; i++) { + data[i] = static_cast<uint8_t>(disp >> (i * 8)); + } + } + void save(size_t offset, size_t val, int size, inner::LabelMode mode) + { + addrInfoList_.push_back(AddrInfo(offset, val, size, mode)); + } + bool isAutoGrow() const { return type_ == AUTO_GROW; } + bool isCalledCalcJmpAddress() const { return isCalledCalcJmpAddress_; } + /** + change exec permission of memory + @param addr [in] buffer address + @param size [in] buffer size + @param protectMode [in] mode(RW/RWE/RE) + @return true(success), false(failure) + */ + static inline bool protect(const void *addr, size_t size, int protectMode) + { +#if defined(_WIN32) + const DWORD c_rw = PAGE_READWRITE; + const DWORD c_rwe = PAGE_EXECUTE_READWRITE; + const DWORD c_re = PAGE_EXECUTE_READ; + DWORD mode; +#else + const int c_rw = PROT_READ | PROT_WRITE; + const int c_rwe = PROT_READ | PROT_WRITE | PROT_EXEC; + const int c_re = PROT_READ | PROT_EXEC; + int mode; +#endif + switch (protectMode) { + case PROTECT_RW: mode = c_rw; break; + case PROTECT_RWE: mode = c_rwe; break; + case PROTECT_RE: mode = c_re; break; + default: + return false; + } +#if defined(_WIN32) + DWORD oldProtect; + return VirtualProtect(const_cast<void*>(addr), size, mode, &oldProtect) != 0; +#elif defined(__GNUC__) + size_t pageSize = sysconf(_SC_PAGESIZE); + size_t iaddr = reinterpret_cast<size_t>(addr); + size_t roundAddr = iaddr & ~(pageSize - static_cast<size_t>(1)); +#ifndef NDEBUG + if (pageSize != 4096) fprintf(stderr, "large page(%zd) is used. not tested enough.\n", pageSize); +#endif + return mprotect(reinterpret_cast<void*>(roundAddr), size + (iaddr - roundAddr), mode) == 0; +#else + return true; +#endif + } + /** + get aligned memory pointer + @param addr [in] address + @param alignedSize [in] power of two + @return aligned addr by alingedSize + */ + static inline uint8_t *getAlignedAddress(uint8_t *addr, size_t alignedSize = 16) + { + return reinterpret_cast<uint8_t*>((reinterpret_cast<size_t>(addr) + alignedSize - 1) & ~(alignedSize - static_cast<size_t>(1))); + } +}; + +class Address : public Operand { +public: + enum Mode { + M_ModRM, + M_64bitDisp, + M_rip, + M_ripAddr + }; + XBYAK_CONSTEXPR Address(uint32_t sizeBit, bool broadcast, const RegExp& e) + : Operand(0, MEM, sizeBit), e_(e), label_(0), mode_(M_ModRM), broadcast_(broadcast) + { + e_.verify(); + } +#ifdef XBYAK64 + explicit XBYAK_CONSTEXPR Address(size_t disp) + : Operand(0, MEM, 64), e_(disp), label_(0), mode_(M_64bitDisp), broadcast_(false){ } + XBYAK_CONSTEXPR Address(uint32_t sizeBit, bool broadcast, const RegRip& addr) + : Operand(0, MEM, sizeBit), e_(addr.disp_), label_(addr.label_), mode_(addr.isAddr_ ? M_ripAddr : M_rip), broadcast_(broadcast) { } +#endif + RegExp getRegExp(bool optimize = true) const + { + return optimize ? e_.optimize() : e_; + } + Mode getMode() const { return mode_; } + bool is32bit() const { return e_.getBase().getBit() == 32 || e_.getIndex().getBit() == 32; } + bool isOnlyDisp() const { return !e_.getBase().getBit() && !e_.getIndex().getBit(); } // for mov eax + size_t getDisp() const { return e_.getDisp(); } + uint8_t getRex() const + { + if (mode_ != M_ModRM) return 0; + return getRegExp().getRex(); + } + bool is64bitDisp() const { return mode_ == M_64bitDisp; } // for moffset + bool isBroadcast() const { return broadcast_; } + const Label* getLabel() const { return label_; } + bool operator==(const Address& rhs) const + { + return getBit() == rhs.getBit() && e_ == rhs.e_ && label_ == rhs.label_ && mode_ == rhs.mode_ && broadcast_ == rhs.broadcast_; + } + bool operator!=(const Address& rhs) const { return !operator==(rhs); } + bool isVsib() const { return e_.isVsib(); } +private: + RegExp e_; + const Label* label_; + Mode mode_; + bool broadcast_; +}; + +inline const Address& Operand::getAddress() const +{ + assert(isMEM()); + return static_cast<const Address&>(*this); +} + +inline bool Operand::operator==(const Operand& rhs) const +{ + if (isMEM() && rhs.isMEM()) return this->getAddress() == rhs.getAddress(); + return isEqualIfNotInherited(rhs); +} + +class AddressFrame { + void operator=(const AddressFrame&); + AddressFrame(const AddressFrame&); +public: + const uint32_t bit_; + const bool broadcast_; + explicit XBYAK_CONSTEXPR AddressFrame(uint32_t bit, bool broadcast = false) : bit_(bit), broadcast_(broadcast) { } + Address operator[](const RegExp& e) const + { + return Address(bit_, broadcast_, e); + } + Address operator[](const void *disp) const + { + return Address(bit_, broadcast_, RegExp(reinterpret_cast<size_t>(disp))); + } +#ifdef XBYAK64 + Address operator[](uint64_t disp) const { return Address(disp); } + Address operator[](const RegRip& addr) const { return Address(bit_, broadcast_, addr); } +#endif +}; + +struct JmpLabel { + size_t endOfJmp; /* offset from top to the end address of jmp */ + int jmpSize; + inner::LabelMode mode; + size_t disp; // disp for [rip + disp] + explicit JmpLabel(size_t endOfJmp = 0, int jmpSize = 0, inner::LabelMode mode = inner::LasIs, size_t disp = 0) + : endOfJmp(endOfJmp), jmpSize(jmpSize), mode(mode), disp(disp) + { + } +}; + +class LabelManager; + +class Label { + mutable LabelManager *mgr; + mutable int id; + friend class LabelManager; +public: + Label() : mgr(0), id(0) {} + Label(const Label& rhs); + Label& operator=(const Label& rhs); + ~Label(); + void clear() { mgr = 0; id = 0; } + int getId() const { return id; } + const uint8_t *getAddress() const; + + // backward compatibility + static inline std::string toStr(int num) + { + char buf[16]; +#if defined(_MSC_VER) && (_MSC_VER < 1900) + _snprintf_s +#else + snprintf +#endif + (buf, sizeof(buf), ".%08x", num); + return buf; + } +}; + +class LabelManager { + // for string label + struct SlabelVal { + size_t offset; + SlabelVal(size_t offset) : offset(offset) {} + }; + typedef XBYAK_STD_UNORDERED_MAP<std::string, SlabelVal> SlabelDefList; + typedef XBYAK_STD_UNORDERED_MULTIMAP<std::string, const JmpLabel> SlabelUndefList; + struct SlabelState { + SlabelDefList defList; + SlabelUndefList undefList; + }; + typedef std::list<SlabelState> StateList; + // for Label class + struct ClabelVal { + ClabelVal(size_t offset = 0) : offset(offset), refCount(1) {} + size_t offset; + int refCount; + }; + typedef XBYAK_STD_UNORDERED_MAP<int, ClabelVal> ClabelDefList; + typedef XBYAK_STD_UNORDERED_MULTIMAP<int, const JmpLabel> ClabelUndefList; + typedef XBYAK_STD_UNORDERED_SET<Label*> LabelPtrList; + + CodeArray *base_; + // global : stateList_.front(), local : stateList_.back() + StateList stateList_; + mutable int labelId_; + ClabelDefList clabelDefList_; + ClabelUndefList clabelUndefList_; + LabelPtrList labelPtrList_; + + int getId(const Label& label) const + { + if (label.id == 0) label.id = labelId_++; + return label.id; + } + template<class DefList, class UndefList, class T> + void define_inner(DefList& defList, UndefList& undefList, const T& labelId, size_t addrOffset) + { + // add label + typename DefList::value_type item(labelId, addrOffset); + std::pair<typename DefList::iterator, bool> ret = defList.insert(item); + if (!ret.second) XBYAK_THROW(ERR_LABEL_IS_REDEFINED) + // search undefined label + for (;;) { + typename UndefList::iterator itr = undefList.find(labelId); + if (itr == undefList.end()) break; + const JmpLabel *jmp = &itr->second; + const size_t offset = jmp->endOfJmp - jmp->jmpSize; + size_t disp; + if (jmp->mode == inner::LaddTop) { + disp = addrOffset; + } else if (jmp->mode == inner::Labs) { + disp = size_t(base_->getCurr()); + } else { + disp = addrOffset - jmp->endOfJmp + jmp->disp; +#ifdef XBYAK64 + if (jmp->jmpSize <= 4 && !inner::IsInInt32(disp)) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG) +#endif + if (jmp->jmpSize == 1 && !inner::IsInDisp8((uint32_t)disp)) XBYAK_THROW(ERR_LABEL_IS_TOO_FAR) + } + if (base_->isAutoGrow()) { + base_->save(offset, disp, jmp->jmpSize, jmp->mode); + } else { + base_->rewrite(offset, disp, jmp->jmpSize); + } + undefList.erase(itr); + } + } + template<class DefList, class T> + bool getOffset_inner(const DefList& defList, size_t *offset, const T& label) const + { + typename DefList::const_iterator i = defList.find(label); + if (i == defList.end()) return false; + *offset = i->second.offset; + return true; + } + friend class Label; + void incRefCount(int id, Label *label) + { + clabelDefList_[id].refCount++; + labelPtrList_.insert(label); + } + void decRefCount(int id, Label *label) + { + labelPtrList_.erase(label); + ClabelDefList::iterator i = clabelDefList_.find(id); + if (i == clabelDefList_.end()) return; + if (i->second.refCount == 1) { + clabelDefList_.erase(id); + } else { + --i->second.refCount; + } + } + template<class T> + bool hasUndefinedLabel_inner(const T& list) const + { +#ifndef NDEBUG + for (typename T::const_iterator i = list.begin(); i != list.end(); ++i) { + std::cerr << "undefined label:" << i->first << std::endl; + } +#endif + return !list.empty(); + } + // detach all labels linked to LabelManager + void resetLabelPtrList() + { + for (LabelPtrList::iterator i = labelPtrList_.begin(), ie = labelPtrList_.end(); i != ie; ++i) { + (*i)->clear(); + } + labelPtrList_.clear(); + } +public: + LabelManager() + { + reset(); + } + ~LabelManager() + { + resetLabelPtrList(); + } + void reset() + { + base_ = 0; + labelId_ = 1; + stateList_.clear(); + stateList_.push_back(SlabelState()); + stateList_.push_back(SlabelState()); + clabelDefList_.clear(); + clabelUndefList_.clear(); + resetLabelPtrList(); + } + void enterLocal() + { + stateList_.push_back(SlabelState()); + } + void leaveLocal() + { + if (stateList_.size() <= 2) XBYAK_THROW(ERR_UNDER_LOCAL_LABEL) + if (hasUndefinedLabel_inner(stateList_.back().undefList)) XBYAK_THROW(ERR_LABEL_IS_NOT_FOUND) + stateList_.pop_back(); + } + void set(CodeArray *base) { base_ = base; } + void defineSlabel(std::string label) + { + if (label == "@b" || label == "@f") XBYAK_THROW(ERR_BAD_LABEL_STR) + if (label == "@@") { + SlabelDefList& defList = stateList_.front().defList; + SlabelDefList::iterator i = defList.find("@f"); + if (i != defList.end()) { + defList.erase(i); + label = "@b"; + } else { + i = defList.find("@b"); + if (i != defList.end()) { + defList.erase(i); + } + label = "@f"; + } + } + SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + define_inner(st.defList, st.undefList, label, base_->getSize()); + } + void defineClabel(Label& label) + { + define_inner(clabelDefList_, clabelUndefList_, getId(label), base_->getSize()); + label.mgr = this; + labelPtrList_.insert(&label); + } + void assign(Label& dst, const Label& src) + { + ClabelDefList::const_iterator i = clabelDefList_.find(src.id); + if (i == clabelDefList_.end()) XBYAK_THROW(ERR_LABEL_ISNOT_SET_BY_L) + define_inner(clabelDefList_, clabelUndefList_, dst.id, i->second.offset); + dst.mgr = this; + labelPtrList_.insert(&dst); + } + bool getOffset(size_t *offset, std::string& label) const + { + const SlabelDefList& defList = stateList_.front().defList; + if (label == "@b") { + if (defList.find("@f") != defList.end()) { + label = "@f"; + } else if (defList.find("@b") == defList.end()) { + XBYAK_THROW_RET(ERR_LABEL_IS_NOT_FOUND, false) + } + } else if (label == "@f") { + if (defList.find("@f") != defList.end()) { + label = "@b"; + } + } + const SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + return getOffset_inner(st.defList, offset, label); + } + bool getOffset(size_t *offset, const Label& label) const + { + return getOffset_inner(clabelDefList_, offset, getId(label)); + } + void addUndefinedLabel(const std::string& label, const JmpLabel& jmp) + { + SlabelState& st = *label.c_str() == '.' ? stateList_.back() : stateList_.front(); + st.undefList.insert(SlabelUndefList::value_type(label, jmp)); + } + void addUndefinedLabel(const Label& label, const JmpLabel& jmp) + { + clabelUndefList_.insert(ClabelUndefList::value_type(label.id, jmp)); + } + bool hasUndefSlabel() const + { + for (StateList::const_iterator i = stateList_.begin(), ie = stateList_.end(); i != ie; ++i) { + if (hasUndefinedLabel_inner(i->undefList)) return true; + } + return false; + } + bool hasUndefClabel() const { return hasUndefinedLabel_inner(clabelUndefList_); } + const uint8_t *getCode() const { return base_->getCode(); } + bool isReady() const { return !base_->isAutoGrow() || base_->isCalledCalcJmpAddress(); } +}; + +inline Label::Label(const Label& rhs) +{ + id = rhs.id; + mgr = rhs.mgr; + if (mgr) mgr->incRefCount(id, this); +} +inline Label& Label::operator=(const Label& rhs) +{ + if (id) XBYAK_THROW_RET(ERR_LABEL_IS_ALREADY_SET_BY_L, *this) + id = rhs.id; + mgr = rhs.mgr; + if (mgr) mgr->incRefCount(id, this); + return *this; +} +inline Label::~Label() +{ + if (id && mgr) mgr->decRefCount(id, this); +} +inline const uint8_t* Label::getAddress() const +{ + if (mgr == 0 || !mgr->isReady()) return 0; + size_t offset; + if (!mgr->getOffset(&offset, *this)) return 0; + return mgr->getCode() + offset; +} + +typedef enum { + DefaultEncoding, + VexEncoding, + EvexEncoding +} PreferredEncoding; + +class CodeGenerator : public CodeArray { +public: + enum LabelType { + T_SHORT, + T_NEAR, + T_FAR, // far jump + T_AUTO // T_SHORT if possible + }; +private: + CodeGenerator operator=(const CodeGenerator&); // don't call +#ifdef XBYAK64 + enum { i32e = 32 | 64, BIT = 64 }; + static const uint64_t dummyAddr = uint64_t(0x1122334455667788ull); + typedef Reg64 NativeReg; +#else + enum { i32e = 32, BIT = 32 }; + static const size_t dummyAddr = 0x12345678; + typedef Reg32 NativeReg; +#endif + // (XMM, XMM|MEM) + static inline bool isXMM_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isXMM() || op2.isMEM()); + } + // (MMX, MMX|MEM) or (XMM, XMM|MEM) + static inline bool isXMMorMMX_MEM(const Operand& op1, const Operand& op2) + { + return (op1.isMMX() && (op2.isMMX() || op2.isMEM())) || isXMM_XMMorMEM(op1, op2); + } + // (XMM, MMX|MEM) + static inline bool isXMM_MMXorMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isMMX() || op2.isMEM()); + } + // (MMX, XMM|MEM) + static inline bool isMMX_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isMMX() && (op2.isXMM() || op2.isMEM()); + } + // (XMM, REG32|MEM) + static inline bool isXMM_REG32orMEM(const Operand& op1, const Operand& op2) + { + return op1.isXMM() && (op2.isREG(i32e) || op2.isMEM()); + } + // (REG32, XMM|MEM) + static inline bool isREG32_XMMorMEM(const Operand& op1, const Operand& op2) + { + return op1.isREG(i32e) && (op2.isXMM() || op2.isMEM()); + } + // (REG32, REG32|MEM) + static inline bool isREG32_REG32orMEM(const Operand& op1, const Operand& op2) + { + return op1.isREG(i32e) && ((op2.isREG(i32e) && op1.getBit() == op2.getBit()) || op2.isMEM()); + } + static inline bool isValidSSE(const Operand& op1) + { + // SSE instructions do not support XMM16 - XMM31 + return !(op1.isXMM() && op1.getIdx() >= 16); + } + void rex(const Operand& op1, const Operand& op2 = Operand()) + { + uint8_t rex = 0; + const Operand *p1 = &op1, *p2 = &op2; + if (p1->isMEM()) std::swap(p1, p2); + if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) + if (p2->isMEM()) { + const Address& addr = p2->getAddress(); + if (BIT == 64 && addr.is32bit()) db(0x67); + rex = addr.getRex() | p1->getReg().getRex(); + } else { + // ModRM(reg, base); + rex = op2.getReg().getRex(op1.getReg()); + } + // except movsx(16bit, 32/64bit) + if ((op1.isBit(16) && !op2.isBit(i32e)) || (op2.isBit(16) && !op1.isBit(i32e))) db(0x66); + if (rex) db(rex); + } + enum AVXtype { + // low 3 bit + T_N1 = 1, + T_N2 = 2, + T_N4 = 3, + T_N8 = 4, + T_N16 = 5, + T_N32 = 6, + T_NX_MASK = 7, + // + T_N_VL = 1 << 3, // N * (1, 2, 4) for VL + T_DUP = 1 << 4, // N = (8, 32, 64) + T_66 = 1 << 5, // pp = 1 + T_F3 = 1 << 6, // pp = 2 + T_F2 = T_66 | T_F3, // pp = 3 + T_ER_R = 1 << 7, // reg{er} + T_0F = 1 << 8, + T_0F38 = 1 << 9, + T_0F3A = 1 << 10, + T_L0 = 1 << 11, + T_L1 = 1 << 12, + T_W0 = 1 << 13, + T_W1 = 1 << 14, + T_EW0 = 1 << 15, + T_EW1 = 1 << 16, + T_YMM = 1 << 17, // support YMM, ZMM + T_EVEX = 1 << 18, + T_ER_X = 1 << 19, // xmm{er} + T_ER_Y = 1 << 20, // ymm{er} + T_ER_Z = 1 << 21, // zmm{er} + T_SAE_X = 1 << 22, // xmm{sae} + T_SAE_Y = 1 << 23, // ymm{sae} + T_SAE_Z = 1 << 24, // zmm{sae} + T_MUST_EVEX = 1 << 25, // contains T_EVEX + T_B32 = 1 << 26, // m32bcst + T_B64 = 1 << 27, // m64bcst + T_B16 = T_B32 | T_B64, // m16bcst (Be careful) + T_M_K = 1 << 28, // mem{k} + T_VSIB = 1 << 29, + T_MEM_EVEX = 1 << 30, // use evex if mem + T_FP16 = 1 << 31, // avx512-fp16 + T_MAP5 = T_FP16 | T_0F, + T_MAP6 = T_FP16 | T_0F38, + T_XXX + }; + // T_66 = 1, T_F3 = 2, T_F2 = 3 + uint32_t getPP(int type) const { return (type >> 5) & 3; } + void vex(const Reg& reg, const Reg& base, const Operand *v, int type, int code, bool x = false) + { + int w = (type & T_W1) ? 1 : 0; + bool is256 = (type & T_L1) ? true : (type & T_L0) ? false : reg.isYMM(); + bool r = reg.isExtIdx(); + bool b = base.isExtIdx(); + int idx = v ? v->getIdx() : 0; + if ((idx | reg.getIdx() | base.getIdx()) >= 16) XBYAK_THROW(ERR_BAD_COMBINATION) + uint32_t pp = getPP(type); + uint32_t vvvv = (((~idx) & 15) << 3) | (is256 ? 4 : 0) | pp; + if (!b && !x && !w && (type & T_0F)) { + db(0xC5); db((r ? 0 : 0x80) | vvvv); + } else { + uint32_t mmmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0; + db(0xC4); db((r ? 0 : 0x80) | (x ? 0 : 0x40) | (b ? 0 : 0x20) | mmmm); db((w << 7) | vvvv); + } + db(code); + } + void verifySAE(const Reg& r, int type) const + { + if (((type & T_SAE_X) && r.isXMM()) || ((type & T_SAE_Y) && r.isYMM()) || ((type & T_SAE_Z) && r.isZMM())) return; + XBYAK_THROW(ERR_SAE_IS_INVALID) + } + void verifyER(const Reg& r, int type) const + { + if ((type & T_ER_R) && r.isREG(32|64)) return; + if (((type & T_ER_X) && r.isXMM()) || ((type & T_ER_Y) && r.isYMM()) || ((type & T_ER_Z) && r.isZMM())) return; + XBYAK_THROW(ERR_ER_IS_INVALID) + } + // (a, b, c) contains non zero two or three values then err + int verifyDuplicate(int a, int b, int c, int err) + { + int v = a | b | c; + if ((a > 0 && a != v) + (b > 0 && b != v) + (c > 0 && c != v) > 0) XBYAK_THROW_RET(err, 0) + return v; + } + 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_t VL = 0, bool Hi16Vidx = false) + { + if (!(type & (T_EVEX | T_MUST_EVEX))) XBYAK_THROW_RET(ERR_EVEX_IS_INVALID, 0) + int w = (type & T_EW1) ? 1 : 0; + uint32_t mmm = (type & T_0F) ? 1 : (type & T_0F38) ? 2 : (type & T_0F3A) ? 3 : 0; + if (type & T_FP16) mmm |= 4; + uint32_t pp = getPP(type); + int idx = v ? v->getIdx() : 0; + uint32_t vvvv = ~idx; + + bool R = !reg.isExtIdx(); + bool X = x ? false : !base.isExtIdx2(); + bool B = !base.isExtIdx(); + bool Rp = !reg.isExtIdx2(); + int LL; + int rounding = verifyDuplicate(reg.getRounding(), base.getRounding(), v ? v->getRounding() : 0, ERR_ROUNDING_IS_ALREADY_SET); + int disp8N = 1; + if (rounding) { + if (rounding == EvexModifierRounding::T_SAE) { + verifySAE(base, type); LL = 0; + } else { + verifyER(base, type); LL = rounding - 1; + } + b = true; + } else { + if (v) VL = (std::max)(VL, v->getBit()); + VL = (std::max)((std::max)(reg.getBit(), base.getBit()), VL); + LL = (VL == 512) ? 2 : (VL == 256) ? 1 : 0; + if (b) { + disp8N = ((type & T_B16) == T_B16) ? 2 : (type & T_B32) ? 4 : 8; + } else if (type & T_DUP) { + disp8N = VL == 128 ? 8 : VL == 256 ? 32 : 64; + } else { + if ((type & (T_NX_MASK | T_N_VL)) == 0) { + type |= T_N16 | T_N_VL; // default + } + int low = type & T_NX_MASK; + if (low > 0) { + disp8N = 1 << (low - 1); + if (type & T_N_VL) disp8N *= (VL == 512 ? 4 : VL == 256 ? 2 : 1); + } + } + } + bool Vp = !((v ? v->isExtIdx2() : 0) | Hi16Vidx); + bool z = reg.hasZero() || base.hasZero() || (v ? v->hasZero() : false); + if (aaa == 0) aaa = verifyDuplicate(base.getOpmaskIdx(), reg.getOpmaskIdx(), (v ? v->getOpmaskIdx() : 0), ERR_OPMASK_IS_ALREADY_SET); + if (aaa == 0) z = 0; // clear T_z if mask is not set + db(0x62); + db((R ? 0x80 : 0) | (X ? 0x40 : 0) | (B ? 0x20 : 0) | (Rp ? 0x10 : 0) | mmm); + db((w == 1 ? 0x80 : 0) | ((vvvv & 15) << 3) | 4 | (pp & 3)); + db((z ? 0x80 : 0) | ((LL & 3) << 5) | (b ? 0x10 : 0) | (Vp ? 8 : 0) | (aaa & 7)); + db(code); + return disp8N; + } + void setModRM(int mod, int r1, int r2) + { + db(static_cast<uint8_t>((mod << 6) | ((r1 & 7) << 3) | (r2 & 7))); + } + void setSIB(const RegExp& e, int reg, int disp8N = 0) + { + uint64_t disp64 = e.getDisp(); +#if defined(XBYAK64) && !defined(__ILP32__) +#ifdef XBYAK_OLD_DISP_CHECK + // treat 0xffffffff as 0xffffffffffffffff + uint64_t high = disp64 >> 32; + if (high != 0 && high != 0xFFFFFFFF) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG) +#else + // displacement should be a signed 32-bit value, so also check sign bit + uint64_t high = disp64 >> 31; + if (high != 0 && high != 0x1FFFFFFFF) XBYAK_THROW(ERR_OFFSET_IS_TOO_BIG) +#endif +#endif + uint32_t disp = static_cast<uint32_t>(disp64); + const Reg& base = e.getBase(); + const Reg& index = e.getIndex(); + const int baseIdx = base.getIdx(); + const int baseBit = base.getBit(); + const int indexBit = index.getBit(); + enum { + mod00 = 0, mod01 = 1, mod10 = 2 + }; + int mod = mod10; // disp32 + if (!baseBit || ((baseIdx & 7) != Operand::EBP && disp == 0)) { + mod = mod00; + } else { + if (disp8N == 0) { + if (inner::IsInDisp8(disp)) { + mod = mod01; + } + } else { + // disp must be casted to signed + uint32_t t = static_cast<uint32_t>(static_cast<int>(disp) / disp8N); + if ((disp % disp8N) == 0 && inner::IsInDisp8(t)) { + disp = t; + mod = mod01; + } + } + } + const int newBaseIdx = baseBit ? (baseIdx & 7) : Operand::EBP; + /* ModR/M = [2:3:3] = [Mod:reg/code:R/M] */ + bool hasSIB = indexBit || (baseIdx & 7) == Operand::ESP; +#ifdef XBYAK64 + if (!baseBit && !indexBit) hasSIB = true; +#endif + if (hasSIB) { + setModRM(mod, reg, Operand::ESP); + /* SIB = [2:3:3] = [SS:index:base(=rm)] */ + const int idx = indexBit ? (index.getIdx() & 7) : Operand::ESP; + const int scale = e.getScale(); + const int SS = (scale == 8) ? 3 : (scale == 4) ? 2 : (scale == 2) ? 1 : 0; + setModRM(SS, idx, newBaseIdx); + } else { + setModRM(mod, reg, newBaseIdx); + } + if (mod == mod01) { + db(disp); + } else if (mod == mod10 || (mod == mod00 && !baseBit)) { + dd(disp); + } + } + LabelManager labelMgr_; + bool isInDisp16(uint32_t x) const { return 0xFFFF8000 <= x || x <= 0x7FFF; } + void opModR(const Reg& reg1, const Reg& reg2, int code0, int code1 = NONE, int code2 = NONE) + { + rex(reg2, reg1); + db(code0 | (reg1.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2); + setModRM(3, reg1.getIdx(), reg2.getIdx()); + } + void opModM(const Address& addr, const Reg& reg, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0) + { + if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP) + rex(addr, reg); + db(code0 | (reg.isBit(8) ? 0 : 1)); if (code1 != NONE) db(code1); if (code2 != NONE) db(code2); + opAddr(addr, reg.getIdx(), immSize); + } + void opLoadSeg(const Address& addr, const Reg& reg, int code0, int code1 = NONE) + { + if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP) + if (reg.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + rex(addr, reg); + db(code0); if (code1 != NONE) db(code1); + opAddr(addr, reg.getIdx()); + } + void opMIB(const Address& addr, const Reg& reg, int code0, int code1) + { + if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP) + if (addr.getMode() != Address::M_ModRM) XBYAK_THROW(ERR_INVALID_MIB_ADDRESS) + if (BIT == 64 && addr.is32bit()) db(0x67); + const RegExp& regExp = addr.getRegExp(false); + uint8_t rex = regExp.getRex(); + if (rex) db(rex); + db(code0); db(code1); + setSIB(regExp, reg.getIdx()); + } + void makeJmp(uint32_t disp, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref) + { + const int shortJmpSize = 2; + const int longHeaderSize = longPref ? 2 : 1; + const int longJmpSize = longHeaderSize + 4; + if (type != T_NEAR && inner::IsInDisp8(disp - shortJmpSize)) { + db(shortCode); db(disp - shortJmpSize); + } else { + if (type == T_SHORT) XBYAK_THROW(ERR_LABEL_IS_TOO_FAR) + if (longPref) db(longPref); + db(longCode); dd(disp - longJmpSize); + } + } + bool isNEAR(LabelType type) const { return type == T_NEAR || (type == T_AUTO && isDefaultJmpNEAR_); } + template<class T> + void opJmp(T& label, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref) + { + if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); /* avoid splitting code of jmp */ + size_t offset = 0; + if (labelMgr_.getOffset(&offset, label)) { /* label exists */ + makeJmp(inner::VerifyInInt32(offset - size_), type, shortCode, longCode, longPref); + } else { + int jmpSize = 0; + if (isNEAR(type)) { + jmpSize = 4; + if (longPref) db(longPref); + db(longCode); dd(0); + } else { + jmpSize = 1; + db(shortCode); db(0); + } + JmpLabel jmp(size_, jmpSize, inner::LasIs); + labelMgr_.addUndefinedLabel(label, jmp); + } + } + void opJmpAbs(const void *addr, LabelType type, uint8_t shortCode, uint8_t longCode, uint8_t longPref = 0) + { + if (type == T_FAR) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (isAutoGrow()) { + if (!isNEAR(type)) XBYAK_THROW(ERR_ONLY_T_NEAR_IS_SUPPORTED_IN_AUTO_GROW) + if (size_ + 16 >= maxSize_) growMemory(); + if (longPref) db(longPref); + db(longCode); + dd(0); + save(size_ - 4, size_t(addr) - size_, 4, inner::Labs); + } else { + makeJmp(inner::VerifyInInt32(reinterpret_cast<const uint8_t*>(addr) - getCurr()), type, shortCode, longCode, longPref); + } + + } + void opJmpOp(const Operand& op, LabelType type, int ext) + { + const int bit = 16|i32e; + if (type == T_FAR) { + if (!op.isMEM(bit)) XBYAK_THROW(ERR_NOT_SUPPORTED) + opR_ModM(op, bit, ext + 1, 0xFF, NONE, NONE, false); + } else { + opR_ModM(op, bit, ext, 0xFF, NONE, NONE, true); + } + } + // reg is reg field of ModRM + // immSize is the size for immediate value + // disp8N = 0(normal), disp8N = 1(force disp32), disp8N = {2, 4, 8} ; compressed displacement + void opAddr(const Address &addr, int reg, int immSize = 0, int disp8N = 0, bool permitVisb = false) + { + if (!permitVisb && addr.isVsib()) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING) + if (addr.getMode() == Address::M_ModRM) { + setSIB(addr.getRegExp(), reg, disp8N); + } else if (addr.getMode() == Address::M_rip || addr.getMode() == Address::M_ripAddr) { + setModRM(0, reg, 5); + if (addr.getLabel()) { // [rip + Label] + putL_inner(*addr.getLabel(), true, addr.getDisp() - immSize); + } else { + size_t disp = addr.getDisp(); + if (addr.getMode() == Address::M_ripAddr) { + if (isAutoGrow()) XBYAK_THROW(ERR_INVALID_RIP_IN_AUTO_GROW) + disp -= (size_t)getCurr() + 4 + immSize; + } + dd(inner::VerifyInInt32(disp)); + } + } + } + /* preCode is for SSSE3/SSE4 */ + void opGen(const Operand& reg, const Operand& op, int code, int pref, bool isValid(const Operand&, const Operand&), int imm8 = NONE, int preCode = NONE) + { + if (isValid && !isValid(reg, op)) XBYAK_THROW(ERR_BAD_COMBINATION) + if (!isValidSSE(reg) || !isValidSSE(op)) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (pref != NONE) db(pref); + if (op.isMEM()) { + opModM(op.getAddress(), reg.getReg(), 0x0F, preCode, code, (imm8 != NONE) ? 1 : 0); + } else { + opModR(reg.getReg(), op.getReg(), 0x0F, preCode, code); + } + if (imm8 != NONE) db(imm8); + } + void opMMX_IMM(const Mmx& mmx, int imm8, int code, int ext) + { + if (!isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (mmx.isXMM()) db(0x66); + opModR(Reg32(ext), mmx, 0x0F, code); + db(imm8); + } + void opMMX(const Mmx& mmx, const Operand& op, int code, int pref = 0x66, int imm8 = NONE, int preCode = NONE) + { + opGen(mmx, op, code, mmx.isXMM() ? pref : NONE, isXMMorMMX_MEM, imm8, preCode); + } + void opMovXMM(const Operand& op1, const Operand& op2, int code, int pref) + { + if (!isValidSSE(op1) || !isValidSSE(op2)) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (pref != NONE) db(pref); + if (op1.isXMM() && op2.isMEM()) { + opModM(op2.getAddress(), op1.getReg(), 0x0F, code); + } else if (op1.isMEM() && op2.isXMM()) { + opModM(op1.getAddress(), op2.getReg(), 0x0F, code | 1); + } else { + XBYAK_THROW(ERR_BAD_COMBINATION) + } + } + void opExt(const Operand& op, const Mmx& mmx, int code, int imm, bool hasMMX2 = false) + { + if (!isValidSSE(op) || !isValidSSE(mmx)) XBYAK_THROW(ERR_NOT_SUPPORTED) + if (hasMMX2 && op.isREG(i32e)) { /* pextrw is special */ + if (mmx.isXMM()) db(0x66); + opModR(op.getReg(), mmx, 0x0F, 0xC5); db(imm); + } else { + opGen(mmx, op, code, 0x66, isXMM_REG32orMEM, imm, 0x3A); + } + } + void opR_ModM(const Operand& op, int bit, int ext, int code0, int code1 = NONE, int code2 = NONE, bool disableRex = false, int immSize = 0) + { + int opBit = op.getBit(); + if (disableRex && opBit == 64) opBit = 32; + if (op.isREG(bit)) { + opModR(Reg(ext, Operand::REG, opBit), op.getReg().changeBit(opBit), code0, code1, code2); + } else if (op.isMEM()) { + opModM(op.getAddress(), Reg(ext, Operand::REG, opBit), code0, code1, code2, immSize); + } else { + XBYAK_THROW(ERR_BAD_COMBINATION) + } + } + void opShift(const Operand& op, int imm, int ext) + { + verifyMemHasSize(op); + opR_ModM(op, 0, ext, (0xC0 | ((imm == 1 ? 1 : 0) << 4)), NONE, NONE, false, (imm != 1) ? 1 : 0); + if (imm != 1) db(imm); + } + void opShift(const Operand& op, const Reg8& _cl, int ext) + { + if (_cl.getIdx() != Operand::CL) XBYAK_THROW(ERR_BAD_COMBINATION) + opR_ModM(op, 0, ext, 0xD2); + } + void opModRM(const Operand& op1, const Operand& op2, bool condR, bool condM, int code0, int code1 = NONE, int code2 = NONE, int immSize = 0) + { + if (condR) { + opModR(op1.getReg(), op2.getReg(), code0, code1, code2); + } else if (condM) { + opModM(op2.getAddress(), op1.getReg(), code0, code1, code2, immSize); + } else { + XBYAK_THROW(ERR_BAD_COMBINATION) + } + } + void opShxd(const Operand& op, const Reg& reg, uint8_t imm, int code, const Reg8 *_cl = 0) + { + if (_cl && _cl->getIdx() != Operand::CL) XBYAK_THROW(ERR_BAD_COMBINATION) + 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); + if (!_cl) db(imm); + } + // (REG, REG|MEM), (MEM, REG) + void opRM_RM(const Operand& op1, const Operand& op2, int code) + { + if (op1.isREG() && op2.isMEM()) { + opModM(op2.getAddress(), op1.getReg(), code | 2); + } else { + opModRM(op2, op1, op1.isREG() && op1.getKind() == op2.getKind(), op1.isMEM() && op2.isREG(), code); + } + } + // (REG|MEM, IMM) + void opRM_I(const Operand& op, uint32_t imm, int code, int ext) + { + verifyMemHasSize(op); + uint32_t immBit = inner::IsInDisp8(imm) ? 8 : isInDisp16(imm) ? 16 : 32; + if (op.isBit(8)) immBit = 8; + if (op.getBit() < immBit) XBYAK_THROW(ERR_IMM_IS_TOO_BIG) + if (op.isBit(32|64) && immBit == 16) immBit = 32; /* don't use MEM16 if 32/64bit mode */ + if (op.isREG() && op.getIdx() == 0 && (op.getBit() == immBit || (op.isBit(64) && immBit == 32))) { // rax, eax, ax, al + rex(op); + db(code | 4 | (immBit == 8 ? 0 : 1)); + } else { + int tmp = immBit < (std::min)(op.getBit(), 32U) ? 2 : 0; + opR_ModM(op, 0, ext, 0x80 | tmp, NONE, NONE, false, immBit / 8); + } + db(imm, immBit / 8); + } + void opIncDec(const Operand& op, int code, int ext) + { + verifyMemHasSize(op); +#ifndef XBYAK64 + if (op.isREG() && !op.isBit(8)) { + rex(op); db(code | op.getIdx()); + return; + } +#endif + code = 0xFE; + if (op.isREG()) { + opModR(Reg(ext, Operand::REG, op.getBit()), op.getReg(), code); + } else { + opModM(op.getAddress(), Reg(ext, Operand::REG, op.getBit()), code); + } + } + void opPushPop(const Operand& op, int code, int ext, int alt) + { + int bit = op.getBit(); + if (bit == 16 || bit == BIT) { + if (bit == 16) db(0x66); + if (op.isREG()) { + if (op.getReg().getIdx() >= 8) db(0x41); + db(alt | (op.getIdx() & 7)); + return; + } + if (op.isMEM()) { + opModM(op.getAddress(), Reg(ext, Operand::REG, 32), code); + return; + } + } + XBYAK_THROW(ERR_BAD_COMBINATION) + } + void verifyMemHasSize(const Operand& op) const + { + if (op.isMEM() && op.getBit() == 0) XBYAK_THROW(ERR_MEM_SIZE_IS_NOT_SPECIFIED) + } + /* + mov(r, imm) = db(imm, mov_imm(r, imm)) + */ + int mov_imm(const Reg& reg, uint64_t imm) + { + int bit = reg.getBit(); + const int idx = reg.getIdx(); + int code = 0xB0 | ((bit == 8 ? 0 : 1) << 3); + if (bit == 64 && (imm & ~uint64_t(0xffffffffu)) == 0) { + rex(Reg32(idx)); + bit = 32; + } else { + rex(reg); + if (bit == 64 && inner::IsInInt32(imm)) { + db(0xC7); + code = 0xC0; + bit = 32; + } + } + db(code | (idx & 7)); + return bit / 8; + } + template<class T> + void putL_inner(T& label, bool relative = false, size_t disp = 0) + { + const int jmpSize = relative ? 4 : (int)sizeof(size_t); + if (isAutoGrow() && size_ + 16 >= maxSize_) growMemory(); + size_t offset = 0; + if (labelMgr_.getOffset(&offset, label)) { + if (relative) { + db(inner::VerifyInInt32(offset + disp - size_ - jmpSize), jmpSize); + } else if (isAutoGrow()) { + db(uint64_t(0), jmpSize); + save(size_ - jmpSize, offset, jmpSize, inner::LaddTop); + } else { + db(size_t(top_) + offset, jmpSize); + } + return; + } + db(uint64_t(0), jmpSize); + JmpLabel jmp(size_, jmpSize, (relative ? inner::LasIs : isAutoGrow() ? inner::LaddTop : inner::Labs), disp); + labelMgr_.addUndefinedLabel(label, jmp); + } + void opMovxx(const Reg& reg, const Operand& op, uint8_t code) + { + if (op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) + int w = op.isBit(16); + bool cond = reg.isREG() && (reg.getBit() > op.getBit()); + opModRM(reg, op, cond && op.isREG(), cond && op.isMEM(), 0x0F, code | w); + } + void opFpuMem(const Address& addr, uint8_t m16, uint8_t m32, uint8_t m64, uint8_t ext, uint8_t m64ext) + { + if (addr.is64bitDisp()) XBYAK_THROW(ERR_CANT_USE_64BIT_DISP) + uint8_t code = addr.isBit(16) ? m16 : addr.isBit(32) ? m32 : addr.isBit(64) ? m64 : 0; + if (!code) XBYAK_THROW(ERR_BAD_MEM_SIZE) + if (m64ext && addr.isBit(64)) ext = m64ext; + + rex(addr, st0); + db(code); + opAddr(addr, ext); + } + // use code1 if reg1 == st0 + // use code2 if reg1 != st0 && reg2 == st0 + void opFpuFpu(const Fpu& reg1, const Fpu& reg2, uint32_t code1, uint32_t code2) + { + uint32_t code = reg1.getIdx() == 0 ? code1 : reg2.getIdx() == 0 ? code2 : 0; + if (!code) XBYAK_THROW(ERR_BAD_ST_COMBINATION) + db(uint8_t(code >> 8)); + db(uint8_t(code | (reg1.getIdx() | reg2.getIdx()))); + } + void opFpu(const Fpu& reg, uint8_t code1, uint8_t code2) + { + db(code1); db(code2 | reg.getIdx()); + } + void opVex(const Reg& r, const Operand *p1, const Operand& op2, int type, int code, int imm8 = NONE) + { + if (op2.isMEM()) { + const Address& addr = op2.getAddress(); + const RegExp& regExp = addr.getRegExp(); + const Reg& base = regExp.getBase(); + const Reg& index = regExp.getIndex(); + if (BIT == 64 && addr.is32bit()) db(0x67); + int disp8N = 0; + bool x = index.isExtIdx(); + if ((type & (T_MUST_EVEX|T_MEM_EVEX)) || r.hasEvex() || (p1 && p1->hasEvex()) || addr.isBroadcast() || addr.getOpmaskIdx()) { + int aaa = addr.getOpmaskIdx(); + if (aaa && !(type & T_M_K)) XBYAK_THROW(ERR_INVALID_OPMASK_WITH_MEMORY) + bool b = false; + if (addr.isBroadcast()) { + if (!(type & (T_B32 | T_B64))) XBYAK_THROW(ERR_INVALID_BROADCAST) + b = true; + } + int VL = regExp.isVsib() ? index.getBit() : 0; + disp8N = evex(r, base, p1, type, code, x, b, aaa, VL, index.isExtIdx2()); + } else { + vex(r, base, p1, type, code, x); + } + opAddr(addr, r.getIdx(), (imm8 != NONE) ? 1 : 0, disp8N, (type & T_VSIB) != 0); + } else { + const Reg& base = op2.getReg(); + if ((type & T_MUST_EVEX) || r.hasEvex() || (p1 && p1->hasEvex()) || base.hasEvex()) { + evex(r, base, p1, type, code); + } else { + vex(r, base, p1, type, code); + } + setModRM(3, r.getIdx(), base.getIdx()); + } + if (imm8 != NONE) db(imm8); + } + // (r, r, r/m) if isR_R_RM + // (r, r/m, r) + void opGpr(const Reg32e& r, const Operand& op1, const Operand& op2, int type, uint8_t code, bool isR_R_RM, int imm8 = NONE) + { + const Operand *p1 = &op1; + const Operand *p2 = &op2; + if (!isR_R_RM) std::swap(p1, p2); + const unsigned int bit = r.getBit(); + if (p1->getBit() != bit || (p2->isREG() && p2->getBit() != bit)) XBYAK_THROW(ERR_BAD_COMBINATION) + type |= (bit == 64) ? T_W1 : T_W0; + opVex(r, p1, *p2, type, code, imm8); + } + void opAVX_X_X_XM(const Xmm& x1, const Operand& op1, const Operand& op2, int type, int code0, int imm8 = NONE) + { + const Xmm *x2 = static_cast<const Xmm*>(&op1); + const Operand *op = &op2; + if (op2.isNone()) { // (x1, op1) -> (x1, x1, op1) + x2 = &x1; + op = &op1; + } + // (x1, x2, op) + if (!((x1.isXMM() && x2->isXMM()) || ((type & T_YMM) && ((x1.isYMM() && x2->isYMM()) || (x1.isZMM() && x2->isZMM()))))) XBYAK_THROW(ERR_BAD_COMBINATION) + opVex(x1, x2, *op, type, code0, imm8); + } + void opAVX_K_X_XM(const Opmask& k, const Xmm& x2, const Operand& op3, int type, int code0, int imm8 = NONE) + { + if (!op3.isMEM() && (x2.getKind() != op3.getKind())) XBYAK_THROW(ERR_BAD_COMBINATION) + opVex(k, &x2, op3, type, code0, imm8); + } + // (x, x/m), (y, x/m256), (z, y/m) + void checkCvt1(const Operand& x, const Operand& op) const + { + if (!op.isMEM() && !(x.is(Operand::XMM | Operand::YMM) && op.isXMM()) && !(x.isZMM() && op.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) + } + // (x, x/m), (x, y/m256), (y, z/m) + void checkCvt2(const Xmm& x, const Operand& op) const + { + if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) XBYAK_THROW(ERR_BAD_COMBINATION) + } + void opCvt(const Xmm& x, const Operand& op, int type, int code) + { + Operand::Kind kind = x.isXMM() ? (op.isBit(256) ? Operand::YMM : Operand::XMM) : Operand::ZMM; + opVex(x.copyAndSetKind(kind), &xm0, op, type, code); + } + void opCvt2(const Xmm& x, const Operand& op, int type, int code) + { + checkCvt2(x, op); + opCvt(x, op, type, code); + } + void opCvt3(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int type64, int type32, uint8_t code) + { + if (!(x1.isXMM() && x2.isXMM() && (op.isREG(i32e) || op.isMEM()))) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + Xmm x(op.getIdx()); + const Operand *p = op.isREG() ? &x : &op; + opVex(x1, &x2, *p, type | (op.isBit(64) ? type64 : type32), code); + } + // (x, x/y/xword/yword), (y, z/m) + void checkCvt4(const Xmm& x, const Operand& op) const + { + if (!(x.isXMM() && op.is(Operand::XMM | Operand::YMM | Operand::MEM) && op.isBit(128|256)) && !(x.isYMM() && op.is(Operand::ZMM | Operand::MEM))) XBYAK_THROW(ERR_BAD_COMBINATION) + } + // (x, x/y/z/xword/yword/zword) + void opCvt5(const Xmm& x, const Operand& op, int type, int code) + { + if (!(x.isXMM() && op.isBit(128|256|512))) XBYAK_THROW(ERR_BAD_COMBINATION) + Operand::Kind kind = op.isBit(128) ? Operand::XMM : op.isBit(256) ? Operand::YMM : Operand::ZMM; + opVex(x.copyAndSetKind(kind), &xm0, op, type, code); + } + const Xmm& cvtIdx0(const Operand& x) const + { + return x.isZMM() ? zm0 : x.isYMM() ? ym0 : xm0; + } + // support (x, x/m, imm), (y, y/m, imm) + void opAVX_X_XM_IMM(const Xmm& x, const Operand& op, int type, int code, int imm8 = NONE) + { + opAVX_X_X_XM(x, cvtIdx0(x), op, type, code, imm8); + } + // QQQ:need to refactor + void opSp1(const Reg& reg, const Operand& op, uint8_t pref, uint8_t code0, uint8_t code1) + { + if (reg.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) + bool is16bit = reg.isREG(16) && (op.isREG(16) || op.isMEM()); + if (!is16bit && !(reg.isREG(i32e) && (op.isREG(reg.getBit()) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) + if (is16bit) db(0x66); + db(pref); opModRM(reg.changeBit(i32e == 32 ? 32 : reg.getBit()), op, op.isREG(), true, code0, code1); + } + void opGather(const Xmm& x1, const Address& addr, const Xmm& x2, int type, uint8_t code, int mode) + { + const RegExp& regExp = addr.getRegExp(); + if (!regExp.isVsib(128 | 256)) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING) + const int y_vx_y = 0; + const int y_vy_y = 1; +// const int x_vy_x = 2; + const bool isAddrYMM = regExp.getIndex().getBit() == 256; + if (!x1.isXMM() || isAddrYMM || !x2.isXMM()) { + bool isOK = false; + if (mode == y_vx_y) { + isOK = x1.isYMM() && !isAddrYMM && x2.isYMM(); + } else if (mode == y_vy_y) { + isOK = x1.isYMM() && isAddrYMM && x2.isYMM(); + } else { // x_vy_x + isOK = !x1.isYMM() && isAddrYMM && !x2.isYMM(); + } + if (!isOK) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING) + } + int i1 = x1.getIdx(); + int i2 = regExp.getIndex().getIdx(); + int i3 = x2.getIdx(); + if (i1 == i2 || i1 == i3 || i2 == i3) XBYAK_THROW(ERR_SAME_REGS_ARE_INVALID); + opAVX_X_X_XM(isAddrYMM ? Ymm(i1) : x1, isAddrYMM ? Ymm(i3) : x2, addr, type, code); + } + enum { + xx_yy_zz = 0, + xx_yx_zy = 1, + xx_xy_yz = 2 + }; + void checkGather2(const Xmm& x1, const Reg& x2, int mode) const + { + if (x1.isXMM() && x2.isXMM()) return; + switch (mode) { + case xx_yy_zz: if ((x1.isYMM() && x2.isYMM()) || (x1.isZMM() && x2.isZMM())) return; + break; + case xx_yx_zy: if ((x1.isYMM() && x2.isXMM()) || (x1.isZMM() && x2.isYMM())) return; + break; + case xx_xy_yz: if ((x1.isXMM() && x2.isYMM()) || (x1.isYMM() && x2.isZMM())) return; + break; + } + XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING) + } + void opGather2(const Xmm& x, const Address& addr, int type, uint8_t code, int mode) + { + if (x.hasZero()) XBYAK_THROW(ERR_INVALID_ZERO) + const RegExp& regExp = addr.getRegExp(); + checkGather2(x, regExp.getIndex(), mode); + int maskIdx = x.getOpmaskIdx(); + if ((type & T_M_K) && addr.getOpmaskIdx()) maskIdx = addr.getOpmaskIdx(); + if (maskIdx == 0) XBYAK_THROW(ERR_K0_IS_INVALID); + if (!(type & T_M_K) && x.getIdx() == regExp.getIndex().getIdx()) XBYAK_THROW(ERR_SAME_REGS_ARE_INVALID); + opVex(x, 0, addr, type, code); + } + /* + xx_xy_yz ; mode = true + xx_xy_xz ; mode = false + */ + void opVmov(const Operand& op, const Xmm& x, int type, uint8_t code, bool mode) + { + if (mode) { + if (!op.isMEM() && !((op.isXMM() && x.isXMM()) || (op.isXMM() && x.isYMM()) || (op.isYMM() && x.isZMM()))) XBYAK_THROW(ERR_BAD_COMBINATION) + } else { + if (!op.isMEM() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) + } + opVex(x, 0, op, type, code); + } + void opGatherFetch(const Address& addr, const Xmm& x, int type, uint8_t code, Operand::Kind kind) + { + if (addr.hasZero()) XBYAK_THROW(ERR_INVALID_ZERO) + if (addr.getRegExp().getIndex().getKind() != kind) XBYAK_THROW(ERR_BAD_VSIB_ADDRESSING) + opVex(x, 0, addr, type, code); + } + void opEncoding(const Xmm& x1, const Xmm& x2, const Operand& op, int type, int code0, PreferredEncoding encoding) + { + opAVX_X_X_XM(x1, x2, op, type | orEvexIf(encoding), code0); + } + int orEvexIf(PreferredEncoding encoding) { + if (encoding == DefaultEncoding) { + encoding = defaultEncoding_; + } + if (encoding == EvexEncoding) { +#ifdef XBYAK_DISABLE_AVX512 + XBYAK_THROW(ERR_EVEX_IS_INVALID) +#endif + return T_MUST_EVEX; + } + return 0; + } + void opInOut(const Reg& a, const Reg& d, uint8_t code) + { + if (a.getIdx() == Operand::AL && d.getIdx() == Operand::DX && d.getBit() == 16) { + switch (a.getBit()) { + case 8: db(code); return; + case 16: db(0x66); db(code + 1); return; + case 32: db(code + 1); return; + } + } + XBYAK_THROW(ERR_BAD_COMBINATION) + } + void opInOut(const Reg& a, uint8_t code, uint8_t v) + { + if (a.getIdx() == Operand::AL) { + switch (a.getBit()) { + case 8: db(code); db(v); return; + case 16: db(0x66); db(code + 1); db(v); return; + case 32: db(code + 1); db(v); return; + } + } + XBYAK_THROW(ERR_BAD_COMBINATION) + } +#ifdef XBYAK64 + void opAMX(const Tmm& t1, const Address& addr, int type, int code0) + { + // require both base and index + const RegExp exp = addr.getRegExp(false); + if (exp.getBase().getBit() == 0 || exp.getIndex().getBit() == 0) XBYAK_THROW(ERR_NOT_SUPPORTED) + opVex(t1, &tmm0, addr, type, code0); + } +#endif +public: + unsigned int getVersion() const { return VERSION; } + using CodeArray::db; + const Mmx mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7; + const Xmm xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7; + const Ymm ymm0, ymm1, ymm2, ymm3, ymm4, ymm5, ymm6, ymm7; + const Zmm zmm0, zmm1, zmm2, zmm3, zmm4, zmm5, zmm6, zmm7; + const Xmm &xm0, &xm1, &xm2, &xm3, &xm4, &xm5, &xm6, &xm7; + const Ymm &ym0, &ym1, &ym2, &ym3, &ym4, &ym5, &ym6, &ym7; + const Zmm &zm0, &zm1, &zm2, &zm3, &zm4, &zm5, &zm6, &zm7; + const Reg32 eax, ecx, edx, ebx, esp, ebp, esi, edi; + const Reg16 ax, cx, dx, bx, sp, bp, si, di; + const Reg8 al, cl, dl, bl, ah, ch, dh, bh; + const AddressFrame ptr, byte, word, dword, qword, xword, yword, zword; // xword is same as oword of NASM + const AddressFrame ptr_b, xword_b, yword_b, zword_b; // broadcast such as {1to2}, {1to4}, {1to8}, {1to16}, {b} + const Fpu st0, st1, st2, st3, st4, st5, st6, st7; + const Opmask k0, k1, k2, k3, k4, k5, k6, k7; + const BoundsReg bnd0, bnd1, bnd2, bnd3; + 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} + const EvexModifierZero T_z; // {z} +#ifdef XBYAK64 + const Reg64 rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15; + const Reg32 r8d, r9d, r10d, r11d, r12d, r13d, r14d, r15d; + const Reg16 r8w, r9w, r10w, r11w, r12w, r13w, r14w, r15w; + const Reg8 r8b, r9b, r10b, r11b, r12b, r13b, r14b, r15b; + const Reg8 spl, bpl, sil, dil; + const Xmm xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15; + const Xmm xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23; + const Xmm xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31; + const Ymm ymm8, ymm9, ymm10, ymm11, ymm12, ymm13, ymm14, ymm15; + const Ymm ymm16, ymm17, ymm18, ymm19, ymm20, ymm21, ymm22, ymm23; + const Ymm ymm24, ymm25, ymm26, ymm27, ymm28, ymm29, ymm30, ymm31; + const Zmm zmm8, zmm9, zmm10, zmm11, zmm12, zmm13, zmm14, zmm15; + const Zmm zmm16, zmm17, zmm18, zmm19, zmm20, zmm21, zmm22, zmm23; + const Zmm zmm24, zmm25, zmm26, zmm27, zmm28, zmm29, zmm30, zmm31; + const Tmm tmm0, tmm1, tmm2, tmm3, tmm4, tmm5, tmm6, tmm7; + const Xmm &xm8, &xm9, &xm10, &xm11, &xm12, &xm13, &xm14, &xm15; // for my convenience + const Xmm &xm16, &xm17, &xm18, &xm19, &xm20, &xm21, &xm22, &xm23; + const Xmm &xm24, &xm25, &xm26, &xm27, &xm28, &xm29, &xm30, &xm31; + const Ymm &ym8, &ym9, &ym10, &ym11, &ym12, &ym13, &ym14, &ym15; + const Ymm &ym16, &ym17, &ym18, &ym19, &ym20, &ym21, &ym22, &ym23; + const Ymm &ym24, &ym25, &ym26, &ym27, &ym28, &ym29, &ym30, &ym31; + const Zmm &zm8, &zm9, &zm10, &zm11, &zm12, &zm13, &zm14, &zm15; + const Zmm &zm16, &zm17, &zm18, &zm19, &zm20, &zm21, &zm22, &zm23; + const Zmm &zm24, &zm25, &zm26, &zm27, &zm28, &zm29, &zm30, &zm31; + const RegRip rip; +#endif +#ifndef XBYAK_DISABLE_SEGMENT + const Segment es, cs, ss, ds, fs, gs; +#endif +private: + bool isDefaultJmpNEAR_; + PreferredEncoding defaultEncoding_; +public: + void L(const std::string& label) { labelMgr_.defineSlabel(label); } + void L(Label& label) { labelMgr_.defineClabel(label); } + Label L() { Label label; L(label); return label; } + void inLocalLabel() { labelMgr_.enterLocal(); } + void outLocalLabel() { labelMgr_.leaveLocal(); } + /* + assign src to dst + require + dst : does not used by L() + src : used by L() + */ + void assignL(Label& dst, const Label& src) { labelMgr_.assign(dst, src); } + /* + put address of label to buffer + @note the put size is 4(32-bit), 8(64-bit) + */ + void putL(std::string label) { putL_inner(label); } + void putL(const Label& label) { putL_inner(label); } + + // set default type of `jmp` of undefined label to T_NEAR + void setDefaultJmpNEAR(bool isNear) { isDefaultJmpNEAR_ = isNear; } + void jmp(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 4); } + void jmp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); } + void jmp(const char *label, LabelType type = T_AUTO) { jmp(std::string(label), type); } + void jmp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0xEB, 0xE9, 0); } + void jmp(const void *addr, LabelType type = T_AUTO) { opJmpAbs(addr, type, 0xEB, 0xE9); } + + void call(const Operand& op, LabelType type = T_AUTO) { opJmpOp(op, type, 2); } + // call(string label), not const std::string& + void call(std::string label) { opJmp(label, T_NEAR, 0, 0xE8, 0); } + void call(const char *label) { call(std::string(label)); } + void call(const Label& label) { opJmp(label, T_NEAR, 0, 0xE8, 0); } + // call(function pointer) +#ifdef XBYAK_VARIADIC_TEMPLATE + template<class Ret, class... Params> + void call(Ret(*func)(Params...)) { call(reinterpret_cast<const void*>(func)); } +#endif + void call(const void *addr) { opJmpAbs(addr, T_NEAR, 0, 0xE8); } + + void test(const Operand& op, const Reg& reg) + { + opModRM(reg, op, op.isREG() && (op.getKind() == reg.getKind()), op.isMEM(), 0x84); + } + void test(const Operand& op, uint32_t imm) + { + verifyMemHasSize(op); + int immSize = (std::min)(op.getBit() / 8, 4U); + if (op.isREG() && op.getIdx() == 0) { // al, ax, eax + rex(op); + db(0xA8 | (op.isBit(8) ? 0 : 1)); + } else { + opR_ModM(op, 0, 0, 0xF6, NONE, NONE, false, immSize); + } + db(imm, immSize); + } + void imul(const Reg& reg, const Operand& op) + { + opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x0F, 0xAF); + } + void imul(const Reg& reg, const Operand& op, int imm) + { + int s = inner::IsInDisp8(imm) ? 1 : 0; + int immSize = s ? 1 : reg.isREG(16) ? 2 : 4; + opModRM(reg, op, op.isREG() && (reg.getKind() == op.getKind()), op.isMEM(), 0x69 | (s << 1), NONE, NONE, immSize); + db(imm, immSize); + } + void push(const Operand& op) { opPushPop(op, 0xFF, 6, 0x50); } + void pop(const Operand& op) { opPushPop(op, 0x8F, 0, 0x58); } + void push(const AddressFrame& af, uint32_t imm) + { + if (af.bit_ == 8) { + db(0x6A); db(imm); + } else if (af.bit_ == 16) { + db(0x66); db(0x68); dw(imm); + } else { + db(0x68); dd(imm); + } + } + /* use "push(word, 4)" if you want "push word 4" */ + void push(uint32_t imm) + { + if (inner::IsInDisp8(imm)) { + push(byte, imm); + } else { + push(dword, imm); + } + } + void mov(const Operand& reg1, const Operand& reg2) + { + const Reg *reg = 0; + const Address *addr = 0; + uint8_t code = 0; + if (reg1.isREG() && reg1.getIdx() == 0 && reg2.isMEM()) { // mov eax|ax|al, [disp] + reg = ®1.getReg(); + addr= ®2.getAddress(); + code = 0xA0; + } else + if (reg1.isMEM() && reg2.isREG() && reg2.getIdx() == 0) { // mov [disp], eax|ax|al + reg = ®2.getReg(); + addr= ®1.getAddress(); + code = 0xA2; + } +#ifdef XBYAK64 + if (addr && addr->is64bitDisp()) { + if (code) { + rex(*reg); + db(reg1.isREG(8) ? 0xA0 : reg1.isREG() ? 0xA1 : reg2.isREG(8) ? 0xA2 : 0xA3); + db(addr->getDisp(), 8); + } else { + XBYAK_THROW(ERR_BAD_COMBINATION) + } + } else +#else + if (code && addr->isOnlyDisp()) { + rex(*reg, *addr); + db(code | (reg->isBit(8) ? 0 : 1)); + dd(static_cast<uint32_t>(addr->getDisp())); + } else +#endif + { + opRM_RM(reg1, reg2, 0x88); + } + } + void mov(const Operand& op, uint64_t imm) + { + if (op.isREG()) { + const int size = mov_imm(op.getReg(), imm); + db(imm, size); + } else if (op.isMEM()) { + verifyMemHasSize(op); + int immSize = op.getBit() / 8; + if (immSize <= 4) { + int64_t s = int64_t(imm) >> (immSize * 8); + if (s != 0 && s != -1) XBYAK_THROW(ERR_IMM_IS_TOO_BIG) + } else { + if (!inner::IsInInt32(imm)) XBYAK_THROW(ERR_IMM_IS_TOO_BIG) + immSize = 4; + } + opModM(op.getAddress(), Reg(0, Operand::REG, op.getBit()), 0xC6, NONE, NONE, immSize); + db(static_cast<uint32_t>(imm), immSize); + } else { + XBYAK_THROW(ERR_BAD_COMBINATION) + } + } + + // The template is used to avoid ambiguity when the 2nd argument is 0. + // When the 2nd argument is 0 the call goes to + // `void mov(const Operand& op, uint64_t imm)`. + template <typename T1, typename T2> + void mov(const T1&, const T2 *) { T1::unexpected; } + void mov(const NativeReg& reg, const Label& label) + { + mov_imm(reg, dummyAddr); + putL(label); + } + void xchg(const Operand& op1, const Operand& op2) + { + const Operand *p1 = &op1, *p2 = &op2; + if (p1->isMEM() || (p2->isREG(16 | i32e) && p2->getIdx() == 0)) { + p1 = &op2; p2 = &op1; + } + if (p1->isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) + if (p2->isREG() && (p1->isREG(16 | i32e) && p1->getIdx() == 0) +#ifdef XBYAK64 + && (p2->getIdx() != 0 || !p1->isREG(32)) +#endif + ) { + rex(*p2, *p1); db(0x90 | (p2->getIdx() & 7)); + return; + } + opModRM(*p1, *p2, (p1->isREG() && p2->isREG() && (p1->getBit() == p2->getBit())), p2->isMEM(), 0x86 | (p1->isBit(8) ? 0 : 1)); + } + +#ifndef XBYAK_DISABLE_SEGMENT + void push(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x06); break; + case Segment::cs: db(0x0E); break; + case Segment::ss: db(0x16); break; + case Segment::ds: db(0x1E); break; + case Segment::fs: db(0x0F); db(0xA0); break; + case Segment::gs: db(0x0F); db(0xA8); break; + default: + assert(0); + } + } + void pop(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x07); break; + case Segment::cs: XBYAK_THROW(ERR_BAD_COMBINATION) + case Segment::ss: db(0x17); break; + case Segment::ds: db(0x1F); break; + case Segment::fs: db(0x0F); db(0xA1); break; + case Segment::gs: db(0x0F); db(0xA9); break; + default: + assert(0); + } + } + void putSeg(const Segment& seg) + { + switch (seg.getIdx()) { + case Segment::es: db(0x2E); break; + case Segment::cs: db(0x36); break; + case Segment::ss: db(0x3E); break; + case Segment::ds: db(0x26); break; + case Segment::fs: db(0x64); break; + case Segment::gs: db(0x65); break; + default: + assert(0); + } + } + void mov(const Operand& op, const Segment& seg) + { + opModRM(Reg8(seg.getIdx()), op, op.isREG(16|i32e), op.isMEM(), 0x8C); + } + void mov(const Segment& seg, const Operand& op) + { + opModRM(Reg8(seg.getIdx()), op.isREG(16|i32e) ? static_cast<const Operand&>(op.getReg().cvt32()) : op, op.isREG(16|i32e), op.isMEM(), 0x8E); + } +#endif + + enum { NONE = 256 }; + // constructor + CodeGenerator(size_t maxSize = DEFAULT_MAX_CODE_SIZE, void *userPtr = 0, Allocator *allocator = 0) + : CodeArray(maxSize, userPtr, allocator) + , mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7) + , xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7) + , ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7) + , zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7) + // for my convenience + , xm0(xmm0), xm1(xmm1), xm2(xmm2), xm3(xmm3), xm4(xmm4), xm5(xmm5), xm6(xmm6), xm7(xmm7) + , ym0(ymm0), ym1(ymm1), ym2(ymm2), ym3(ymm3), ym4(ymm4), ym5(ymm5), ym6(ymm6), ym7(ymm7) + , zm0(zmm0), zm1(zmm1), zm2(zmm2), zm3(zmm3), zm4(zmm4), zm5(zmm5), zm6(zmm6), zm7(zmm7) + + , eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI) + , ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI) + , al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH) + , ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512) + , ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true) + , st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7) + , k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7) + , bnd0(0), bnd1(1), bnd2(2), bnd3(3) + , T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE) + , T_z() +#ifdef XBYAK64 + , 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) + , r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15) + , r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15) + , 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) + , xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15) + , xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23) + , xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31) + , ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15) + , ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23) + , ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31) + , zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15) + , zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23) + , zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31) + , tmm0(0), tmm1(1), tmm2(2), tmm3(3), tmm4(4), tmm5(5), tmm6(6), tmm7(7) + // for my convenience + , xm8(xmm8), xm9(xmm9), xm10(xmm10), xm11(xmm11), xm12(xmm12), xm13(xmm13), xm14(xmm14), xm15(xmm15) + , xm16(xmm16), xm17(xmm17), xm18(xmm18), xm19(xmm19), xm20(xmm20), xm21(xmm21), xm22(xmm22), xm23(xmm23) + , xm24(xmm24), xm25(xmm25), xm26(xmm26), xm27(xmm27), xm28(xmm28), xm29(xmm29), xm30(xmm30), xm31(xmm31) + , ym8(ymm8), ym9(ymm9), ym10(ymm10), ym11(ymm11), ym12(ymm12), ym13(ymm13), ym14(ymm14), ym15(ymm15) + , ym16(ymm16), ym17(ymm17), ym18(ymm18), ym19(ymm19), ym20(ymm20), ym21(ymm21), ym22(ymm22), ym23(ymm23) + , ym24(ymm24), ym25(ymm25), ym26(ymm26), ym27(ymm27), ym28(ymm28), ym29(ymm29), ym30(ymm30), ym31(ymm31) + , zm8(zmm8), zm9(zmm9), zm10(zmm10), zm11(zmm11), zm12(zmm12), zm13(zmm13), zm14(zmm14), zm15(zmm15) + , zm16(zmm16), zm17(zmm17), zm18(zmm18), zm19(zmm19), zm20(zmm20), zm21(zmm21), zm22(zmm22), zm23(zmm23) + , zm24(zmm24), zm25(zmm25), zm26(zmm26), zm27(zmm27), zm28(zmm28), zm29(zmm29), zm30(zmm30), zm31(zmm31) + , rip() +#endif +#ifndef XBYAK_DISABLE_SEGMENT + , es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs) +#endif + , isDefaultJmpNEAR_(false) + , defaultEncoding_(EvexEncoding) + { + labelMgr_.set(this); + } + void reset() + { + ClearError(); + resetSize(); + labelMgr_.reset(); + labelMgr_.set(this); + } + bool hasUndefinedLabel() const { return labelMgr_.hasUndefSlabel() || labelMgr_.hasUndefClabel(); } + /* + MUST call ready() to complete generating code if you use AutoGrow mode. + It is not necessary for the other mode if hasUndefinedLabel() is true. + */ + void ready(ProtectMode mode = PROTECT_RWE) + { + if (hasUndefinedLabel()) XBYAK_THROW(ERR_LABEL_IS_NOT_FOUND) + if (isAutoGrow()) { + calcJmpAddress(); + if (useProtect()) setProtectMode(mode); + } + } + // set read/exec + void readyRE() { return ready(PROTECT_RE); } +#ifdef XBYAK_TEST + void dump(bool doClear = true) + { + CodeArray::dump(); + if (doClear) size_ = 0; + } +#endif + +#ifdef XBYAK_UNDEF_JNL + #undef jnl +#endif + + // set default encoding to select Vex or Evex + void setDefaultEncoding(PreferredEncoding encoding) { defaultEncoding_ = encoding; } + + /* + use single byte nop if useMultiByteNop = false + */ + void nop(size_t size = 1, bool useMultiByteNop = true) + { + if (!useMultiByteNop) { + for (size_t i = 0; i < size; i++) { + db(0x90); + } + return; + } + /* + Intel Architectures Software Developer's Manual Volume 2 + recommended multi-byte sequence of NOP instruction + AMD and Intel seem to agree on the same sequences for up to 9 bytes: + https://support.amd.com/TechDocs/55723_SOG_Fam_17h_Processors_3.00.pdf + */ + static const uint8_t nopTbl[9][9] = { + {0x90}, + {0x66, 0x90}, + {0x0F, 0x1F, 0x00}, + {0x0F, 0x1F, 0x40, 0x00}, + {0x0F, 0x1F, 0x44, 0x00, 0x00}, + {0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00}, + {0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00}, + {0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + {0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00}, + }; + const size_t n = sizeof(nopTbl) / sizeof(nopTbl[0]); + while (size > 0) { + size_t len = (std::min)(n, size); + const uint8_t *seq = nopTbl[len - 1]; + db(seq, len); + size -= len; + } + } + +#ifndef XBYAK_DONT_READ_LIST +#include "xbyak_mnemonic.h" + /* + use single byte nop if useMultiByteNop = false + */ + void align(size_t x = 16, bool useMultiByteNop = true) + { + if (x == 1) return; + if (x < 1 || (x & (x - 1))) XBYAK_THROW(ERR_BAD_ALIGN) + if (isAutoGrow() && x > inner::ALIGN_PAGE_SIZE) fprintf(stderr, "warning:autoGrow mode does not support %d align\n", (int)x); + size_t remain = size_t(getCurr()) % x; + if (remain) { + nop(x - remain, useMultiByteNop); + } + } +#endif +}; + +template <> +inline void CodeGenerator::mov(const NativeReg& reg, const char *label) // can't use std::string +{ + assert(label); + mov_imm(reg, dummyAddr); + putL(label); +} + +namespace util { +static const XBYAK_CONSTEXPR Mmx mm0(0), mm1(1), mm2(2), mm3(3), mm4(4), mm5(5), mm6(6), mm7(7); +static const XBYAK_CONSTEXPR Xmm xmm0(0), xmm1(1), xmm2(2), xmm3(3), xmm4(4), xmm5(5), xmm6(6), xmm7(7); +static const XBYAK_CONSTEXPR Ymm ymm0(0), ymm1(1), ymm2(2), ymm3(3), ymm4(4), ymm5(5), ymm6(6), ymm7(7); +static const XBYAK_CONSTEXPR Zmm zmm0(0), zmm1(1), zmm2(2), zmm3(3), zmm4(4), zmm5(5), zmm6(6), zmm7(7); +static const XBYAK_CONSTEXPR Reg32 eax(Operand::EAX), ecx(Operand::ECX), edx(Operand::EDX), ebx(Operand::EBX), esp(Operand::ESP), ebp(Operand::EBP), esi(Operand::ESI), edi(Operand::EDI); +static const XBYAK_CONSTEXPR Reg16 ax(Operand::AX), cx(Operand::CX), dx(Operand::DX), bx(Operand::BX), sp(Operand::SP), bp(Operand::BP), si(Operand::SI), di(Operand::DI); +static const XBYAK_CONSTEXPR Reg8 al(Operand::AL), cl(Operand::CL), dl(Operand::DL), bl(Operand::BL), ah(Operand::AH), ch(Operand::CH), dh(Operand::DH), bh(Operand::BH); +static const XBYAK_CONSTEXPR AddressFrame ptr(0), byte(8), word(16), dword(32), qword(64), xword(128), yword(256), zword(512); +static const XBYAK_CONSTEXPR AddressFrame ptr_b(0, true), xword_b(128, true), yword_b(256, true), zword_b(512, true); +static const XBYAK_CONSTEXPR Fpu st0(0), st1(1), st2(2), st3(3), st4(4), st5(5), st6(6), st7(7); +static const XBYAK_CONSTEXPR Opmask k0(0), k1(1), k2(2), k3(3), k4(4), k5(5), k6(6), k7(7); +static const XBYAK_CONSTEXPR BoundsReg bnd0(0), bnd1(1), bnd2(2), bnd3(3); +static const XBYAK_CONSTEXPR EvexModifierRounding T_sae(EvexModifierRounding::T_SAE), T_rn_sae(EvexModifierRounding::T_RN_SAE), T_rd_sae(EvexModifierRounding::T_RD_SAE), T_ru_sae(EvexModifierRounding::T_RU_SAE), T_rz_sae(EvexModifierRounding::T_RZ_SAE); +static const XBYAK_CONSTEXPR EvexModifierZero T_z; +#ifdef XBYAK64 +static const XBYAK_CONSTEXPR 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); +static const XBYAK_CONSTEXPR Reg32 r8d(8), r9d(9), r10d(10), r11d(11), r12d(12), r13d(13), r14d(14), r15d(15); +static const XBYAK_CONSTEXPR Reg16 r8w(8), r9w(9), r10w(10), r11w(11), r12w(12), r13w(13), r14w(14), r15w(15); +static const XBYAK_CONSTEXPR 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); +static const XBYAK_CONSTEXPR Xmm xmm8(8), xmm9(9), xmm10(10), xmm11(11), xmm12(12), xmm13(13), xmm14(14), xmm15(15); +static const XBYAK_CONSTEXPR Xmm xmm16(16), xmm17(17), xmm18(18), xmm19(19), xmm20(20), xmm21(21), xmm22(22), xmm23(23); +static const XBYAK_CONSTEXPR Xmm xmm24(24), xmm25(25), xmm26(26), xmm27(27), xmm28(28), xmm29(29), xmm30(30), xmm31(31); +static const XBYAK_CONSTEXPR Ymm ymm8(8), ymm9(9), ymm10(10), ymm11(11), ymm12(12), ymm13(13), ymm14(14), ymm15(15); +static const XBYAK_CONSTEXPR Ymm ymm16(16), ymm17(17), ymm18(18), ymm19(19), ymm20(20), ymm21(21), ymm22(22), ymm23(23); +static const XBYAK_CONSTEXPR Ymm ymm24(24), ymm25(25), ymm26(26), ymm27(27), ymm28(28), ymm29(29), ymm30(30), ymm31(31); +static const XBYAK_CONSTEXPR Zmm zmm8(8), zmm9(9), zmm10(10), zmm11(11), zmm12(12), zmm13(13), zmm14(14), zmm15(15); +static const XBYAK_CONSTEXPR Zmm zmm16(16), zmm17(17), zmm18(18), zmm19(19), zmm20(20), zmm21(21), zmm22(22), zmm23(23); +static const XBYAK_CONSTEXPR Zmm zmm24(24), zmm25(25), zmm26(26), zmm27(27), zmm28(28), zmm29(29), zmm30(30), zmm31(31); +static const XBYAK_CONSTEXPR Zmm tmm0(0), tmm1(1), tmm2(2), tmm3(3), tmm4(4), tmm5(5), tmm6(6), tmm7(7); +static const XBYAK_CONSTEXPR RegRip rip; +#endif +#ifndef XBYAK_DISABLE_SEGMENT +static const XBYAK_CONSTEXPR Segment es(Segment::es), cs(Segment::cs), ss(Segment::ss), ds(Segment::ds), fs(Segment::fs), gs(Segment::gs); +#endif +} // util + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#if defined(__GNUC__) && !defined(__clang__) + #pragma GCC diagnostic pop +#endif + +} // end of namespace + +#endif // XBYAK_XBYAK_H_ diff --git a/xbyak/xbyak_bin2hex.h b/xbyak/xbyak_bin2hex.h new file mode 100644 index 0000000..69ecdbf --- /dev/null +++ b/xbyak/xbyak_bin2hex.h @@ -0,0 +1,258 @@ +enum { + B00000000= 0, + B00000001= 1, + B00000010= 2, + B00000011= 3, + B00000100= 4, + B00000101= 5, + B00000110= 6, + B00000111= 7, + B00001000= 8, + B00001001= 9, + B00001010= 10, + B00001011= 11, + B00001100= 12, + B00001101= 13, + B00001110= 14, + B00001111= 15, + B00010000= 16, + B00010001= 17, + B00010010= 18, + B00010011= 19, + B00010100= 20, + B00010101= 21, + B00010110= 22, + B00010111= 23, + B00011000= 24, + B00011001= 25, + B00011010= 26, + B00011011= 27, + B00011100= 28, + B00011101= 29, + B00011110= 30, + B00011111= 31, + B00100000= 32, + B00100001= 33, + B00100010= 34, + B00100011= 35, + B00100100= 36, + B00100101= 37, + B00100110= 38, + B00100111= 39, + B00101000= 40, + B00101001= 41, + B00101010= 42, + B00101011= 43, + B00101100= 44, + B00101101= 45, + B00101110= 46, + B00101111= 47, + B00110000= 48, + B00110001= 49, + B00110010= 50, + B00110011= 51, + B00110100= 52, + B00110101= 53, + B00110110= 54, + B00110111= 55, + B00111000= 56, + B00111001= 57, + B00111010= 58, + B00111011= 59, + B00111100= 60, + B00111101= 61, + B00111110= 62, + B00111111= 63, + B01000000= 64, + B01000001= 65, + B01000010= 66, + B01000011= 67, + B01000100= 68, + B01000101= 69, + B01000110= 70, + B01000111= 71, + B01001000= 72, + B01001001= 73, + B01001010= 74, + B01001011= 75, + B01001100= 76, + B01001101= 77, + B01001110= 78, + B01001111= 79, + B01010000= 80, + B01010001= 81, + B01010010= 82, + B01010011= 83, + B01010100= 84, + B01010101= 85, + B01010110= 86, + B01010111= 87, + B01011000= 88, + B01011001= 89, + B01011010= 90, + B01011011= 91, + B01011100= 92, + B01011101= 93, + B01011110= 94, + B01011111= 95, + B01100000= 96, + B01100001= 97, + B01100010= 98, + B01100011= 99, + B01100100= 100, + B01100101= 101, + B01100110= 102, + B01100111= 103, + B01101000= 104, + B01101001= 105, + B01101010= 106, + B01101011= 107, + B01101100= 108, + B01101101= 109, + B01101110= 110, + B01101111= 111, + B01110000= 112, + B01110001= 113, + B01110010= 114, + B01110011= 115, + B01110100= 116, + B01110101= 117, + B01110110= 118, + B01110111= 119, + B01111000= 120, + B01111001= 121, + B01111010= 122, + B01111011= 123, + B01111100= 124, + B01111101= 125, + B01111110= 126, + B01111111= 127, + B10000000= 128, + B10000001= 129, + B10000010= 130, + B10000011= 131, + B10000100= 132, + B10000101= 133, + B10000110= 134, + B10000111= 135, + B10001000= 136, + B10001001= 137, + B10001010= 138, + B10001011= 139, + B10001100= 140, + B10001101= 141, + B10001110= 142, + B10001111= 143, + B10010000= 144, + B10010001= 145, + B10010010= 146, + B10010011= 147, + B10010100= 148, + B10010101= 149, + B10010110= 150, + B10010111= 151, + B10011000= 152, + B10011001= 153, + B10011010= 154, + B10011011= 155, + B10011100= 156, + B10011101= 157, + B10011110= 158, + B10011111= 159, + B10100000= 160, + B10100001= 161, + B10100010= 162, + B10100011= 163, + B10100100= 164, + B10100101= 165, + B10100110= 166, + B10100111= 167, + B10101000= 168, + B10101001= 169, + B10101010= 170, + B10101011= 171, + B10101100= 172, + B10101101= 173, + B10101110= 174, + B10101111= 175, + B10110000= 176, + B10110001= 177, + B10110010= 178, + B10110011= 179, + B10110100= 180, + B10110101= 181, + B10110110= 182, + B10110111= 183, + B10111000= 184, + B10111001= 185, + B10111010= 186, + B10111011= 187, + B10111100= 188, + B10111101= 189, + B10111110= 190, + B10111111= 191, + B11000000= 192, + B11000001= 193, + B11000010= 194, + B11000011= 195, + B11000100= 196, + B11000101= 197, + B11000110= 198, + B11000111= 199, + B11001000= 200, + B11001001= 201, + B11001010= 202, + B11001011= 203, + B11001100= 204, + B11001101= 205, + B11001110= 206, + B11001111= 207, + B11010000= 208, + B11010001= 209, + B11010010= 210, + B11010011= 211, + B11010100= 212, + B11010101= 213, + B11010110= 214, + B11010111= 215, + B11011000= 216, + B11011001= 217, + B11011010= 218, + B11011011= 219, + B11011100= 220, + B11011101= 221, + B11011110= 222, + B11011111= 223, + B11100000= 224, + B11100001= 225, + B11100010= 226, + B11100011= 227, + B11100100= 228, + B11100101= 229, + B11100110= 230, + B11100111= 231, + B11101000= 232, + B11101001= 233, + B11101010= 234, + B11101011= 235, + B11101100= 236, + B11101101= 237, + B11101110= 238, + B11101111= 239, + B11110000= 240, + B11110001= 241, + B11110010= 242, + B11110011= 243, + B11110100= 244, + B11110101= 245, + B11110110= 246, + B11110111= 247, + B11111000= 248, + B11111001= 249, + B11111010= 250, + B11111011= 251, + B11111100= 252, + B11111101= 253, + B11111110= 254, + B11111111= 255 +}; diff --git a/xbyak/xbyak_mnemonic.h b/xbyak/xbyak_mnemonic.h new file mode 100644 index 0000000..cc657fd --- /dev/null +++ b/xbyak/xbyak_mnemonic.h @@ -0,0 +1,2329 @@ +const char *getVersionString() const { return "6.67"; } +void aadd(const Address& addr, const Reg32e ®) { opModM(addr, reg, 0x0F, 0x38, 0x0FC); } +void aand(const Address& addr, const Reg32e ®) { db(0x66); opModM(addr, reg, 0x0F, 0x38, 0x0FC); } +void adc(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x10, 2); } +void adc(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x10); } +void adcx(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0x66, isREG32_REG32orMEM, NONE, 0x38); } +void add(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x00, 0); } +void add(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x00); } +void addpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x66, isXMM_XMMorMEM); } +void addps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0x100, isXMM_XMMorMEM); } +void addsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF2, isXMM_XMMorMEM); } +void addss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x58, 0xF3, isXMM_XMMorMEM); } +void addsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0x66, isXMM_XMMorMEM); } +void addsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xD0, 0xF2, isXMM_XMMorMEM); } +void adox(const Reg32e& reg, const Operand& op) { opGen(reg, op, 0xF6, 0xF3, isREG32_REG32orMEM, NONE, 0x38); } +void aesdec(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDE, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesdeclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesenc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDC, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesenclast(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDD, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aesimc(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xDB, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void aeskeygenassist(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0xDF, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void and_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x20, 4); } +void and_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x20); } +void andn(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_0F38, 0xf2, true); } +void andnpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x66, isXMM_XMMorMEM); } +void andnps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x55, 0x100, isXMM_XMMorMEM); } +void andpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x66, isXMM_XMMorMEM); } +void andps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x54, 0x100, isXMM_XMMorMEM); } +void aor(const Address& addr, const Reg32e ®) { db(0xF2); opModM(addr, reg, 0x0F, 0x38, 0x0FC); } +void axor(const Address& addr, const Reg32e ®) { db(0xF3); opModM(addr, reg, 0x0F, 0x38, 0x0FC); } +void bextr(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf7, false); } +void blendpd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0D, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void blendps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0C, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void blendvpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void blendvps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void blsi(const Reg32e& r, const Operand& op) { opGpr(Reg32e(3, r.getBit()), op, r, T_0F38, 0xf3, false); } +void blsmsk(const Reg32e& r, const Operand& op) { opGpr(Reg32e(2, r.getBit()), op, r, T_0F38, 0xf3, false); } +void blsr(const Reg32e& r, const Operand& op) { opGpr(Reg32e(1, r.getBit()), op, r, T_0F38, 0xf3, false); } +void bnd() { db(0xF2); } +void bndcl(const BoundsReg& bnd, const Operand& op) { db(0xF3); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } +void bndcn(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1B, NONE, !op.isMEM()); } +void bndcu(const BoundsReg& bnd, const Operand& op) { db(0xF2); opR_ModM(op, i32e, bnd.getIdx(), 0x0F, 0x1A, NONE, !op.isMEM()); } +void bndldx(const BoundsReg& bnd, const Address& addr) { opMIB(addr, bnd, 0x0F, 0x1A); } +void bndmk(const BoundsReg& bnd, const Address& addr) { db(0xF3); opModM(addr, bnd, 0x0F, 0x1B); } +void bndmov(const Address& addr, const BoundsReg& bnd) { db(0x66); opModM(addr, bnd, 0x0F, 0x1B); } +void bndmov(const BoundsReg& bnd, const Operand& op) { db(0x66); opModRM(bnd, op, op.isBNDREG(), op.isMEM(), 0x0F, 0x1A); } +void bndstx(const Address& addr, const BoundsReg& bnd) { opMIB(addr, bnd, 0x0F, 0x1B); } +void bsf(const Reg®, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBC); } +void bsr(const Reg®, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0xBD); } +void bswap(const Reg32e& reg) { opModR(Reg32(1), reg, 0x0F); } +void bt(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xA3); } +void bt(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 4, 0x0f, 0xba, NONE, false, 1); db(imm); } +void btc(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xBB); } +void btc(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 7, 0x0f, 0xba, NONE, false, 1); db(imm); } +void btr(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xB3); } +void btr(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 6, 0x0f, 0xba, NONE, false, 1); db(imm); } +void bts(const Operand& op, const Reg& reg) { opModRM(reg, op, op.isREG(16|32|64) && op.getBit() == reg.getBit(), op.isMEM(), 0x0f, 0xAB); } +void bts(const Operand& op, uint8_t imm) { opR_ModM(op, 16|32|64, 5, 0x0f, 0xba, NONE, false, 1); db(imm); } +void bzhi(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_0F38, 0xf5, false); } +void cbw() { db(0x66); db(0x98); } +void cdq() { db(0x99); } +void clc() { db(0xF8); } +void cld() { db(0xFC); } +void cldemote(const Address& addr) { opMIB(addr, eax, 0x0F, 0x1C); } +void clflush(const Address& addr) { opModM(addr, Reg32(7), 0x0F, 0xAE); } +void clflushopt(const Address& addr) { db(0x66); opModM(addr, Reg32(7), 0x0F, 0xAE); } +void cli() { db(0xFA); } +void clwb(const Address& addr) { db(0x66); opMIB(addr, esi, 0x0F, 0xAE); } +void clzero() { db(0x0F); db(0x01); db(0xFC); } +void cmc() { db(0xF5); } +void cmova(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524 +void cmovae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmovbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524 +void cmovc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmove(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524 +void cmovg(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524 +void cmovge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524 +void cmovl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524 +void cmovle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524 +void cmovna(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 6); }//-V524 +void cmovnae(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 2); }//-V524 +void cmovnb(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovnbe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 7); }//-V524 +void cmovnc(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 3); }//-V524 +void cmovne(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524 +void cmovng(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 14); }//-V524 +void cmovnge(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 12); }//-V524 +void cmovnl(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 13); }//-V524 +void cmovnle(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 15); }//-V524 +void cmovno(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 1); }//-V524 +void cmovnp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524 +void cmovns(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 9); }//-V524 +void cmovnz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 5); }//-V524 +void cmovo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 0); }//-V524 +void cmovp(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524 +void cmovpe(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 10); }//-V524 +void cmovpo(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 11); }//-V524 +void cmovs(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 8); }//-V524 +void cmovz(const Reg& reg, const Operand& op) { opModRM(reg, op, op.isREG(16 | i32e), op.isMEM(), 0x0F, 0x40 | 4); }//-V524 +void cmp(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x38, 7); } +void cmp(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x38); } +void cmpeqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 0); } +void cmpeqps(const Xmm& x, const Operand& op) { cmpps(x, op, 0); } +void cmpeqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 0); } +void cmpeqss(const Xmm& x, const Operand& op) { cmpss(x, op, 0); } +void cmplepd(const Xmm& x, const Operand& op) { cmppd(x, op, 2); } +void cmpleps(const Xmm& x, const Operand& op) { cmpps(x, op, 2); } +void cmplesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 2); } +void cmpless(const Xmm& x, const Operand& op) { cmpss(x, op, 2); } +void cmpltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 1); } +void cmpltps(const Xmm& x, const Operand& op) { cmpps(x, op, 1); } +void cmpltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 1); } +void cmpltss(const Xmm& x, const Operand& op) { cmpss(x, op, 1); } +void cmpneqpd(const Xmm& x, const Operand& op) { cmppd(x, op, 4); } +void cmpneqps(const Xmm& x, const Operand& op) { cmpps(x, op, 4); } +void cmpneqsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 4); } +void cmpneqss(const Xmm& x, const Operand& op) { cmpss(x, op, 4); } +void cmpnlepd(const Xmm& x, const Operand& op) { cmppd(x, op, 6); } +void cmpnleps(const Xmm& x, const Operand& op) { cmpps(x, op, 6); } +void cmpnlesd(const Xmm& x, const Operand& op) { cmpsd(x, op, 6); } +void cmpnless(const Xmm& x, const Operand& op) { cmpss(x, op, 6); } +void cmpnltpd(const Xmm& x, const Operand& op) { cmppd(x, op, 5); } +void cmpnltps(const Xmm& x, const Operand& op) { cmpps(x, op, 5); } +void cmpnltsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 5); } +void cmpnltss(const Xmm& x, const Operand& op) { cmpss(x, op, 5); } +void cmpordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 7); } +void cmpordps(const Xmm& x, const Operand& op) { cmpps(x, op, 7); } +void cmpordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 7); } +void cmpordss(const Xmm& x, const Operand& op) { cmpss(x, op, 7); } +void cmppd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0x66, isXMM_XMMorMEM, imm8); } +void cmpps(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0x100, isXMM_XMMorMEM, imm8); } +void cmpsb() { db(0xA6); } +void cmpsd() { db(0xA7); } +void cmpsd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0xF2, isXMM_XMMorMEM, imm8); } +void cmpss(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC2, 0xF3, isXMM_XMMorMEM, imm8); } +void cmpsw() { db(0x66); db(0xA7); } +void cmpunordpd(const Xmm& x, const Operand& op) { cmppd(x, op, 3); } +void cmpunordps(const Xmm& x, const Operand& op) { cmpps(x, op, 3); } +void cmpunordsd(const Xmm& x, const Operand& op) { cmpsd(x, op, 3); } +void cmpunordss(const Xmm& x, const Operand& op) { cmpss(x, op, 3); } +void cmpxchg(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xB0 | (reg.isBit(8) ? 0 : 1)); } +void cmpxchg8b(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xC7); } +void comisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x66, isXMM_XMMorMEM); } +void comiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2F, 0x100, isXMM_XMMorMEM); } +void cpuid() { db(0x0F); db(0xA2); } +void crc32(const Reg32e& reg, const Operand& op) { if (reg.isBit(32) && op.isBit(16)) db(0x66); db(0xF2); opModRM(reg, op, op.isREG(), op.isMEM(), 0x0F, 0x38, 0xF0 | (op.isBit(8) ? 0 : 1)); } +void cvtdq2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF3, isXMM_XMMorMEM); } +void cvtdq2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x100, isXMM_XMMorMEM); } +void cvtpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0xF2, isXMM_XMMorMEM); } +void cvtpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x66, isMMX_XMMorMEM); } +void cvtpd2ps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x66, isXMM_XMMorMEM); } +void cvtpi2pd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x66, isXMM_MMXorMEM); } +void cvtpi2ps(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0x100, isXMM_MMXorMEM); } +void cvtps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0x66, isXMM_XMMorMEM); } +void cvtps2pd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0x100, isXMM_XMMorMEM); } +void cvtps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0x100, isMMX_XMMorMEM); } +void cvtsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF2, isREG32_XMMorMEM); } +void cvtsd2ss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF2, isXMM_XMMorMEM); } +void cvtsi2sd(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF2, isXMM_REG32orMEM); } +void cvtsi2ss(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2A, 0xF3, isXMM_REG32orMEM); } +void cvtss2sd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5A, 0xF3, isXMM_XMMorMEM); } +void cvtss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2D, 0xF3, isREG32_XMMorMEM); } +void cvttpd2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xE6, 0x66, isXMM_XMMorMEM); } +void cvttpd2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x66, isMMX_XMMorMEM); } +void cvttps2dq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5B, 0xF3, isXMM_XMMorMEM); } +void cvttps2pi(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0x100, isMMX_XMMorMEM); } +void cvttsd2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF2, isREG32_XMMorMEM); } +void cvttss2si(const Operand& reg, const Operand& op) { opGen(reg, op, 0x2C, 0xF3, isREG32_XMMorMEM); } +void cwd() { db(0x66); db(0x99); } +void cwde() { db(0x98); } +void dec(const Operand& op) { opIncDec(op, 0x48, 1); } +void div(const Operand& op) { opR_ModM(op, 0, 6, 0xF6); } +void divpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x66, isXMM_XMMorMEM); } +void divps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0x100, isXMM_XMMorMEM); } +void divsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF2, isXMM_XMMorMEM); } +void divss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5E, 0xF3, isXMM_XMMorMEM); } +void dppd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void dpps(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void emms() { db(0x0F); db(0x77); } +void endbr32() { db(0xF3); db(0x0F); db(0x1E); db(0xFB); } +void endbr64() { db(0xF3); db(0x0F); db(0x1E); db(0xFA); } +void enter(uint16_t x, uint8_t y) { db(0xC8); dw(x); db(y); } +void extractps(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x17, imm); } +void f2xm1() { db(0xD9); db(0xF0); } +void fabs() { db(0xD9); db(0xE1); } +void fadd(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 0, 0); } +void fadd(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C0, 0xDCC0); } +void fadd(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C0, 0xDCC0); } +void faddp() { db(0xDE); db(0xC1); } +void faddp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC0); } +void faddp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC0); } +void fbld(const Address& addr) { opModM(addr, Reg32(4), 0xDF, 0x100); } +void fbstp(const Address& addr) { opModM(addr, Reg32(6), 0xDF, 0x100); } +void fchs() { db(0xD9); db(0xE0); } +void fclex() { db(0x9B); db(0xDB); db(0xE2); } +void fcmovb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC0, 0x00C0); } +void fcmovb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC0, 0x00C0); } +void fcmovbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD0, 0x00D0); } +void fcmovbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD0, 0x00D0); } +void fcmove(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAC8, 0x00C8); } +void fcmove(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAC8, 0x00C8); } +void fcmovnb(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC0, 0x00C0); } +void fcmovnb(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC0, 0x00C0); } +void fcmovnbe(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD0, 0x00D0); } +void fcmovnbe(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD0, 0x00D0); } +void fcmovne(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBC8, 0x00C8); } +void fcmovne(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBC8, 0x00C8); } +void fcmovnu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBD8, 0x00D8); } +void fcmovnu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBD8, 0x00D8); } +void fcmovu(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDAD8, 0x00D8); } +void fcmovu(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDAD8, 0x00D8); } +void fcom() { db(0xD8); db(0xD1); } +void fcom(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 2, 0); } +void fcom(const Fpu& reg) { opFpu(reg, 0xD8, 0xD0); } +void fcomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBF0, 0x00F0); } +void fcomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBF0, 0x00F0); } +void fcomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFF0, 0x00F0); } +void fcomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFF0, 0x00F0); } +void fcomp() { db(0xD8); db(0xD9); } +void fcomp(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 3, 0); } +void fcomp(const Fpu& reg) { opFpu(reg, 0xD8, 0xD8); } +void fcompp() { db(0xDE); db(0xD9); } +void fcos() { db(0xD9); db(0xFF); } +void fdecstp() { db(0xD9); db(0xF6); } +void fdiv(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 6, 0); } +void fdiv(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F0, 0xDCF8); } +void fdiv(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F0, 0xDCF8); } +void fdivp() { db(0xDE); db(0xF9); } +void fdivp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF8); } +void fdivp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF8); } +void fdivr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 7, 0); } +void fdivr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8F8, 0xDCF0); } +void fdivr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8F8, 0xDCF0); } +void fdivrp() { db(0xDE); db(0xF1); } +void fdivrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEF0); } +void fdivrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEF0); } +void ffree(const Fpu& reg) { opFpu(reg, 0xDD, 0xC0); } +void fiadd(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 0, 0); } +void ficom(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 2, 0); } +void ficomp(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 3, 0); } +void fidiv(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 6, 0); } +void fidivr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 7, 0); } +void fild(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 0, 5); } +void fimul(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 1, 0); } +void fincstp() { db(0xD9); db(0xF7); } +void finit() { db(0x9B); db(0xDB); db(0xE3); } +void fist(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0x00, 2, 0); } +void fistp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDF, 3, 7); } +void fisttp(const Address& addr) { opFpuMem(addr, 0xDF, 0xDB, 0xDD, 1, 0); } +void fisub(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 4, 0); } +void fisubr(const Address& addr) { opFpuMem(addr, 0xDE, 0xDA, 0x00, 5, 0); } +void fld(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 0, 0); } +void fld(const Fpu& reg) { opFpu(reg, 0xD9, 0xC0); } +void fld1() { db(0xD9); db(0xE8); } +void fldcw(const Address& addr) { opModM(addr, Reg32(5), 0xD9, 0x100); } +void fldenv(const Address& addr) { opModM(addr, Reg32(4), 0xD9, 0x100); } +void fldl2e() { db(0xD9); db(0xEA); } +void fldl2t() { db(0xD9); db(0xE9); } +void fldlg2() { db(0xD9); db(0xEC); } +void fldln2() { db(0xD9); db(0xED); } +void fldpi() { db(0xD9); db(0xEB); } +void fldz() { db(0xD9); db(0xEE); } +void fmul(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 1, 0); } +void fmul(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8C8, 0xDCC8); } +void fmul(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8C8, 0xDCC8); } +void fmulp() { db(0xDE); db(0xC9); } +void fmulp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEC8); } +void fmulp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEC8); } +void fnclex() { db(0xDB); db(0xE2); } +void fninit() { db(0xDB); db(0xE3); } +void fnop() { db(0xD9); db(0xD0); } +void fnsave(const Address& addr) { opModM(addr, Reg32(6), 0xDD, 0x100); } +void fnstcw(const Address& addr) { opModM(addr, Reg32(7), 0xD9, 0x100); } +void fnstenv(const Address& addr) { opModM(addr, Reg32(6), 0xD9, 0x100); } +void fnstsw(const Address& addr) { opModM(addr, Reg32(7), 0xDD, 0x100); } +void fnstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xDF); db(0xE0); } +void fpatan() { db(0xD9); db(0xF3); } +void fprem() { db(0xD9); db(0xF8); } +void fprem1() { db(0xD9); db(0xF5); } +void fptan() { db(0xD9); db(0xF2); } +void frndint() { db(0xD9); db(0xFC); } +void frstor(const Address& addr) { opModM(addr, Reg32(4), 0xDD, 0x100); } +void fsave(const Address& addr) { db(0x9B); opModM(addr, Reg32(6), 0xDD, 0x100); } +void fscale() { db(0xD9); db(0xFD); } +void fsin() { db(0xD9); db(0xFE); } +void fsincos() { db(0xD9); db(0xFB); } +void fsqrt() { db(0xD9); db(0xFA); } +void fst(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 2, 0); } +void fst(const Fpu& reg) { opFpu(reg, 0xDD, 0xD0); } +void fstcw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xD9, 0x100); } +void fstenv(const Address& addr) { db(0x9B); opModM(addr, Reg32(6), 0xD9, 0x100); } +void fstp(const Address& addr) { opFpuMem(addr, 0x00, 0xD9, 0xDD, 3, 0); } +void fstp(const Fpu& reg) { opFpu(reg, 0xDD, 0xD8); } +void fstsw(const Address& addr) { db(0x9B); opModM(addr, Reg32(7), 0xDD, 0x100); } +void fstsw(const Reg16& r) { if (r.getIdx() != Operand::AX) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x9B); db(0xDF); db(0xE0); } +void fsub(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 4, 0); } +void fsub(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E0, 0xDCE8); } +void fsub(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E0, 0xDCE8); } +void fsubp() { db(0xDE); db(0xE9); } +void fsubp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE8); } +void fsubp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE8); } +void fsubr(const Address& addr) { opFpuMem(addr, 0x00, 0xD8, 0xDC, 5, 0); } +void fsubr(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xD8E8, 0xDCE0); } +void fsubr(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xD8E8, 0xDCE0); } +void fsubrp() { db(0xDE); db(0xE1); } +void fsubrp(const Fpu& reg1) { opFpuFpu(reg1, st0, 0x0000, 0xDEE0); } +void fsubrp(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0x0000, 0xDEE0); } +void ftst() { db(0xD9); db(0xE4); } +void fucom() { db(0xDD); db(0xE1); } +void fucom(const Fpu& reg) { opFpu(reg, 0xDD, 0xE0); } +void fucomi(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDBE8, 0x00E8); } +void fucomi(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDBE8, 0x00E8); } +void fucomip(const Fpu& reg1) { opFpuFpu(st0, reg1, 0xDFE8, 0x00E8); } +void fucomip(const Fpu& reg1, const Fpu& reg2) { opFpuFpu(reg1, reg2, 0xDFE8, 0x00E8); } +void fucomp() { db(0xDD); db(0xE9); } +void fucomp(const Fpu& reg) { opFpu(reg, 0xDD, 0xE8); } +void fucompp() { db(0xDA); db(0xE9); } +void fwait() { db(0x9B); } +void fxam() { db(0xD9); db(0xE5); } +void fxch() { db(0xD9); db(0xC9); } +void fxch(const Fpu& reg) { opFpu(reg, 0xD9, 0xC8); } +void fxrstor(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0xAE); } +void fxtract() { db(0xD9); db(0xF4); } +void fyl2x() { db(0xD9); db(0xF1); } +void fyl2xp1() { db(0xD9); db(0xF9); } +void gf2p8affineinvqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void gf2p8affineqb(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0xCE, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void gf2p8mulb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCF, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void haddpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0x66, isXMM_XMMorMEM); } +void haddps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7C, 0xF2, isXMM_XMMorMEM); } +void hlt() { db(0xF4); } +void hsubpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0x66, isXMM_XMMorMEM); } +void hsubps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x7D, 0xF2, isXMM_XMMorMEM); } +void idiv(const Operand& op) { opR_ModM(op, 0, 7, 0xF6); } +void imul(const Operand& op) { opR_ModM(op, 0, 5, 0xF6); } +void in_(const Reg& a, const Reg& d) { opInOut(a, d, 0xEC); } +void in_(const Reg& a, uint8_t v) { opInOut(a, 0xE4, v); } +void inc(const Operand& op) { opIncDec(op, 0x40, 0); } +void insertps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void int3() { db(0xCC); } +void int_(uint8_t x) { db(0xCD); db(x); } +void ja(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void ja(const char *label, LabelType type = T_AUTO) { ja(std::string(label), type); }//-V524 +void ja(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524 +void ja(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jae(const char *label, LabelType type = T_AUTO) { jae(std::string(label), type); }//-V524 +void jae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jb(const char *label, LabelType type = T_AUTO) { jb(std::string(label), type); }//-V524 +void jb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jbe(const char *label, LabelType type = T_AUTO) { jbe(std::string(label), type); }//-V524 +void jbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524 +void jbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jc(const char *label, LabelType type = T_AUTO) { jc(std::string(label), type); }//-V524 +void jc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void je(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void je(const char *label, LabelType type = T_AUTO) { je(std::string(label), type); }//-V524 +void je(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524 +void je(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void jg(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jg(const char *label, LabelType type = T_AUTO) { jg(std::string(label), type); }//-V524 +void jg(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524 +void jg(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jge(const char *label, LabelType type = T_AUTO) { jge(std::string(label), type); }//-V524 +void jge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524 +void jge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jl(const char *label, LabelType type = T_AUTO) { jl(std::string(label), type); }//-V524 +void jl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524 +void jl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jle(const char *label, LabelType type = T_AUTO) { jle(std::string(label), type); }//-V524 +void jle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524 +void jle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jna(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jna(const char *label, LabelType type = T_AUTO) { jna(std::string(label), type); }//-V524 +void jna(const void *addr) { opJmpAbs(addr, T_NEAR, 0x76, 0x86, 0x0F); }//-V524 +void jna(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x76, 0x86, 0x0F); }//-V524 +void jnae(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jnae(const char *label, LabelType type = T_AUTO) { jnae(std::string(label), type); }//-V524 +void jnae(const void *addr) { opJmpAbs(addr, T_NEAR, 0x72, 0x82, 0x0F); }//-V524 +void jnae(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x72, 0x82, 0x0F); }//-V524 +void jnb(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnb(const char *label, LabelType type = T_AUTO) { jnb(std::string(label), type); }//-V524 +void jnb(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jnb(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnbe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jnbe(const char *label, LabelType type = T_AUTO) { jnbe(std::string(label), type); }//-V524 +void jnbe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x77, 0x87, 0x0F); }//-V524 +void jnbe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x77, 0x87, 0x0F); }//-V524 +void jnc(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jnc(const char *label, LabelType type = T_AUTO) { jnc(std::string(label), type); }//-V524 +void jnc(const void *addr) { opJmpAbs(addr, T_NEAR, 0x73, 0x83, 0x0F); }//-V524 +void jnc(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x73, 0x83, 0x0F); }//-V524 +void jne(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jne(const char *label, LabelType type = T_AUTO) { jne(std::string(label), type); }//-V524 +void jne(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524 +void jne(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jng(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jng(const char *label, LabelType type = T_AUTO) { jng(std::string(label), type); }//-V524 +void jng(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7E, 0x8E, 0x0F); }//-V524 +void jng(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7E, 0x8E, 0x0F); }//-V524 +void jnge(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jnge(const char *label, LabelType type = T_AUTO) { jnge(std::string(label), type); }//-V524 +void jnge(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7C, 0x8C, 0x0F); }//-V524 +void jnge(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7C, 0x8C, 0x0F); }//-V524 +void jnl(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jnl(const char *label, LabelType type = T_AUTO) { jnl(std::string(label), type); }//-V524 +void jnl(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7D, 0x8D, 0x0F); }//-V524 +void jnl(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7D, 0x8D, 0x0F); }//-V524 +void jnle(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jnle(const char *label, LabelType type = T_AUTO) { jnle(std::string(label), type); }//-V524 +void jnle(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7F, 0x8F, 0x0F); }//-V524 +void jnle(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7F, 0x8F, 0x0F); }//-V524 +void jno(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524 +void jno(const char *label, LabelType type = T_AUTO) { jno(std::string(label), type); }//-V524 +void jno(const void *addr) { opJmpAbs(addr, T_NEAR, 0x71, 0x81, 0x0F); }//-V524 +void jno(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x71, 0x81, 0x0F); }//-V524 +void jnp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jnp(const char *label, LabelType type = T_AUTO) { jnp(std::string(label), type); }//-V524 +void jnp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524 +void jnp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jns(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524 +void jns(const char *label, LabelType type = T_AUTO) { jns(std::string(label), type); }//-V524 +void jns(const void *addr) { opJmpAbs(addr, T_NEAR, 0x79, 0x89, 0x0F); }//-V524 +void jns(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x79, 0x89, 0x0F); }//-V524 +void jnz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jnz(const char *label, LabelType type = T_AUTO) { jnz(std::string(label), type); }//-V524 +void jnz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x75, 0x85, 0x0F); }//-V524 +void jnz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x75, 0x85, 0x0F); }//-V524 +void jo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524 +void jo(const char *label, LabelType type = T_AUTO) { jo(std::string(label), type); }//-V524 +void jo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x70, 0x80, 0x0F); }//-V524 +void jo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x70, 0x80, 0x0F); }//-V524 +void jp(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jp(const char *label, LabelType type = T_AUTO) { jp(std::string(label), type); }//-V524 +void jp(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524 +void jp(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(const char *label, LabelType type = T_AUTO) { jpe(std::string(label), type); }//-V524 +void jpe(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7A, 0x8A, 0x0F); }//-V524 +void jpe(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7A, 0x8A, 0x0F); }//-V524 +void jpo(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void jpo(const char *label, LabelType type = T_AUTO) { jpo(std::string(label), type); }//-V524 +void jpo(const void *addr) { opJmpAbs(addr, T_NEAR, 0x7B, 0x8B, 0x0F); }//-V524 +void jpo(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x7B, 0x8B, 0x0F); }//-V524 +void js(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524 +void js(const char *label, LabelType type = T_AUTO) { js(std::string(label), type); }//-V524 +void js(const void *addr) { opJmpAbs(addr, T_NEAR, 0x78, 0x88, 0x0F); }//-V524 +void js(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x78, 0x88, 0x0F); }//-V524 +void jz(const Label& label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void jz(const char *label, LabelType type = T_AUTO) { jz(std::string(label), type); }//-V524 +void jz(const void *addr) { opJmpAbs(addr, T_NEAR, 0x74, 0x84, 0x0F); }//-V524 +void jz(std::string label, LabelType type = T_AUTO) { opJmp(label, type, 0x74, 0x84, 0x0F); }//-V524 +void lahf() { db(0x9F); } +void lddqu(const Xmm& xmm, const Address& addr) { db(0xF2); opModM(addr, xmm, 0x0F, 0xF0); } +void ldmxcsr(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0xAE); } +void lea(const Reg& reg, const Address& addr) { if (!reg.isBit(16 | i32e)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModM(addr, reg, 0x8D); } +void leave() { db(0xC9); } +void lfence() { db(0x0F); db(0xAE); db(0xE8); } +void lfs(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB4); } +void lgs(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB5); } +void lock() { db(0xF0); } +void lodsb() { db(0xAC); } +void lodsd() { db(0xAD); } +void lodsw() { db(0x66); db(0xAD); } +void loop(const Label& label) { opJmp(label, T_SHORT, 0xE2, 0, 0); } +void loop(const char *label) { loop(std::string(label)); } +void loop(std::string label) { opJmp(label, T_SHORT, 0xE2, 0, 0); } +void loope(const Label& label) { opJmp(label, T_SHORT, 0xE1, 0, 0); } +void loope(const char *label) { loope(std::string(label)); } +void loope(std::string label) { opJmp(label, T_SHORT, 0xE1, 0, 0); } +void loopne(const Label& label) { opJmp(label, T_SHORT, 0xE0, 0, 0); } +void loopne(const char *label) { loopne(std::string(label)); } +void loopne(std::string label) { opJmp(label, T_SHORT, 0xE0, 0, 0); } +void lss(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0x0F, 0xB2); } +void lzcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBD); } +void maskmovdqu(const Xmm& reg1, const Xmm& reg2) { db(0x66); opModR(reg1, reg2, 0x0F, 0xF7); } +void maskmovq(const Mmx& reg1, const Mmx& reg2) { if (!reg1.isMMX() || !reg2.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModR(reg1, reg2, 0x0F, 0xF7); } +void maxpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x66, isXMM_XMMorMEM); } +void maxps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0x100, isXMM_XMMorMEM); } +void maxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF2, isXMM_XMMorMEM); } +void maxss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5F, 0xF3, isXMM_XMMorMEM); } +void mfence() { db(0x0F); db(0xAE); db(0xF0); } +void minpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x66, isXMM_XMMorMEM); } +void minps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0x100, isXMM_XMMorMEM); } +void minsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF2, isXMM_XMMorMEM); } +void minss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5D, 0xF3, isXMM_XMMorMEM); } +void monitor() { db(0x0F); db(0x01); db(0xC8); } +void monitorx() { db(0x0F); db(0x01); db(0xFA); } +void movapd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x29); } +void movapd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x66); } +void movaps(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x29); } +void movaps(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x28, 0x100); } +void movbe(const Address& addr, const Reg& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF1); } +void movbe(const Reg& reg, const Address& addr) { opModM(addr, reg, 0x0F, 0x38, 0xF0); } +void movd(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x7E); } +void movd(const Mmx& mmx, const Address& addr) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, 0x6E); } +void movd(const Mmx& mmx, const Reg32& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); } +void movd(const Reg32& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); } +void movddup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF2, isXMM_XMMorMEM, NONE, NONE); } +void movdir64b(const Reg& reg, const Address& addr) { db(0x66); opModM(addr, reg.cvt32(), 0x0F, 0x38, 0xF8); } +void movdiri(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0x38, 0xF9); } +void movdq2q(const Mmx& mmx, const Xmm& xmm) { db(0xF2); opModR(mmx, xmm, 0x0F, 0xD6); } +void movdqa(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x7F); } +void movdqa(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0x66); } +void movdqu(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x7F); } +void movdqu(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x6F, 0xF3); } +void movhlps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x12); } +void movhpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x66); } +void movhps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x16, 0x100); } +void movlhps(const Xmm& reg1, const Xmm& reg2) { opModR(reg1, reg2, 0x0F, 0x16); } +void movlpd(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x66); } +void movlps(const Operand& op1, const Operand& op2) { opMovXMM(op1, op2, 0x12, 0x100); } +void movmskpd(const Reg32e& reg, const Xmm& xmm) { db(0x66); movmskps(reg, xmm); } +void movmskps(const Reg32e& reg, const Xmm& xmm) { opModR(reg, xmm, 0x0F, 0x50); } +void movntdq(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0xE7); } +void movntdqa(const Xmm& xmm, const Address& addr) { db(0x66); opModM(addr, xmm, 0x0F, 0x38, 0x2A); } +void movnti(const Address& addr, const Reg32e& reg) { opModM(addr, reg, 0x0F, 0xC3); } +void movntpd(const Address& addr, const Xmm& reg) { opModM(addr, Reg16(reg.getIdx()), 0x0F, 0x2B); } +void movntps(const Address& addr, const Xmm& xmm) { opModM(addr, Mmx(xmm.getIdx()), 0x0F, 0x2B); } +void movntq(const Address& addr, const Mmx& mmx) { if (!mmx.isMMX()) XBYAK_THROW(ERR_BAD_COMBINATION) opModM(addr, mmx, 0x0F, 0xE7); } +void movq(const Address& addr, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModM(addr, mmx, 0x0F, mmx.isXMM() ? 0xD6 : 0x7F); } +void movq(const Mmx& mmx, const Operand& op) { if (mmx.isXMM()) db(0xF3); opModRM(mmx, op, (mmx.getKind() == op.getKind()), op.isMEM(), 0x0F, mmx.isXMM() ? 0x7E : 0x6F); } +void movq2dq(const Xmm& xmm, const Mmx& mmx) { db(0xF3); opModR(xmm, mmx, 0x0F, 0xD6); } +void movsb() { db(0xA4); } +void movsd() { db(0xA5); } +void movsd(const Address& addr, const Xmm& xmm) { db(0xF2); opModM(addr, xmm, 0x0F, 0x11); } +void movsd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF2); } +void movshdup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x16, 0xF3, isXMM_XMMorMEM, NONE, NONE); } +void movsldup(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x12, 0xF3, isXMM_XMMorMEM, NONE, NONE); } +void movss(const Address& addr, const Xmm& xmm) { db(0xF3); opModM(addr, xmm, 0x0F, 0x11); } +void movss(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0xF3); } +void movsw() { db(0x66); db(0xA5); } +void movsx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xBE); } +void movupd(const Address& addr, const Xmm& xmm) { db(0x66); opModM(addr, xmm, 0x0F, 0x11); } +void movupd(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x66); } +void movups(const Address& addr, const Xmm& xmm) { opModM(addr, xmm, 0x0F, 0x11); } +void movups(const Xmm& xmm, const Operand& op) { opMMX(xmm, op, 0x10, 0x100); } +void movzx(const Reg& reg, const Operand& op) { opMovxx(reg, op, 0xB6); } +void mpsadbw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x42, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void mul(const Operand& op) { opR_ModM(op, 0, 4, 0xF6); } +void mulpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x66, isXMM_XMMorMEM); } +void mulps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0x100, isXMM_XMMorMEM); } +void mulsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF2, isXMM_XMMorMEM); } +void mulss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x59, 0xF3, isXMM_XMMorMEM); } +void mulx(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf6, true); } +void mwait() { db(0x0F); db(0x01); db(0xC9); } +void mwaitx() { db(0x0F); db(0x01); db(0xFB); } +void neg(const Operand& op) { opR_ModM(op, 0, 3, 0xF6); } +void not_(const Operand& op) { opR_ModM(op, 0, 2, 0xF6); } +void or_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x08, 1); } +void or_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x08); } +void orpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x66, isXMM_XMMorMEM); } +void orps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x56, 0x100, isXMM_XMMorMEM); } +void out_(const Reg& d, const Reg& a) { opInOut(a, d, 0xEE); } +void out_(uint8_t v, const Reg& a) { opInOut(a, 0xE6, v); } +void outsb() { db(0x6E); } +void outsd() { db(0x6F); } +void outsw() { db(0x66); db(0x6F); } +void pabsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1C, 0x66, NONE, 0x38); } +void pabsd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1E, 0x66, NONE, 0x38); } +void pabsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x1D, 0x66, NONE, 0x38); } +void packssdw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6B); } +void packsswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x63); } +void packusdw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2B, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void packuswb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x67); } +void paddb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFC); } +void paddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFE); } +void paddq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD4); } +void paddsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEC); } +void paddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xED); } +void paddusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDC); } +void paddusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDD); } +void paddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFD); } +void palignr(const Mmx& mmx, const Operand& op, int imm) { opMMX(mmx, op, 0x0f, 0x66, static_cast<uint8_t>(imm), 0x3a); } +void pand(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDB); } +void pandn(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDF); } +void pause() { db(0xF3); db(0x90); } +void pavgb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE0); } +void pavgw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE3); } +void pblendvb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x10, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pblendw(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0E, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void pclmulhqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x11); } +void pclmulhqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x01); } +void pclmullqhdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x10); } +void pclmullqlqdq(const Xmm& xmm, const Operand& op) { pclmulqdq(xmm, op, 0x00); } +void pclmulqdq(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x44, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void pcmpeqb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x74); } +void pcmpeqd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x76); } +void pcmpeqq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x29, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pcmpeqw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x75); } +void pcmpestri(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x61, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpestrm(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x60, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpgtb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x64); } +void pcmpgtd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x66); } +void pcmpgtq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x37, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pcmpgtw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x65); } +void pcmpistri(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x63, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pcmpistrm(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x62, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void pdep(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F2 | T_0F38, 0xf5, true); } +void pext(const Reg32e& r1, const Reg32e& r2, const Operand& op) { opGpr(r1, r2, op, T_F3 | T_0F38, 0xf5, true); } +void pextrb(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x14, imm); } +void pextrd(const Operand& op, const Xmm& xmm, uint8_t imm) { opExt(op, xmm, 0x16, imm); } +void pextrw(const Operand& op, const Mmx& xmm, uint8_t imm) { opExt(op, xmm, 0x15, imm, true); } +void phaddd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x02, 0x66, NONE, 0x38); } +void phaddsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x03, 0x66, NONE, 0x38); } +void phaddw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x01, 0x66, NONE, 0x38); } +void phminposuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x41, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void phsubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x06, 0x66, NONE, 0x38); } +void phsubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x07, 0x66, NONE, 0x38); } +void phsubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x05, 0x66, NONE, 0x38); } +void pinsrb(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x20, 0x66, isXMM_REG32orMEM, imm, 0x3A); } +void pinsrd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x22, 0x66, isXMM_REG32orMEM, imm, 0x3A); } +void pinsrw(const Mmx& mmx, const Operand& op, int imm) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(mmx, op, 0xC4, mmx.isXMM() ? 0x66 : NONE, 0, imm); } +void pmaddubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x04, 0x66, NONE, 0x38); } +void pmaddwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF5); } +void pmaxsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3C, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3D, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEE); } +void pmaxub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDE); } +void pmaxud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3F, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmaxuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3E, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsb(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x38, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x39, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEA); } +void pminub(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xDA); } +void pminud(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3B, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pminuw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x3A, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovmskb(const Reg32e& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(reg, mmx, 0x0F, 0xD7); } +void pmovsxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x21, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x22, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x20, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x25, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x23, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovsxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x24, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x31, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x32, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxbw(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x30, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x35, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxwd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x33, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmovzxwq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x34, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmuldq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x28, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmulhrsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0B, 0x66, NONE, 0x38); } +void pmulhuw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE4); } +void pmulhw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE5); } +void pmulld(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x40, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void pmullw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD5); } +void pmuludq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF4); } +void popcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xB8); } +void popf() { db(0x9D); } +void por(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEB); } +void prefetchnta(const Address& addr) { opModM(addr, Reg32(0), 0x0F, 0x18); } +void prefetcht0(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x18); } +void prefetcht1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x18); } +void prefetcht2(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0x18); } +void prefetchw(const Address& addr) { opModM(addr, Reg32(1), 0x0F, 0x0D); } +void prefetchwt1(const Address& addr) { opModM(addr, Reg32(2), 0x0F, 0x0D); } +void psadbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF6); } +void pshufb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x00, 0x66, NONE, 0x38); } +void pshufd(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0x66, imm8); } +void pshufhw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0xF3, imm8); } +void pshuflw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0xF2, imm8); } +void pshufw(const Mmx& mmx, const Operand& op, uint8_t imm8) { opMMX(mmx, op, 0x70, 0x00, imm8); } +void psignb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x08, 0x66, NONE, 0x38); } +void psignd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x0A, 0x66, NONE, 0x38); } +void psignw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x09, 0x66, NONE, 0x38); } +void pslld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF2); } +void pslld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 6); } +void pslldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 7); } +void psllq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF3); } +void psllq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 6); } +void psllw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF1); } +void psllw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 6); } +void psrad(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE2); } +void psrad(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 4); } +void psraw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE1); } +void psraw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 4); } +void psrld(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD2); } +void psrld(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x72, 2); } +void psrldq(const Xmm& xmm, int imm8) { opMMX_IMM(xmm, imm8, 0x73, 3); } +void psrlq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD3); } +void psrlq(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x73, 2); } +void psrlw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD1); } +void psrlw(const Mmx& mmx, int imm8) { opMMX_IMM(mmx, imm8, 0x71, 2); } +void psubb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF8); } +void psubd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFA); } +void psubq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xFB); } +void psubsb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE8); } +void psubsw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xE9); } +void psubusb(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD8); } +void psubusw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xD9); } +void psubw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xF9); } +void ptest(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x17, 0x66, isXMM_XMMorMEM, NONE, 0x38); } +void punpckhbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x68); } +void punpckhdq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x6A); } +void punpckhqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6D, 0x66, isXMM_XMMorMEM); } +void punpckhwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x69); } +void punpcklbw(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x60); } +void punpckldq(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x62); } +void punpcklqdq(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x6C, 0x66, isXMM_XMMorMEM); } +void punpcklwd(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0x61); } +void pushf() { db(0x9C); } +void pxor(const Mmx& mmx, const Operand& op) { opMMX(mmx, op, 0xEF); } +void rcl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 2); } +void rcl(const Operand& op, int imm) { opShift(op, imm, 2); } +void rcpps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0x100, isXMM_XMMorMEM); } +void rcpss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x53, 0xF3, isXMM_XMMorMEM); } +void rcr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 3); } +void rcr(const Operand& op, int imm) { opShift(op, imm, 3); } +void rdmsr() { db(0x0F); db(0x32); } +void rdpmc() { db(0x0F); db(0x33); } +void rdrand(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(6, Operand::REG, r.getBit()), r, 0x0F, 0xC7); } +void rdseed(const Reg& r) { if (r.isBit(8)) XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) opModR(Reg(7, Operand::REG, r.getBit()), r, 0x0F, 0xC7); } +void rdtsc() { db(0x0F); db(0x31); } +void rdtscp() { db(0x0F); db(0x01); db(0xF9); } +void rep() { db(0xF3); } +void repe() { db(0xF3); } +void repne() { db(0xF2); } +void repnz() { db(0xF2); } +void repz() { db(0xF3); } +void ret(int imm = 0) { if (imm) { db(0xC2); dw(imm); } else { db(0xC3); } } +void retf(int imm = 0) { if (imm) { db(0xCA); dw(imm); } else { db(0xCB); } } +void rol(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 0); } +void rol(const Operand& op, int imm) { opShift(op, imm, 0); } +void ror(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 1); } +void ror(const Operand& op, int imm) { opShift(op, imm, 1); } +void rorx(const Reg32e& r, const Operand& op, uint8_t imm) { opGpr(r, op, Reg32e(0, r.getBit()), T_0F3A | T_F2, 0xF0, false, imm); } +void roundpd(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x09, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void roundps(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0x08, 0x66, isXMM_XMMorMEM, imm, 0x3A); } +void roundsd(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0B, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void roundss(const Xmm& xmm, const Operand& op, int imm) { opGen(xmm, op, 0x0A, 0x66, isXMM_XMMorMEM, static_cast<uint8_t>(imm), 0x3A); } +void rsqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0x100, isXMM_XMMorMEM); } +void rsqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x52, 0xF3, isXMM_XMMorMEM); } +void sahf() { db(0x9E); } +void sal(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); } +void sal(const Operand& op, int imm) { opShift(op, imm, 4); } +void sar(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 7); } +void sar(const Operand& op, int imm) { opShift(op, imm, 7); } +void sarx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F3 | T_0F38, 0xf7, false); } +void sbb(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x18, 3); } +void sbb(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x18); } +void scasb() { db(0xAE); } +void scasd() { db(0xAF); } +void scasw() { db(0x66); db(0xAF); } +void serialize() { db(0x0F); db(0x01); db(0xE8); } +void seta(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524 +void setae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void setbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524 +void setc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void sete(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524 +void setg(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524 +void setge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524 +void setl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524 +void setle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524 +void setna(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 6); }//-V524 +void setnae(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 2); }//-V524 +void setnb(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setnbe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 7); }//-V524 +void setnc(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 3); }//-V524 +void setne(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524 +void setng(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 14); }//-V524 +void setnge(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 12); }//-V524 +void setnl(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 13); }//-V524 +void setnle(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 15); }//-V524 +void setno(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 1); }//-V524 +void setnp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524 +void setns(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 9); }//-V524 +void setnz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 5); }//-V524 +void seto(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 0); }//-V524 +void setp(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524 +void setpe(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 10); }//-V524 +void setpo(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 11); }//-V524 +void sets(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 8); }//-V524 +void setz(const Operand& op) { opR_ModM(op, 8, 0, 0x0F, 0x90 | 4); }//-V524 +void sfence() { db(0x0F); db(0xAE); db(0xF8); } +void sha1msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC9, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCA, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1nexte(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xC8, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha1rnds4(const Xmm& xmm, const Operand& op, uint8_t imm) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, imm, 0x3A); } +void sha256msg1(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCC, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha256msg2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCD, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void sha256rnds2(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0xCB, NONE, isXMM_XMMorMEM, NONE, 0x38); } +void shl(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 4); } +void shl(const Operand& op, int imm) { opShift(op, imm, 4); } +void shld(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xA4, &_cl); } +void shld(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0xA4); } +void shlx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_66 | T_0F38, 0xf7, false); } +void shr(const Operand& op, const Reg8& _cl) { opShift(op, _cl, 5); } +void shr(const Operand& op, int imm) { opShift(op, imm, 5); } +void shrd(const Operand& op, const Reg& reg, const Reg8& _cl) { opShxd(op, reg, 0, 0xAC, &_cl); } +void shrd(const Operand& op, const Reg& reg, uint8_t imm) { opShxd(op, reg, imm, 0xAC); } +void shrx(const Reg32e& r1, const Operand& op, const Reg32e& r2) { opGpr(r1, op, r2, T_F2 | T_0F38, 0xf7, false); } +void shufpd(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC6, 0x66, isXMM_XMMorMEM, imm8); } +void shufps(const Xmm& xmm, const Operand& op, uint8_t imm8) { opGen(xmm, op, 0xC6, 0x100, isXMM_XMMorMEM, imm8); } +void sqrtpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x66, isXMM_XMMorMEM); } +void sqrtps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0x100, isXMM_XMMorMEM); } +void sqrtsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF2, isXMM_XMMorMEM); } +void sqrtss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x51, 0xF3, isXMM_XMMorMEM); } +void stac() { db(0x0F); db(0x01); db(0xCB); } +void stc() { db(0xF9); } +void std() { db(0xFD); } +void sti() { db(0xFB); } +void stmxcsr(const Address& addr) { opModM(addr, Reg32(3), 0x0F, 0xAE); } +void stosb() { db(0xAA); } +void stosd() { db(0xAB); } +void stosw() { db(0x66); db(0xAB); } +void sub(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x28, 5); } +void sub(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x28); } +void subpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x66, isXMM_XMMorMEM); } +void subps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0x100, isXMM_XMMorMEM); } +void subsd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF2, isXMM_XMMorMEM); } +void subss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x5C, 0xF3, isXMM_XMMorMEM); } +void sysenter() { db(0x0F); db(0x34); } +void sysexit() { db(0x0F); db(0x35); } +void tpause(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0x66); db(0x0F); db(0xAE); setModRM(3, 6, idx); } +void tzcnt(const Reg®, const Operand& op) { opSp1(reg, op, 0xF3, 0x0F, 0xBC); } +void ucomisd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x66, isXMM_XMMorMEM); } +void ucomiss(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x2E, 0x100, isXMM_XMMorMEM); } +void ud2() { db(0x0F); db(0x0B); } +void umonitor(const Reg& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) int bit = r.getBit(); if (BIT != bit) { if ((BIT == 32 && bit == 16) || (BIT == 64 && bit == 32)) { db(0x67); } else { XBYAK_THROW(ERR_BAD_SIZE_OF_REGISTER) } } db(0xF3); db(0x0F); db(0xAE); setModRM(3, 6, idx); } +void umwait(const Reg32& r) { int idx = r.getIdx(); if (idx > 7) XBYAK_THROW(ERR_BAD_PARAMETER) db(0xF2); db(0x0F); db(0xAE); setModRM(3, 6, idx); } +void unpckhpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x66, isXMM_XMMorMEM); } +void unpckhps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x15, 0x100, isXMM_XMMorMEM); } +void unpcklpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x66, isXMM_XMMorMEM); } +void unpcklps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x14, 0x100, isXMM_XMMorMEM); } +void vaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x58); } +void vaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x58); } +void vaddsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x58); } +void vaddss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x58); } +void vaddsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0xD0); } +void vaddsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0xD0); } +void vaesdec(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDE); } +void vaesdeclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDF); } +void vaesenc(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDC); } +void vaesenclast(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F38 | T_YMM | T_EVEX, 0xDD); } +void vaesimc(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_W0, 0xDB); } +void vaeskeygenassist(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0xDF, imm); } +void vandnpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x55); } +void vandnps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x55); } +void vandpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x54); } +void vandps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x54); } +void vbcstnebf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F3 | T_0F38 | T_W0 | T_YMM | T_B16, 0xB1); } +void vbcstnesh2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_66 | T_0F38 | T_W0 | T_YMM | T_B16, 0xB1); } +void vblendpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0D, imm); } +void vblendps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0C, imm); } +void vblendvpd(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4B, x4.getIdx() << 4); } +void vblendvps(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4A, x4.getIdx() << 4); } +void vbroadcastf128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x1A); } +void vbroadcasti128(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x5A); } +void vbroadcastsd(const Ymm& y, const Operand& op) { if (!op.isMEM() && !(y.isYMM() && op.isXMM()) && !(y.isZMM() && op.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(y, op, T_0F38 | T_66 | T_W0 | T_YMM | T_EVEX | T_EW1 | T_N8, 0x19); } +void vbroadcastss(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x18); } +void vcmpeq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 16); } +void vcmpeq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 16); } +void vcmpeq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 16); } +void vcmpeq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 16); } +void vcmpeq_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 8); } +void vcmpeq_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 8); } +void vcmpeq_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 8); } +void vcmpeq_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 8); } +void vcmpeq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 24); } +void vcmpeq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 24); } +void vcmpeq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 24); } +void vcmpeq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 24); } +void vcmpeqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 0); } +void vcmpeqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 0); } +void vcmpeqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 0); } +void vcmpeqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 0); } +void vcmpfalse_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 27); } +void vcmpfalse_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 27); } +void vcmpfalse_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 27); } +void vcmpfalse_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 27); } +void vcmpfalsepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 11); } +void vcmpfalseps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 11); } +void vcmpfalsesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 11); } +void vcmpfalsess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 11); } +void vcmpge_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 29); } +void vcmpge_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 29); } +void vcmpge_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 29); } +void vcmpge_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 29); } +void vcmpgepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 13); } +void vcmpgeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 13); } +void vcmpgesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 13); } +void vcmpgess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 13); } +void vcmpgt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 30); } +void vcmpgt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 30); } +void vcmpgt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 30); } +void vcmpgt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 30); } +void vcmpgtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 14); } +void vcmpgtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 14); } +void vcmpgtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 14); } +void vcmpgtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 14); } +void vcmple_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 18); } +void vcmple_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 18); } +void vcmple_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 18); } +void vcmple_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 18); } +void vcmplepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 2); } +void vcmpleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 2); } +void vcmplesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 2); } +void vcmpless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 2); } +void vcmplt_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 17); } +void vcmplt_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 17); } +void vcmplt_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 17); } +void vcmplt_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 17); } +void vcmpltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 1); } +void vcmpltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 1); } +void vcmpltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 1); } +void vcmpltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 1); } +void vcmpneq_oqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 12); } +void vcmpneq_oqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 12); } +void vcmpneq_oqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 12); } +void vcmpneq_oqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 12); } +void vcmpneq_ospd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 28); } +void vcmpneq_osps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 28); } +void vcmpneq_ossd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 28); } +void vcmpneq_osss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 28); } +void vcmpneq_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 20); } +void vcmpneq_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 20); } +void vcmpneq_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 20); } +void vcmpneq_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 20); } +void vcmpneqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 4); } +void vcmpneqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 4); } +void vcmpneqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 4); } +void vcmpneqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 4); } +void vcmpnge_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 25); } +void vcmpnge_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 25); } +void vcmpnge_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 25); } +void vcmpnge_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 25); } +void vcmpngepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 9); } +void vcmpngeps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 9); } +void vcmpngesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 9); } +void vcmpngess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 9); } +void vcmpngt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 26); } +void vcmpngt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 26); } +void vcmpngt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 26); } +void vcmpngt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 26); } +void vcmpngtpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 10); } +void vcmpngtps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 10); } +void vcmpngtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 10); } +void vcmpngtss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 10); } +void vcmpnle_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 22); } +void vcmpnle_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 22); } +void vcmpnle_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 22); } +void vcmpnle_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 22); } +void vcmpnlepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 6); } +void vcmpnleps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 6); } +void vcmpnlesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 6); } +void vcmpnless(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 6); } +void vcmpnlt_uqpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 21); } +void vcmpnlt_uqps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 21); } +void vcmpnlt_uqsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 21); } +void vcmpnlt_uqss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 21); } +void vcmpnltpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 5); } +void vcmpnltps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 5); } +void vcmpnltsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 5); } +void vcmpnltss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 5); } +void vcmpord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 23); } +void vcmpord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 23); } +void vcmpord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 23); } +void vcmpord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 23); } +void vcmpordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 7); } +void vcmpordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 7); } +void vcmpordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 7); } +void vcmpordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 7); } +void vcmppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xC2, imm); } +void vcmpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_YMM, 0xC2, imm); } +void vcmpsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F, 0xC2, imm); } +void vcmpss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0xC2, imm); } +void vcmptrue_uspd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 31); } +void vcmptrue_usps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 31); } +void vcmptrue_ussd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 31); } +void vcmptrue_usss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 31); } +void vcmptruepd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 15); } +void vcmptrueps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 15); } +void vcmptruesd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 15); } +void vcmptruess(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 15); } +void vcmpunord_spd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 19); } +void vcmpunord_sps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 19); } +void vcmpunord_ssd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 19); } +void vcmpunord_sss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 19); } +void vcmpunordpd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmppd(x1, x2, op, 3); } +void vcmpunordps(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpps(x1, x2, op, 3); } +void vcmpunordsd(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpsd(x1, x2, op, 3); } +void vcmpunordss(const Xmm& x1, const Xmm& x2, const Operand& op) { vcmpss(x1, x2, op, 3); } +void vcomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2F); } +void vcomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2F); } +void vcvtdq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_F3 | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL, 0xE6); } +void vcvtdq2ps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); } +void vcvtneebf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F3 | T_0F38 | T_W0 | T_YMM, 0xB0); } +void vcvtneeph2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_66 | T_0F38 | T_W0 | T_YMM, 0xB0); } +void vcvtneobf162ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_F2 | T_0F38 | T_W0 | T_YMM, 0xB0); } +void vcvtneoph2ps(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_W0 | T_YMM, 0xB0); } +void vcvtneps2bf16(const Xmm& x, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opCvt2(x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32 | orEvexIf(encoding), 0x72); } +void vcvtpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_F2 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0xE6); } +void vcvtpd2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_66 | T_YMM | T_EVEX | T_EW1 | T_B64 | T_ER_Z, 0x5A); } +void vcvtph2ps(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F38 | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y, 0x13); } +void vcvtps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5B); } +void vcvtps2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_0F | T_YMM | T_EVEX | T_EW0 | T_B32 | T_N8 | T_N_VL | T_SAE_Y, 0x5A); } +void vcvtps2ph(const Operand& op, const Xmm& x, uint8_t imm) { checkCvt1(x, op); opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N8 | T_N_VL | T_SAE_Y | T_M_K, 0x1D, imm); } +void vcvtsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_ER_X, 0x2D); } +void vcvtsd2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x5A); } +void vcvtsi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F2 | T_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); } +void vcvtsi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_0F | T_F3 | T_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x2A); } +void vcvtss2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x5A); } +void vcvtss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_ER_X | T_N8, 0x2D); } +void vcvttpd2dq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_66 | T_0F | T_YMM | T_EVEX |T_EW1 | T_B64 | T_ER_Z, 0xE6); } +void vcvttps2dq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX | T_SAE_Z | T_B32, 0x5B); } +void vcvttsd2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W0 | T_EVEX | T_EW0 | T_N4 | T_SAE_X, 0x2C); } +void vcvttss2si(const Reg32& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W0 | T_EVEX | T_EW0 | T_SAE_X | T_N8, 0x2C); } +void vdivpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5E); } +void vdivps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5E); } +void vdivsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5E); } +void vdivss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5E); } +void vdppd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x41, imm); } +void vdpps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x40, imm); } +void vextractf128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x19, imm); } +void vextracti128(const Operand& op, const Ymm& y, uint8_t imm) { if (!(op.isXMEM() && y.isYMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y, 0, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x39, imm); } +void vextractps(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_N4, 0x17, imm); } +void vfmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x98); } +void vfmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x98); } +void vfmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x99); } +void vfmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x99); } +void vfmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA8); } +void vfmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA8); } +void vfmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xA9); } +void vfmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xA9); } +void vfmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB8); } +void vfmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB8); } +void vfmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xB9); } +void vfmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xB9); } +void vfmaddsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x96); } +void vfmaddsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x96); } +void vfmaddsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA6); } +void vfmaddsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA6); } +void vfmaddsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB6); } +void vfmaddsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB6); } +void vfmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9A); } +void vfmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9A); } +void vfmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9B); } +void vfmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9B); } +void vfmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAA); } +void vfmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAA); } +void vfmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAB); } +void vfmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAB); } +void vfmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBA); } +void vfmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBA); } +void vfmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBB); } +void vfmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBB); } +void vfmsubadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x97); } +void vfmsubadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x97); } +void vfmsubadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xA7); } +void vfmsubadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xA7); } +void vfmsubadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xB7); } +void vfmsubadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xB7); } +void vfnmadd132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9C); } +void vfnmadd132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9C); } +void vfnmadd132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9D); } +void vfnmadd132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9D); } +void vfnmadd213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAC); } +void vfnmadd213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAC); } +void vfnmadd213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAD); } +void vfnmadd213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAD); } +void vfnmadd231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBC); } +void vfnmadd231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBC); } +void vfnmadd231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBD); } +void vfnmadd231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBD); } +void vfnmsub132pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x9E); } +void vfnmsub132ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x9E); } +void vfnmsub132sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0x9F); } +void vfnmsub132ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0x9F); } +void vfnmsub213pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xAE); } +void vfnmsub213ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xAE); } +void vfnmsub213sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xAF); } +void vfnmsub213ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xAF); } +void vfnmsub231pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0xBE); } +void vfnmsub231ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0xBE); } +void vfnmsub231sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_W1 | T_EW1 | T_EVEX | T_ER_X, 0xBF); } +void vfnmsub231ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_W0 | T_EW0 | T_EVEX | T_ER_X, 0xBF); } +void vgatherdpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x92, 0); } +void vgatherdps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x92, 1); } +void vgatherqpd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x93, 1); } +void vgatherqps(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x93, 2); } +void vgf2p8affineinvqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCF, imm); } +void vgf2p8affineqb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_SAE_Z | T_B64, 0xCE, imm); } +void vgf2p8mulb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_SAE_Z, 0xCF); } +void vhaddpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7C); } +void vhaddps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7C); } +void vhsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_66 | T_0F | T_YMM, 0x7D); } +void vhsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_F2 | T_0F | T_YMM, 0x7D); } +void vinsertf128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x18, imm); } +void vinserti128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isXMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x38, imm); } +void vinsertps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_W0 | T_EW0 | T_EVEX, 0x21, imm); } +void vlddqu(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, cvtIdx0(x), addr, T_0F | T_F2 | T_W0 | T_YMM, 0xF0); } +void vldmxcsr(const Address& addr) { opAVX_X_X_XM(xm2, xm0, addr, T_0F, 0xAE); } +void vmaskmovdqu(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_66, 0xF7); } +void vmaskmovpd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2F); } +void vmaskmovpd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2D); } +void vmaskmovps(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2E); } +void vmaskmovps(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x2C); } +void vmaxpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5F); } +void vmaxps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5F); } +void vmaxsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5F); } +void vmaxss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5F); } +void vminpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5D); } +void vminps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5D); } +void vminsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5D); } +void vminss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5D); } +void vmovapd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x29); } +void vmovapd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x28); } +void vmovaps(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x29); } +void vmovaps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x28); } +void vmovd(const Operand& op, const Xmm& x) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x7E); } +void vmovd(const Xmm& x, const Operand& op) { if (!op.isREG(32) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_0F | T_66 | T_W0 | T_EVEX | T_N4, 0x6E); } +void vmovddup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_DUP | T_F2 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_X | T_ER_Y | T_ER_Z, 0x12); } +void vmovdqa(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_YMM, 0x7F); } +void vmovdqa(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_YMM, 0x6F); } +void vmovdqu(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_F3 | T_0F | T_YMM, 0x7F); } +void vmovdqu(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM, 0x6F); } +void vmovhlps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x12); } +void vmovhpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x17); } +void vmovhpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x16); } +void vmovhps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x17); } +void vmovhps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x16); } +void vmovlhps(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_0F | T_EVEX | T_EW0, 0x16); } +void vmovlpd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x13); } +void vmovlpd(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, 0x12); } +void vmovlps(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_EVEX | T_EW0 | T_N8, 0x13); } +void vmovlps(const Xmm& x, const Operand& op1, const Operand& op2 = Operand()) { if (!op2.isNone() && !op2.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, op1, op2, T_0F | T_EVEX | T_EW0 | T_N8, 0x12); } +void vmovmskpd(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_66 | T_W0 | T_YMM, 0x50); } +void vmovmskps(const Reg& r, const Xmm& x) { if (!r.isBit(i32e)) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x.isXMM() ? Xmm(r.getIdx()) : Ymm(r.getIdx()), cvtIdx0(x), x, T_0F | T_W0 | T_YMM, 0x50); } +void vmovntdq(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW0, 0xE7); } +void vmovntdqa(const Xmm& x, const Address& addr) { opVex(x, 0, addr, T_0F38 | T_66 | T_YMM | T_EVEX | T_EW0, 0x2A); } +void vmovntpd(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_66 | T_YMM | T_EVEX | T_EW1, 0x2B); } +void vmovntps(const Address& addr, const Xmm& x) { opVex(x, 0, addr, T_0F | T_YMM | T_EVEX | T_EW0, 0x2B); } +void vmovq(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_0F | T_66 | T_EVEX | T_EW1 | T_N8, x.getIdx() < 16 ? 0xD6 : 0x7E); } +void vmovq(const Xmm& x, const Address& addr) { int type, code; if (x.getIdx() < 16) { type = T_0F | T_F3; code = 0x7E; } else { type = T_0F | T_66 | T_EVEX | T_EW1 | T_N8; code = 0x6E; } opAVX_X_X_XM(x, xm0, addr, type, code); } +void vmovq(const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x1, xm0, x2, T_0F | T_F3 | T_EVEX | T_EW1 | T_N8, 0x7E); } +void vmovsd(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_M_K, 0x11); } +void vmovsd(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); } +void vmovsd(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX, 0x10); } +void vmovshdup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x16); } +void vmovsldup(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_EW0 | T_YMM | T_EVEX, 0x12); } +void vmovss(const Address& addr, const Xmm& x) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_M_K, 0x11); } +void vmovss(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); } +void vmovss(const Xmm& x1, const Xmm& x2, const Operand& op = Operand()) { if (!op.isNone() && !op.isXMM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX, 0x10); } +void vmovupd(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_M_K, 0x11); } +void vmovupd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0x10); } +void vmovups(const Address& addr, const Xmm& xmm) { opAVX_X_XM_IMM(xmm, addr, T_0F | T_EW0 | T_YMM | T_EVEX | T_M_K, 0x11); } +void vmovups(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX, 0x10); } +void vmpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x42, imm); } +void vmulpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x59); } +void vmulps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x59); } +void vmulsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x59); } +void vmulss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x59); } +void vorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x56); } +void vorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x56); } +void vpabsb(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1C); } +void vpabsd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x1E); } +void vpabsw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x1D); } +void vpackssdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6B); } +void vpacksswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x63); } +void vpackusdw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x2B); } +void vpackuswb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x67); } +void vpaddb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFC); } +void vpaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFE); } +void vpaddq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xD4); } +void vpaddsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEC); } +void vpaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xED); } +void vpaddusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDC); } +void vpaddusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDD); } +void vpaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xFD); } +void vpalignr(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_YMM | T_EVEX, 0x0F, imm); } +void vpand(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDB); } +void vpandn(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xDF); } +void vpavgb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE0); } +void vpavgw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE3); } +void vpblendd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x02, imm); } +void vpblendvb(const Xmm& x1, const Xmm& x2, const Operand& op, const Xmm& x4) { opAVX_X_X_XM(x1, x2, op, T_0F3A | T_66 | T_YMM, 0x4C, x4.getIdx() << 4); } +void vpblendw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM, 0x0E, imm); } +void vpbroadcastb(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x78); } +void vpbroadcastd(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x58); } +void vpbroadcastq(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX, 0x59); } +void vpbroadcastw(const Xmm& x, const Operand& op) { if (!(op.isXMM() || op.isMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_W0 | T_YMM | T_EVEX, 0x79); } +void vpclmulqdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0 | T_YMM | T_EVEX, 0x44, imm); } +void vpcmpeqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x74); } +void vpcmpeqd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x76); } +void vpcmpeqq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x29); } +void vpcmpeqw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x75); } +void vpcmpestri(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x61, imm); } +void vpcmpestrm(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x60, imm); } +void vpcmpgtb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x64); } +void vpcmpgtd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x66); } +void vpcmpgtq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x37); } +void vpcmpgtw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0x65); } +void vpcmpistri(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x63, imm); } +void vpcmpistrm(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A, 0x62, imm); } +void vpdpbssd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_W0 | T_YMM, 0x50); } +void vpdpbssds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_W0 | T_YMM, 0x51); } +void vpdpbsud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_W0 | T_YMM, 0x50); } +void vpdpbsuds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_W0 | T_YMM, 0x51); } +void vpdpbusd(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x50, encoding); } +void vpdpbusds(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x51, encoding); } +void vpdpbuud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F38 | T_W0 | T_YMM, 0x50); } +void vpdpbuuds(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F38 | T_W0 | T_YMM, 0x51); } +void vpdpwssd(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x52, encoding); } +void vpdpwssds(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_B32, 0x53, encoding); } +void vperm2f128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x06, imm); } +void vperm2i128(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { if (!(y1.isYMM() && y2.isYMM() && op.isYMEM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(y1, &y2, op, T_0F3A | T_66 | T_W0 | T_YMM, 0x46, imm); } +void vpermd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x36); } +void vpermilpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x0D); } +void vpermilpd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_EVEX | T_B64, 0x05, imm); } +void vpermilps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x0C); } +void vpermilps(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_EVEX | T_B32, 0x04, imm); } +void vpermpd(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x01, imm); } +void vpermpd(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x16); } +void vpermps(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x16); } +void vpermq(const Ymm& y, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(y, op, T_66 | T_0F3A | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x00, imm); } +void vpermq(const Ymm& y1, const Ymm& y2, const Operand& op) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F38 | T_W0 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x36); } +void vpextrb(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(8|16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x14, imm); } +void vpextrd(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(32) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x16, imm); } +void vpextrq(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(64) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x, 0, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x16, imm); } +void vpextrw(const Operand& op, const Xmm& x, uint8_t imm) { if (!((op.isREG(16|i32e) || op.isMEM()) && x.isXMM())) XBYAK_THROW(ERR_BAD_COMBINATION) if (op.isREG() && x.getIdx() < 16) { opAVX_X_X_XM(Xmm(op.getIdx()), xm0, x, T_0F | T_66, 0xC5, imm); } else { opVex(x, 0, op, T_0F3A | T_66 | T_EVEX | T_N2, 0x15, imm); } } +void vpgatherdd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x90, 1); } +void vpgatherdq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x90, 0); } +void vpgatherqd(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W0, 0x91, 2); } +void vpgatherqq(const Xmm& x1, const Address& addr, const Xmm& x2) { opGather(x1, addr, x2, T_0F38 | T_66 | T_YMM | T_VSIB | T_W1, 0x91, 1); } +void vphaddd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x02); } +void vphaddsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x03); } +void vphaddw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x01); } +void vphminposuw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38, 0x41); } +void vphsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x06); } +void vphsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x07); } +void vphsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x05); } +void vpinsrb(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_EVEX | T_N1, 0x20, imm); } +void vpinsrd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W0 | T_EVEX | T_EW0 | T_N4, 0x22, imm); } +void vpinsrq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(64) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F3A | T_66 | T_W1 | T_EVEX | T_EW1 | T_N8, 0x22, imm); } +void vpinsrw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { if (!(x1.isXMM() && x2.isXMM() && (op.isREG(32) || op.isMEM()))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x1, &x2, op, T_0F | T_66 | T_EVEX | T_N2, 0xC4, imm); } +void vpmadd52huq(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_B64, 0xB5, encoding); } +void vpmadd52luq(const Xmm& x1, const Xmm& x2, const Operand& op, PreferredEncoding encoding = DefaultEncoding) { opEncoding(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_B64, 0xB4, encoding); } +void vpmaddubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x04); } +void vpmaddwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF5); } +void vpmaskmovd(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8E); } +void vpmaskmovd(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W0 | T_YMM, 0x8C); } +void vpmaskmovq(const Address& addr, const Xmm& x1, const Xmm& x2) { opAVX_X_X_XM(x2, x1, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8E); } +void vpmaskmovq(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_66 | T_W1 | T_YMM, 0x8C); } +void vpmaxsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3C); } +void vpmaxsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3D); } +void vpmaxsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEE); } +void vpmaxub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDE); } +void vpmaxud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3F); } +void vpmaxuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3E); } +void vpminsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x38); } +void vpminsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x39); } +void vpminsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xEA); } +void vpminub(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xDA); } +void vpminud(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x3B); } +void vpminuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x3A); } +void vpmovmskb(const Reg32e& r, const Xmm& x) { if (!x.is(Operand::XMM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(x.isYMM() ? Ymm(r.getIdx()) : Xmm(r.getIdx()), 0, x, T_0F | T_66 | T_YMM, 0xD7); } +void vpmovsxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x21); } +void vpmovsxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x22); } +void vpmovsxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x20); } +void vpmovsxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x25); } +void vpmovsxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x23); } +void vpmovsxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x24); } +void vpmovzxbd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x31); } +void vpmovzxbq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N2 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x32); } +void vpmovzxbw(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x30); } +void vpmovzxdq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX, 0x35); } +void vpmovzxwd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x33); } +void vpmovzxwq(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_N_VL | T_66 | T_0F38 | T_YMM | T_EVEX, 0x34); } +void vpmuldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x28); } +void vpmulhrsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x0B); } +void vpmulhuw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE4); } +void vpmulhw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE5); } +void vpmulld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x40); } +void vpmullw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD5); } +void vpmuludq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xF4); } +void vpor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEB); } +void vpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF6); } +void vpshufb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM | T_EVEX, 0x00); } +void vpshufd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x70, imm); } +void vpshufhw(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_F3 | T_0F | T_YMM | T_EVEX, 0x70, imm); } +void vpshuflw(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_F2 | T_0F | T_YMM | T_EVEX, 0x70, imm); } +void vpsignb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x08); } +void vpsignd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x0A); } +void vpsignw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_YMM, 0x09); } +void vpslld(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpslld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xF2); } +void vpslldq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 7), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); } +void vpsllq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); } +void vpsllq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xF3); } +void vpsllvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x47); } +void vpsllvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x47); } +void vpsllw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 6), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsllw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xF1); } +void vpsrad(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpsrad(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xE2); } +void vpsravd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x46); } +void vpsraw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsraw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xE1); } +void vpsrld(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32 | T_MEM_EVEX, 0x72, imm); } +void vpsrld(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW0 | T_YMM | T_EVEX, 0xD2); } +void vpsrldq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 3), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x73, imm); } +void vpsrlq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64 | T_MEM_EVEX, 0x73, imm); } +void vpsrlq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_EVEX, 0xD3); } +void vpsrlvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W0 | T_EW0 | T_YMM | T_EVEX | T_B32, 0x45); } +void vpsrlvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_W1 | T_EW1 | T_YMM | T_EVEX | T_B64, 0x45); } +void vpsrlw(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 2), x, op, T_66 | T_0F | T_YMM | T_EVEX | T_MEM_EVEX, 0x71, imm); } +void vpsrlw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_YMM | T_EVEX, 0xD1); } +void vpsubb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF8); } +void vpsubd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xFA); } +void vpsubq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xFB); } +void vpsubsb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE8); } +void vpsubsw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xE9); } +void vpsubusb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD8); } +void vpsubusw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xD9); } +void vpsubw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0xF9); } +void vptest(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x17); } +void vpunpckhbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x68); } +void vpunpckhdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x6A); } +void vpunpckhqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6D); } +void vpunpckhwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x69); } +void vpunpcklbw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x60); } +void vpunpckldq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x62); } +void vpunpcklqdq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x6C); } +void vpunpcklwd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM | T_EVEX, 0x61); } +void vpxor(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_YMM, 0xEF); } +void vrcpps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x53); } +void vrcpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x53); } +void vroundpd(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x09, imm); } +void vroundps(const Xmm& xm, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F3A | T_YMM, 0x08, imm); } +void vroundsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0B, imm); } +void vroundss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_W0, 0x0A, imm); } +void vrsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_YMM, 0x52); } +void vrsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F, 0x52); } +void vshufpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0xC6, imm); } +void vshufps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0xC6, imm); } +void vsqrtpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x51); } +void vsqrtps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x51); } +void vsqrtsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_0F | T_EW1 | T_EVEX | T_ER_X, 0x51); } +void vsqrtss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_F3 | T_0F | T_EW0 | T_EVEX | T_ER_X, 0x51); } +void vstmxcsr(const Address& addr) { opAVX_X_X_XM(xm3, xm0, addr, T_0F, 0xAE); } +void vsubpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x5C); } +void vsubps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x5C); } +void vsubsd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F2 | T_EW1 | T_EVEX | T_ER_X | T_N8, 0x5C); } +void vsubss(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_F3 | T_EW0 | T_EVEX | T_ER_X | T_N4, 0x5C); } +void vtestpd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0F); } +void vtestps(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_66 | T_0F38 | T_YMM, 0x0E); } +void vucomisd(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N8 | T_66 | T_0F | T_EW1 | T_EVEX | T_SAE_X, 0x2E); } +void vucomiss(const Xmm& xm, const Operand& op) { opAVX_X_XM_IMM(xm, op, T_N4 | T_0F | T_EW0 | T_EVEX | T_SAE_X, 0x2E); } +void vunpckhpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x15); } +void vunpckhps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x15); } +void vunpcklpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_EVEX | T_B64, 0x14); } +void vunpcklps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_0F | T_EW0 | T_YMM | T_EVEX | T_B32, 0x14); } +void vxorpd(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_66 | T_EW1 | T_YMM | T_EVEX | T_ER_Z | T_B64, 0x57); } +void vxorps(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_0F | T_EW0 | T_YMM | T_EVEX | T_ER_Z | T_B32, 0x57); } +void vzeroall() { db(0xC5); db(0xFC); db(0x77); } +void vzeroupper() { db(0xC5); db(0xF8); db(0x77); } +void wait() { db(0x9B); } +void wbinvd() { db(0x0F); db(0x09); } +void wrmsr() { db(0x0F); db(0x30); } +void xadd(const Operand& op, const Reg& reg) { opModRM(reg, op, (op.isREG() && reg.isREG() && op.getBit() == reg.getBit()), op.isMEM(), 0x0F, 0xC0 | (reg.isBit(8) ? 0 : 1)); } +void xgetbv() { db(0x0F); db(0x01); db(0xD0); } +void xlatb() { db(0xD7); } +void xor_(const Operand& op, uint32_t imm) { opRM_I(op, imm, 0x30, 6); } +void xor_(const Operand& op1, const Operand& op2) { opRM_RM(op1, op2, 0x30); } +void xorpd(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x66, isXMM_XMMorMEM); } +void xorps(const Xmm& xmm, const Operand& op) { opGen(xmm, op, 0x57, 0x100, isXMM_XMMorMEM); } +#ifdef XBYAK_ENABLE_OMITTED_OPERAND +void vblendpd(const Xmm& x, const Operand& op, uint8_t imm) { vblendpd(x, x, op, imm); } +void vblendps(const Xmm& x, const Operand& op, uint8_t imm) { vblendps(x, x, op, imm); } +void vblendvpd(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvpd(x1, x1, op, x4); } +void vblendvps(const Xmm& x1, const Operand& op, const Xmm& x4) { vblendvps(x1, x1, op, x4); } +void vcmpeq_ospd(const Xmm& x, const Operand& op) { vcmpeq_ospd(x, x, op); } +void vcmpeq_osps(const Xmm& x, const Operand& op) { vcmpeq_osps(x, x, op); } +void vcmpeq_ossd(const Xmm& x, const Operand& op) { vcmpeq_ossd(x, x, op); } +void vcmpeq_osss(const Xmm& x, const Operand& op) { vcmpeq_osss(x, x, op); } +void vcmpeq_uqpd(const Xmm& x, const Operand& op) { vcmpeq_uqpd(x, x, op); } +void vcmpeq_uqps(const Xmm& x, const Operand& op) { vcmpeq_uqps(x, x, op); } +void vcmpeq_uqsd(const Xmm& x, const Operand& op) { vcmpeq_uqsd(x, x, op); } +void vcmpeq_uqss(const Xmm& x, const Operand& op) { vcmpeq_uqss(x, x, op); } +void vcmpeq_uspd(const Xmm& x, const Operand& op) { vcmpeq_uspd(x, x, op); } +void vcmpeq_usps(const Xmm& x, const Operand& op) { vcmpeq_usps(x, x, op); } +void vcmpeq_ussd(const Xmm& x, const Operand& op) { vcmpeq_ussd(x, x, op); } +void vcmpeq_usss(const Xmm& x, const Operand& op) { vcmpeq_usss(x, x, op); } +void vcmpeqpd(const Xmm& x, const Operand& op) { vcmpeqpd(x, x, op); } +void vcmpeqps(const Xmm& x, const Operand& op) { vcmpeqps(x, x, op); } +void vcmpeqsd(const Xmm& x, const Operand& op) { vcmpeqsd(x, x, op); } +void vcmpeqss(const Xmm& x, const Operand& op) { vcmpeqss(x, x, op); } +void vcmpfalse_ospd(const Xmm& x, const Operand& op) { vcmpfalse_ospd(x, x, op); } +void vcmpfalse_osps(const Xmm& x, const Operand& op) { vcmpfalse_osps(x, x, op); } +void vcmpfalse_ossd(const Xmm& x, const Operand& op) { vcmpfalse_ossd(x, x, op); } +void vcmpfalse_osss(const Xmm& x, const Operand& op) { vcmpfalse_osss(x, x, op); } +void vcmpfalsepd(const Xmm& x, const Operand& op) { vcmpfalsepd(x, x, op); } +void vcmpfalseps(const Xmm& x, const Operand& op) { vcmpfalseps(x, x, op); } +void vcmpfalsesd(const Xmm& x, const Operand& op) { vcmpfalsesd(x, x, op); } +void vcmpfalsess(const Xmm& x, const Operand& op) { vcmpfalsess(x, x, op); } +void vcmpge_oqpd(const Xmm& x, const Operand& op) { vcmpge_oqpd(x, x, op); } +void vcmpge_oqps(const Xmm& x, const Operand& op) { vcmpge_oqps(x, x, op); } +void vcmpge_oqsd(const Xmm& x, const Operand& op) { vcmpge_oqsd(x, x, op); } +void vcmpge_oqss(const Xmm& x, const Operand& op) { vcmpge_oqss(x, x, op); } +void vcmpgepd(const Xmm& x, const Operand& op) { vcmpgepd(x, x, op); } +void vcmpgeps(const Xmm& x, const Operand& op) { vcmpgeps(x, x, op); } +void vcmpgesd(const Xmm& x, const Operand& op) { vcmpgesd(x, x, op); } +void vcmpgess(const Xmm& x, const Operand& op) { vcmpgess(x, x, op); } +void vcmpgt_oqpd(const Xmm& x, const Operand& op) { vcmpgt_oqpd(x, x, op); } +void vcmpgt_oqps(const Xmm& x, const Operand& op) { vcmpgt_oqps(x, x, op); } +void vcmpgt_oqsd(const Xmm& x, const Operand& op) { vcmpgt_oqsd(x, x, op); } +void vcmpgt_oqss(const Xmm& x, const Operand& op) { vcmpgt_oqss(x, x, op); } +void vcmpgtpd(const Xmm& x, const Operand& op) { vcmpgtpd(x, x, op); } +void vcmpgtps(const Xmm& x, const Operand& op) { vcmpgtps(x, x, op); } +void vcmpgtsd(const Xmm& x, const Operand& op) { vcmpgtsd(x, x, op); } +void vcmpgtss(const Xmm& x, const Operand& op) { vcmpgtss(x, x, op); } +void vcmple_oqpd(const Xmm& x, const Operand& op) { vcmple_oqpd(x, x, op); } +void vcmple_oqps(const Xmm& x, const Operand& op) { vcmple_oqps(x, x, op); } +void vcmple_oqsd(const Xmm& x, const Operand& op) { vcmple_oqsd(x, x, op); } +void vcmple_oqss(const Xmm& x, const Operand& op) { vcmple_oqss(x, x, op); } +void vcmplepd(const Xmm& x, const Operand& op) { vcmplepd(x, x, op); } +void vcmpleps(const Xmm& x, const Operand& op) { vcmpleps(x, x, op); } +void vcmplesd(const Xmm& x, const Operand& op) { vcmplesd(x, x, op); } +void vcmpless(const Xmm& x, const Operand& op) { vcmpless(x, x, op); } +void vcmplt_oqpd(const Xmm& x, const Operand& op) { vcmplt_oqpd(x, x, op); } +void vcmplt_oqps(const Xmm& x, const Operand& op) { vcmplt_oqps(x, x, op); } +void vcmplt_oqsd(const Xmm& x, const Operand& op) { vcmplt_oqsd(x, x, op); } +void vcmplt_oqss(const Xmm& x, const Operand& op) { vcmplt_oqss(x, x, op); } +void vcmpltpd(const Xmm& x, const Operand& op) { vcmpltpd(x, x, op); } +void vcmpltps(const Xmm& x, const Operand& op) { vcmpltps(x, x, op); } +void vcmpltsd(const Xmm& x, const Operand& op) { vcmpltsd(x, x, op); } +void vcmpltss(const Xmm& x, const Operand& op) { vcmpltss(x, x, op); } +void vcmpneq_oqpd(const Xmm& x, const Operand& op) { vcmpneq_oqpd(x, x, op); } +void vcmpneq_oqps(const Xmm& x, const Operand& op) { vcmpneq_oqps(x, x, op); } +void vcmpneq_oqsd(const Xmm& x, const Operand& op) { vcmpneq_oqsd(x, x, op); } +void vcmpneq_oqss(const Xmm& x, const Operand& op) { vcmpneq_oqss(x, x, op); } +void vcmpneq_ospd(const Xmm& x, const Operand& op) { vcmpneq_ospd(x, x, op); } +void vcmpneq_osps(const Xmm& x, const Operand& op) { vcmpneq_osps(x, x, op); } +void vcmpneq_ossd(const Xmm& x, const Operand& op) { vcmpneq_ossd(x, x, op); } +void vcmpneq_osss(const Xmm& x, const Operand& op) { vcmpneq_osss(x, x, op); } +void vcmpneq_uspd(const Xmm& x, const Operand& op) { vcmpneq_uspd(x, x, op); } +void vcmpneq_usps(const Xmm& x, const Operand& op) { vcmpneq_usps(x, x, op); } +void vcmpneq_ussd(const Xmm& x, const Operand& op) { vcmpneq_ussd(x, x, op); } +void vcmpneq_usss(const Xmm& x, const Operand& op) { vcmpneq_usss(x, x, op); } +void vcmpneqpd(const Xmm& x, const Operand& op) { vcmpneqpd(x, x, op); } +void vcmpneqps(const Xmm& x, const Operand& op) { vcmpneqps(x, x, op); } +void vcmpneqsd(const Xmm& x, const Operand& op) { vcmpneqsd(x, x, op); } +void vcmpneqss(const Xmm& x, const Operand& op) { vcmpneqss(x, x, op); } +void vcmpnge_uqpd(const Xmm& x, const Operand& op) { vcmpnge_uqpd(x, x, op); } +void vcmpnge_uqps(const Xmm& x, const Operand& op) { vcmpnge_uqps(x, x, op); } +void vcmpnge_uqsd(const Xmm& x, const Operand& op) { vcmpnge_uqsd(x, x, op); } +void vcmpnge_uqss(const Xmm& x, const Operand& op) { vcmpnge_uqss(x, x, op); } +void vcmpngepd(const Xmm& x, const Operand& op) { vcmpngepd(x, x, op); } +void vcmpngeps(const Xmm& x, const Operand& op) { vcmpngeps(x, x, op); } +void vcmpngesd(const Xmm& x, const Operand& op) { vcmpngesd(x, x, op); } +void vcmpngess(const Xmm& x, const Operand& op) { vcmpngess(x, x, op); } +void vcmpngt_uqpd(const Xmm& x, const Operand& op) { vcmpngt_uqpd(x, x, op); } +void vcmpngt_uqps(const Xmm& x, const Operand& op) { vcmpngt_uqps(x, x, op); } +void vcmpngt_uqsd(const Xmm& x, const Operand& op) { vcmpngt_uqsd(x, x, op); } +void vcmpngt_uqss(const Xmm& x, const Operand& op) { vcmpngt_uqss(x, x, op); } +void vcmpngtpd(const Xmm& x, const Operand& op) { vcmpngtpd(x, x, op); } +void vcmpngtps(const Xmm& x, const Operand& op) { vcmpngtps(x, x, op); } +void vcmpngtsd(const Xmm& x, const Operand& op) { vcmpngtsd(x, x, op); } +void vcmpngtss(const Xmm& x, const Operand& op) { vcmpngtss(x, x, op); } +void vcmpnle_uqpd(const Xmm& x, const Operand& op) { vcmpnle_uqpd(x, x, op); } +void vcmpnle_uqps(const Xmm& x, const Operand& op) { vcmpnle_uqps(x, x, op); } +void vcmpnle_uqsd(const Xmm& x, const Operand& op) { vcmpnle_uqsd(x, x, op); } +void vcmpnle_uqss(const Xmm& x, const Operand& op) { vcmpnle_uqss(x, x, op); } +void vcmpnlepd(const Xmm& x, const Operand& op) { vcmpnlepd(x, x, op); } +void vcmpnleps(const Xmm& x, const Operand& op) { vcmpnleps(x, x, op); } +void vcmpnlesd(const Xmm& x, const Operand& op) { vcmpnlesd(x, x, op); } +void vcmpnless(const Xmm& x, const Operand& op) { vcmpnless(x, x, op); } +void vcmpnlt_uqpd(const Xmm& x, const Operand& op) { vcmpnlt_uqpd(x, x, op); } +void vcmpnlt_uqps(const Xmm& x, const Operand& op) { vcmpnlt_uqps(x, x, op); } +void vcmpnlt_uqsd(const Xmm& x, const Operand& op) { vcmpnlt_uqsd(x, x, op); } +void vcmpnlt_uqss(const Xmm& x, const Operand& op) { vcmpnlt_uqss(x, x, op); } +void vcmpnltpd(const Xmm& x, const Operand& op) { vcmpnltpd(x, x, op); } +void vcmpnltps(const Xmm& x, const Operand& op) { vcmpnltps(x, x, op); } +void vcmpnltsd(const Xmm& x, const Operand& op) { vcmpnltsd(x, x, op); } +void vcmpnltss(const Xmm& x, const Operand& op) { vcmpnltss(x, x, op); } +void vcmpord_spd(const Xmm& x, const Operand& op) { vcmpord_spd(x, x, op); } +void vcmpord_sps(const Xmm& x, const Operand& op) { vcmpord_sps(x, x, op); } +void vcmpord_ssd(const Xmm& x, const Operand& op) { vcmpord_ssd(x, x, op); } +void vcmpord_sss(const Xmm& x, const Operand& op) { vcmpord_sss(x, x, op); } +void vcmpordpd(const Xmm& x, const Operand& op) { vcmpordpd(x, x, op); } +void vcmpordps(const Xmm& x, const Operand& op) { vcmpordps(x, x, op); } +void vcmpordsd(const Xmm& x, const Operand& op) { vcmpordsd(x, x, op); } +void vcmpordss(const Xmm& x, const Operand& op) { vcmpordss(x, x, op); } +void vcmppd(const Xmm& x, const Operand& op, uint8_t imm) { vcmppd(x, x, op, imm); } +void vcmpps(const Xmm& x, const Operand& op, uint8_t imm) { vcmpps(x, x, op, imm); } +void vcmpsd(const Xmm& x, const Operand& op, uint8_t imm) { vcmpsd(x, x, op, imm); } +void vcmpss(const Xmm& x, const Operand& op, uint8_t imm) { vcmpss(x, x, op, imm); } +void vcmptrue_uspd(const Xmm& x, const Operand& op) { vcmptrue_uspd(x, x, op); } +void vcmptrue_usps(const Xmm& x, const Operand& op) { vcmptrue_usps(x, x, op); } +void vcmptrue_ussd(const Xmm& x, const Operand& op) { vcmptrue_ussd(x, x, op); } +void vcmptrue_usss(const Xmm& x, const Operand& op) { vcmptrue_usss(x, x, op); } +void vcmptruepd(const Xmm& x, const Operand& op) { vcmptruepd(x, x, op); } +void vcmptrueps(const Xmm& x, const Operand& op) { vcmptrueps(x, x, op); } +void vcmptruesd(const Xmm& x, const Operand& op) { vcmptruesd(x, x, op); } +void vcmptruess(const Xmm& x, const Operand& op) { vcmptruess(x, x, op); } +void vcmpunord_spd(const Xmm& x, const Operand& op) { vcmpunord_spd(x, x, op); } +void vcmpunord_sps(const Xmm& x, const Operand& op) { vcmpunord_sps(x, x, op); } +void vcmpunord_ssd(const Xmm& x, const Operand& op) { vcmpunord_ssd(x, x, op); } +void vcmpunord_sss(const Xmm& x, const Operand& op) { vcmpunord_sss(x, x, op); } +void vcmpunordpd(const Xmm& x, const Operand& op) { vcmpunordpd(x, x, op); } +void vcmpunordps(const Xmm& x, const Operand& op) { vcmpunordps(x, x, op); } +void vcmpunordsd(const Xmm& x, const Operand& op) { vcmpunordsd(x, x, op); } +void vcmpunordss(const Xmm& x, const Operand& op) { vcmpunordss(x, x, op); } +void vcvtsd2ss(const Xmm& x, const Operand& op) { vcvtsd2ss(x, x, op); } +void vcvtsi2sd(const Xmm& x, const Operand& op) { vcvtsi2sd(x, x, op); } +void vcvtsi2ss(const Xmm& x, const Operand& op) { vcvtsi2ss(x, x, op); } +void vcvtss2sd(const Xmm& x, const Operand& op) { vcvtss2sd(x, x, op); } +void vdppd(const Xmm& x, const Operand& op, uint8_t imm) { vdppd(x, x, op, imm); } +void vdpps(const Xmm& x, const Operand& op, uint8_t imm) { vdpps(x, x, op, imm); } +void vinsertps(const Xmm& x, const Operand& op, uint8_t imm) { vinsertps(x, x, op, imm); } +void vmpsadbw(const Xmm& x, const Operand& op, uint8_t imm) { vmpsadbw(x, x, op, imm); } +void vpackssdw(const Xmm& x, const Operand& op) { vpackssdw(x, x, op); } +void vpacksswb(const Xmm& x, const Operand& op) { vpacksswb(x, x, op); } +void vpackusdw(const Xmm& x, const Operand& op) { vpackusdw(x, x, op); } +void vpackuswb(const Xmm& x, const Operand& op) { vpackuswb(x, x, op); } +void vpaddb(const Xmm& x, const Operand& op) { vpaddb(x, x, op); } +void vpaddd(const Xmm& x, const Operand& op) { vpaddd(x, x, op); } +void vpaddq(const Xmm& x, const Operand& op) { vpaddq(x, x, op); } +void vpaddsb(const Xmm& x, const Operand& op) { vpaddsb(x, x, op); } +void vpaddsw(const Xmm& x, const Operand& op) { vpaddsw(x, x, op); } +void vpaddusb(const Xmm& x, const Operand& op) { vpaddusb(x, x, op); } +void vpaddusw(const Xmm& x, const Operand& op) { vpaddusw(x, x, op); } +void vpaddw(const Xmm& x, const Operand& op) { vpaddw(x, x, op); } +void vpalignr(const Xmm& x, const Operand& op, uint8_t imm) { vpalignr(x, x, op, imm); } +void vpand(const Xmm& x, const Operand& op) { vpand(x, x, op); } +void vpandn(const Xmm& x, const Operand& op) { vpandn(x, x, op); } +void vpavgb(const Xmm& x, const Operand& op) { vpavgb(x, x, op); } +void vpavgw(const Xmm& x, const Operand& op) { vpavgw(x, x, op); } +void vpblendd(const Xmm& x, const Operand& op, uint8_t imm) { vpblendd(x, x, op, imm); } +void vpblendvb(const Xmm& x1, const Operand& op, const Xmm& x4) { vpblendvb(x1, x1, op, x4); } +void vpblendw(const Xmm& x, const Operand& op, uint8_t imm) { vpblendw(x, x, op, imm); } +void vpclmulqdq(const Xmm& x, const Operand& op, uint8_t imm) { vpclmulqdq(x, x, op, imm); } +void vpcmpeqb(const Xmm& x, const Operand& op) { vpcmpeqb(x, x, op); } +void vpcmpeqd(const Xmm& x, const Operand& op) { vpcmpeqd(x, x, op); } +void vpcmpeqq(const Xmm& x, const Operand& op) { vpcmpeqq(x, x, op); } +void vpcmpeqw(const Xmm& x, const Operand& op) { vpcmpeqw(x, x, op); } +void vpcmpgtb(const Xmm& x, const Operand& op) { vpcmpgtb(x, x, op); } +void vpcmpgtd(const Xmm& x, const Operand& op) { vpcmpgtd(x, x, op); } +void vpcmpgtq(const Xmm& x, const Operand& op) { vpcmpgtq(x, x, op); } +void vpcmpgtw(const Xmm& x, const Operand& op) { vpcmpgtw(x, x, op); } +void vphaddd(const Xmm& x, const Operand& op) { vphaddd(x, x, op); } +void vphaddsw(const Xmm& x, const Operand& op) { vphaddsw(x, x, op); } +void vphaddw(const Xmm& x, const Operand& op) { vphaddw(x, x, op); } +void vphsubd(const Xmm& x, const Operand& op) { vphsubd(x, x, op); } +void vphsubsw(const Xmm& x, const Operand& op) { vphsubsw(x, x, op); } +void vphsubw(const Xmm& x, const Operand& op) { vphsubw(x, x, op); } +void vpinsrb(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrb(x, x, op, imm); } +void vpinsrd(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrd(x, x, op, imm); } +void vpinsrq(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrq(x, x, op, imm); } +void vpinsrw(const Xmm& x, const Operand& op, uint8_t imm) { vpinsrw(x, x, op, imm); } +void vpmaddubsw(const Xmm& x, const Operand& op) { vpmaddubsw(x, x, op); } +void vpmaddwd(const Xmm& x, const Operand& op) { vpmaddwd(x, x, op); } +void vpmaxsb(const Xmm& x, const Operand& op) { vpmaxsb(x, x, op); } +void vpmaxsd(const Xmm& x, const Operand& op) { vpmaxsd(x, x, op); } +void vpmaxsw(const Xmm& x, const Operand& op) { vpmaxsw(x, x, op); } +void vpmaxub(const Xmm& x, const Operand& op) { vpmaxub(x, x, op); } +void vpmaxud(const Xmm& x, const Operand& op) { vpmaxud(x, x, op); } +void vpmaxuw(const Xmm& x, const Operand& op) { vpmaxuw(x, x, op); } +void vpminsb(const Xmm& x, const Operand& op) { vpminsb(x, x, op); } +void vpminsd(const Xmm& x, const Operand& op) { vpminsd(x, x, op); } +void vpminsw(const Xmm& x, const Operand& op) { vpminsw(x, x, op); } +void vpminub(const Xmm& x, const Operand& op) { vpminub(x, x, op); } +void vpminud(const Xmm& x, const Operand& op) { vpminud(x, x, op); } +void vpminuw(const Xmm& x, const Operand& op) { vpminuw(x, x, op); } +void vpmuldq(const Xmm& x, const Operand& op) { vpmuldq(x, x, op); } +void vpmulhrsw(const Xmm& x, const Operand& op) { vpmulhrsw(x, x, op); } +void vpmulhuw(const Xmm& x, const Operand& op) { vpmulhuw(x, x, op); } +void vpmulhw(const Xmm& x, const Operand& op) { vpmulhw(x, x, op); } +void vpmulld(const Xmm& x, const Operand& op) { vpmulld(x, x, op); } +void vpmullw(const Xmm& x, const Operand& op) { vpmullw(x, x, op); } +void vpmuludq(const Xmm& x, const Operand& op) { vpmuludq(x, x, op); } +void vpor(const Xmm& x, const Operand& op) { vpor(x, x, op); } +void vpsadbw(const Xmm& x, const Operand& op) { vpsadbw(x, x, op); } +void vpsignb(const Xmm& x, const Operand& op) { vpsignb(x, x, op); } +void vpsignd(const Xmm& x, const Operand& op) { vpsignd(x, x, op); } +void vpsignw(const Xmm& x, const Operand& op) { vpsignw(x, x, op); } +void vpslld(const Xmm& x, const Operand& op) { vpslld(x, x, op); } +void vpslld(const Xmm& x, uint8_t imm) { vpslld(x, x, imm); } +void vpslldq(const Xmm& x, uint8_t imm) { vpslldq(x, x, imm); } +void vpsllq(const Xmm& x, const Operand& op) { vpsllq(x, x, op); } +void vpsllq(const Xmm& x, uint8_t imm) { vpsllq(x, x, imm); } +void vpsllw(const Xmm& x, const Operand& op) { vpsllw(x, x, op); } +void vpsllw(const Xmm& x, uint8_t imm) { vpsllw(x, x, imm); } +void vpsrad(const Xmm& x, const Operand& op) { vpsrad(x, x, op); } +void vpsrad(const Xmm& x, uint8_t imm) { vpsrad(x, x, imm); } +void vpsraw(const Xmm& x, const Operand& op) { vpsraw(x, x, op); } +void vpsraw(const Xmm& x, uint8_t imm) { vpsraw(x, x, imm); } +void vpsrld(const Xmm& x, const Operand& op) { vpsrld(x, x, op); } +void vpsrld(const Xmm& x, uint8_t imm) { vpsrld(x, x, imm); } +void vpsrldq(const Xmm& x, uint8_t imm) { vpsrldq(x, x, imm); } +void vpsrlq(const Xmm& x, const Operand& op) { vpsrlq(x, x, op); } +void vpsrlq(const Xmm& x, uint8_t imm) { vpsrlq(x, x, imm); } +void vpsrlw(const Xmm& x, const Operand& op) { vpsrlw(x, x, op); } +void vpsrlw(const Xmm& x, uint8_t imm) { vpsrlw(x, x, imm); } +void vpsubb(const Xmm& x, const Operand& op) { vpsubb(x, x, op); } +void vpsubd(const Xmm& x, const Operand& op) { vpsubd(x, x, op); } +void vpsubq(const Xmm& x, const Operand& op) { vpsubq(x, x, op); } +void vpsubsb(const Xmm& x, const Operand& op) { vpsubsb(x, x, op); } +void vpsubsw(const Xmm& x, const Operand& op) { vpsubsw(x, x, op); } +void vpsubusb(const Xmm& x, const Operand& op) { vpsubusb(x, x, op); } +void vpsubusw(const Xmm& x, const Operand& op) { vpsubusw(x, x, op); } +void vpsubw(const Xmm& x, const Operand& op) { vpsubw(x, x, op); } +void vpunpckhbw(const Xmm& x, const Operand& op) { vpunpckhbw(x, x, op); } +void vpunpckhdq(const Xmm& x, const Operand& op) { vpunpckhdq(x, x, op); } +void vpunpckhqdq(const Xmm& x, const Operand& op) { vpunpckhqdq(x, x, op); } +void vpunpckhwd(const Xmm& x, const Operand& op) { vpunpckhwd(x, x, op); } +void vpunpcklbw(const Xmm& x, const Operand& op) { vpunpcklbw(x, x, op); } +void vpunpckldq(const Xmm& x, const Operand& op) { vpunpckldq(x, x, op); } +void vpunpcklqdq(const Xmm& x, const Operand& op) { vpunpcklqdq(x, x, op); } +void vpunpcklwd(const Xmm& x, const Operand& op) { vpunpcklwd(x, x, op); } +void vpxor(const Xmm& x, const Operand& op) { vpxor(x, x, op); } +void vrcpss(const Xmm& x, const Operand& op) { vrcpss(x, x, op); } +void vroundsd(const Xmm& x, const Operand& op, uint8_t imm) { vroundsd(x, x, op, imm); } +void vroundss(const Xmm& x, const Operand& op, uint8_t imm) { vroundss(x, x, op, imm); } +void vrsqrtss(const Xmm& x, const Operand& op) { vrsqrtss(x, x, op); } +void vshufpd(const Xmm& x, const Operand& op, uint8_t imm) { vshufpd(x, x, op, imm); } +void vshufps(const Xmm& x, const Operand& op, uint8_t imm) { vshufps(x, x, op, imm); } +void vsqrtsd(const Xmm& x, const Operand& op) { vsqrtsd(x, x, op); } +void vsqrtss(const Xmm& x, const Operand& op) { vsqrtss(x, x, op); } +void vunpckhpd(const Xmm& x, const Operand& op) { vunpckhpd(x, x, op); } +void vunpckhps(const Xmm& x, const Operand& op) { vunpckhps(x, x, op); } +void vunpcklpd(const Xmm& x, const Operand& op) { vunpcklpd(x, x, op); } +void vunpcklps(const Xmm& x, const Operand& op) { vunpcklps(x, x, op); } +#endif +#ifdef XBYAK64 +void jecxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jrcxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jrcxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void cdqe() { db(0x48); db(0x98); } +void cqo() { db(0x48); db(0x99); } +void cmpsq() { db(0x48); db(0xA7); } +void popfq() { db(0x9D); } +void pushfq() { db(0x9C); } +void lodsq() { db(0x48); db(0xAD); } +void movsq() { db(0x48); db(0xA5); } +void scasq() { db(0x48); db(0xAF); } +void stosq() { db(0x48); db(0xAB); } +void syscall() { db(0x0F); db(0x05); } +void sysret() { db(0x0F); db(0x07); } +void cmpxchg16b(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xC7); } +void fxrstor64(const Address& addr) { opModM(addr, Reg64(1), 0x0F, 0xAE); } +void movq(const Reg64& reg, const Mmx& mmx) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x7E); } +void movq(const Mmx& mmx, const Reg64& reg) { if (mmx.isXMM()) db(0x66); opModR(mmx, reg, 0x0F, 0x6E); } +void movsxd(const Reg64& reg, const Operand& op) { if (!op.isBit(32)) XBYAK_THROW(ERR_BAD_COMBINATION) opModRM(reg, op, op.isREG(), op.isMEM(), 0x63); } +void pextrq(const Operand& op, const Xmm& xmm, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x16, 0x66, 0, imm, 0x3A); } +void pinsrq(const Xmm& xmm, const Operand& op, uint8_t imm) { if (!op.isREG(64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opGen(Reg64(xmm.getIdx()), op, 0x22, 0x66, 0, imm, 0x3A); } +void vcvtss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_ER_X | T_N8, 0x2D); } +void vcvttss2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F3 | T_W1 | T_EVEX | T_EW1 | T_SAE_X | T_N8, 0x2C); } +void vcvtsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_ER_X, 0x2D); } +void vcvttsd2si(const Reg64& r, const Operand& op) { opAVX_X_X_XM(Xmm(r.getIdx()), xm0, op, T_0F | T_F2 | T_W1 | T_EVEX | T_EW1 | T_N4 | T_SAE_X, 0x2C); } +void vmovq(const Xmm& x, const Reg64& r) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x6E); } +void vmovq(const Reg64& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, Xmm(r.getIdx()), T_66 | T_0F | T_W1 | T_EVEX | T_EW1, 0x7E); } +void cmpbexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE6, false); } +void cmpbxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE2, false); } +void cmplexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEE, false); } +void cmplxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEC, false); } +void cmpnbexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE7, false); } +void cmpnbxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE3, false); } +void cmpnlexadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEF, false); } +void cmpnlxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xED, false); } +void cmpnoxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE1, false); } +void cmpnpxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEB, false); } +void cmpnsxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE9, false); } +void cmpnzxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE5, false); } +void cmpoxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE0, false); } +void cmppxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xEA, false); } +void cmpsxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE8, false); } +void cmpzxadd(const Address& addr, const Reg32e& r1, const Reg32e& r2) { opGpr(r1, addr, r2, T_66 | T_0F38, 0xE4, false); } +void ldtilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_0F38 | T_W0, 0x49); } +void sttilecfg(const Address& addr) { opVex(tmm0, &tmm0, addr, T_66 | T_0F38 | T_W0, 0x49); } +void tileloadd(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_F2 | T_0F38 | T_W0, 0x4b); } +void tileloaddt1(const Tmm& tm, const Address& addr) { opAMX(tm, addr, T_66 | T_0F38 | T_W0, 0x4b); } +void tilerelease() { db(0xc4); db(0xe2); db(0x78); db(0x49); db(0xc0); } +void tilestored(const Address& addr, const Tmm& tm) { opVex(tm, &tmm0, addr, T_F3 | T_0F38 | T_W0, 0x4b); } +void tilezero(const Tmm& Tmm) { opVex(Tmm, &tmm0, tmm0, T_F2 | T_0F38 | T_W0, 0x49); } +void tdpbssd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F2 | T_0F38 | T_W0, 0x5e); } +void tdpbsud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5e); } +void tdpbusd(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_66 | T_0F38 | T_W0, 0x5e); } +void tdpbuud(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_0F38 | T_W0, 0x5e); } +void tdpfp16ps(const Tmm &x1, const Tmm &x2, const Tmm &x3) { opVex(x1, &x3, x2, T_F2 | T_0F38 | T_W0, 0x5c); } +void tdpbf16ps(const Tmm& x1, const Tmm& x2, const Tmm& x3) { opVex(x1, &x3, x2, T_F3 | T_0F38 | T_W0, 0x5c); } +#else +void jcxz(std::string label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jcxz(const Label& label) { db(0x67); opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(std::string label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void jecxz(const Label& label) { opJmp(label, T_SHORT, 0xe3, 0, 0); } +void aaa() { db(0x37); } +void aad() { db(0xD5); db(0x0A); } +void aam() { db(0xD4); db(0x0A); } +void aas() { db(0x3F); } +void daa() { db(0x27); } +void das() { db(0x2F); } +void into() { db(0xCE); } +void popad() { db(0x61); } +void popfd() { db(0x9D); } +void pusha() { db(0x60); } +void pushad() { db(0x60); } +void pushfd() { db(0x9C); } +void popa() { db(0x61); } +void lds(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0xC5, 0x100); } +void les(const Reg& reg, const Address& addr) { opLoadSeg(addr, reg, 0xC4, 0x100); } +#endif +#ifndef XBYAK_NO_OP_NAMES +void and(const Operand& op1, const Operand& op2) { and_(op1, op2); } +void and(const Operand& op, uint32_t imm) { and_(op, imm); } +void or(const Operand& op1, const Operand& op2) { or_(op1, op2); } +void or(const Operand& op, uint32_t imm) { or_(op, imm); } +void xor(const Operand& op1, const Operand& op2) { xor_(op1, op2); } +void xor(const Operand& op, uint32_t imm) { xor_(op, imm); } +void not(const Operand& op) { not_(op); } +#endif +#ifndef XBYAK_DISABLE_AVX512 +void kaddb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4A); } +void kaddd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x4A); } +void kaddq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4A); } +void kaddw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4A); } +void kandb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x41); } +void kandd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x41); } +void kandnb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x42); } +void kandnd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x42); } +void kandnq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x42); } +void kandnw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x42); } +void kandq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x41); } +void kandw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x41); } +void kmovb(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W0, 0x91); } +void kmovb(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W0, 0x90); } +void kmovb(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_66 | T_W0, 0x92); } +void kmovb(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_66 | T_W0, 0x93); } +void kmovd(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_66 | T_W1, 0x91); } +void kmovd(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_66 | T_W1, 0x90); } +void kmovd(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W0, 0x92); } +void kmovd(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W0, 0x93); } +void kmovq(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W1, 0x91); } +void kmovq(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W1, 0x90); } +void kmovw(const Address& addr, const Opmask& k) { opVex(k, 0, addr, T_L0 | T_0F | T_W0, 0x91); } +void kmovw(const Opmask& k, const Operand& op) { if (!op.isMEM() && !op.isOPMASK()) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(k, 0, op, T_L0 | T_0F | T_W0, 0x90); } +void kmovw(const Opmask& k, const Reg32& r) { opVex(k, 0, r, T_L0 | T_0F | T_W0, 0x92); } +void kmovw(const Reg32& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_W0, 0x93); } +void knotb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x44); } +void knotd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x44); } +void knotq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x44); } +void knotw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x44); } +void korb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x45); } +void kord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x45); } +void korq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x45); } +void kortestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x98); } +void kortestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x98); } +void kortestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x98); } +void kortestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x98); } +void korw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x45); } +void kshiftlb(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x32, imm); } +void kshiftld(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x33, imm); } +void kshiftlq(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x33, imm); } +void kshiftlw(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x32, imm); } +void kshiftrb(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x30, imm); } +void kshiftrd(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W0, 0x31, imm); } +void kshiftrq(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x31, imm); } +void kshiftrw(const Opmask& r1, const Opmask& r2, uint8_t imm) { opVex(r1, 0, r2, T_66 | T_0F3A | T_W1, 0x30, imm); } +void ktestb(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W0, 0x99); } +void ktestd(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_66 | T_W1, 0x99); } +void ktestq(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W1, 0x99); } +void ktestw(const Opmask& r1, const Opmask& r2) { opVex(r1, 0, r2, T_0F | T_W0, 0x99); } +void kunpckbw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x4B); } +void kunpckdq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x4B); } +void kunpckwd(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x4B); } +void kxnorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x46); } +void kxnord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x46); } +void kxnorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x46); } +void kxnorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x46); } +void kxorb(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W0, 0x47); } +void kxord(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_66 | T_W1, 0x47); } +void kxorq(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W1, 0x47); } +void kxorw(const Opmask& r1, const Opmask& r2, const Opmask& r3) { opVex(r1, &r2, r3, T_L1 | T_0F | T_W0, 0x47); } +void v4fmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x9A); } +void v4fmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0x9B); } +void v4fnmaddps(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0xAA); } +void v4fnmaddss(const Xmm& x1, const Xmm& x2, const Address& addr) { opAVX_X_X_XM(x1, x2, addr, T_0F38 | T_F2 | T_EW0 | T_MUST_EVEX | T_N16, 0xAB); } +void vaddph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x58); } +void vaddsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x58); } +void valignd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x03, imm); } +void valignq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x03, imm); } +void vblendmpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x65); } +void vblendmps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x65); } +void vbroadcastf32x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x19); } +void vbroadcastf32x4(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x1A); } +void vbroadcastf32x8(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x1B); } +void vbroadcastf64x2(const Ymm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x1A); } +void vbroadcastf64x4(const Zmm& y, const Address& addr) { opAVX_X_XM_IMM(y, addr, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x1B); } +void vbroadcasti32x2(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N8, 0x59); } +void vbroadcasti32x4(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N16, 0x5A); } +void vbroadcasti32x8(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0 | T_N32, 0x5B); } +void vbroadcasti64x2(const Ymm& y, const Operand& op) { opAVX_X_XM_IMM(y, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N16, 0x5A); } +void vbroadcasti64x4(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1 | T_N32, 0x5B); } +void vcmpeq_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 16); } +void vcmpeq_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 16); } +void vcmpeq_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 16); } +void vcmpeq_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 16); } +void vcmpeq_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 8); } +void vcmpeq_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 8); } +void vcmpeq_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 8); } +void vcmpeq_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 8); } +void vcmpeq_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 24); } +void vcmpeq_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 24); } +void vcmpeq_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 24); } +void vcmpeq_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 24); } +void vcmpeqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 0); } +void vcmpeqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 0); } +void vcmpeqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 0); } +void vcmpeqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 0); } +void vcmpfalse_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 27); } +void vcmpfalse_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 27); } +void vcmpfalse_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 27); } +void vcmpfalse_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 27); } +void vcmpfalsepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 11); } +void vcmpfalseps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 11); } +void vcmpfalsesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 11); } +void vcmpfalsess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 11); } +void vcmpge_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 29); } +void vcmpge_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 29); } +void vcmpge_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 29); } +void vcmpge_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 29); } +void vcmpgepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 13); } +void vcmpgeps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 13); } +void vcmpgesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 13); } +void vcmpgess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 13); } +void vcmpgt_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 30); } +void vcmpgt_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 30); } +void vcmpgt_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 30); } +void vcmpgt_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 30); } +void vcmpgtpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 14); } +void vcmpgtps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 14); } +void vcmpgtsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 14); } +void vcmpgtss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 14); } +void vcmple_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 18); } +void vcmple_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 18); } +void vcmple_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 18); } +void vcmple_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 18); } +void vcmplepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 2); } +void vcmpleps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 2); } +void vcmplesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 2); } +void vcmpless(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 2); } +void vcmplt_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 17); } +void vcmplt_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 17); } +void vcmplt_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 17); } +void vcmplt_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 17); } +void vcmpltpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 1); } +void vcmpltps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 1); } +void vcmpltsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 1); } +void vcmpltss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 1); } +void vcmpneq_oqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 12); } +void vcmpneq_oqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 12); } +void vcmpneq_oqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 12); } +void vcmpneq_oqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 12); } +void vcmpneq_ospd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 28); } +void vcmpneq_osps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 28); } +void vcmpneq_ossd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 28); } +void vcmpneq_osss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 28); } +void vcmpneq_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 20); } +void vcmpneq_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 20); } +void vcmpneq_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 20); } +void vcmpneq_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 20); } +void vcmpneqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 4); } +void vcmpneqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 4); } +void vcmpneqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 4); } +void vcmpneqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 4); } +void vcmpnge_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 25); } +void vcmpnge_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 25); } +void vcmpnge_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 25); } +void vcmpnge_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 25); } +void vcmpngepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 9); } +void vcmpngeps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 9); } +void vcmpngesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 9); } +void vcmpngess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 9); } +void vcmpngt_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 26); } +void vcmpngt_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 26); } +void vcmpngt_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 26); } +void vcmpngt_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 26); } +void vcmpngtpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 10); } +void vcmpngtps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 10); } +void vcmpngtsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 10); } +void vcmpngtss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 10); } +void vcmpnle_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 22); } +void vcmpnle_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 22); } +void vcmpnle_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 22); } +void vcmpnle_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 22); } +void vcmpnlepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 6); } +void vcmpnleps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 6); } +void vcmpnlesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 6); } +void vcmpnless(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 6); } +void vcmpnlt_uqpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 21); } +void vcmpnlt_uqps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 21); } +void vcmpnlt_uqsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 21); } +void vcmpnlt_uqss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 21); } +void vcmpnltpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 5); } +void vcmpnltps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 5); } +void vcmpnltsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 5); } +void vcmpnltss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 5); } +void vcmpord_spd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 23); } +void vcmpord_sps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 23); } +void vcmpord_ssd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 23); } +void vcmpord_sss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 23); } +void vcmpordpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 7); } +void vcmpordps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 7); } +void vcmpordsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 7); } +void vcmpordss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 7); } +void vcmppd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0xC2, imm); } +void vcmpph(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0xC2, imm); } +void vcmpps(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0xC2, imm); } +void vcmpsd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N8 | T_F2 | T_0F | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcmpsh(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N2 | T_F3 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xC2, imm); } +void vcmpss(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_N4 | T_F3 | T_0F | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0xC2, imm); } +void vcmptrue_uspd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 31); } +void vcmptrue_usps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 31); } +void vcmptrue_ussd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 31); } +void vcmptrue_usss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 31); } +void vcmptruepd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 15); } +void vcmptrueps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 15); } +void vcmptruesd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 15); } +void vcmptruess(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 15); } +void vcmpunord_spd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 19); } +void vcmpunord_sps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 19); } +void vcmpunord_ssd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 19); } +void vcmpunord_sss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 19); } +void vcmpunordpd(const Opmask& k, const Xmm& x, const Operand& op) { vcmppd(k, x, op, 3); } +void vcmpunordps(const Opmask& k, const Xmm& x, const Operand& op) { vcmpps(k, x, op, 3); } +void vcmpunordsd(const Opmask& k, const Xmm& x, const Operand& op) { vcmpsd(k, x, op, 3); } +void vcmpunordss(const Opmask& k, const Xmm& x, const Operand& op) { vcmpss(k, x, op, 3); } +void vcomish(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_MUST_EVEX | T_EW0 | T_SAE_X | T_N2, 0x2F); } +void vcompressb(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x63); } +void vcompresspd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8A); } +void vcompressps(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8A); } +void vcompressw(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x63); } +void vcvtdq2ph(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x5B); } +void vcvtne2ps2bf16(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x72); } +void vcvtpd2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_66 | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x5A); } +void vcvtpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7B); } +void vcvtpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); } +void vcvtpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x79); } +void vcvtph2dq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B16, 0x5B); } +void vcvtph2pd(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x5A); } +void vcvtph2psx(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_MAP6 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x13); } +void vcvtph2qq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_X | T_MUST_EVEX | T_B16, 0x7B); } +void vcvtph2udq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B16, 0x79); } +void vcvtph2uqq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_X | T_MUST_EVEX | T_B16, 0x79); } +void vcvtph2uw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); } +void vcvtph2w(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); } +void vcvtps2phx(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_ER_Z | T_MUST_EVEX | T_B32, 0x1D); } +void vcvtps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B32, 0x7B); } +void vcvtps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x79); } +void vcvtps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_ER_Y | T_MUST_EVEX | T_B32, 0x79); } +void vcvtqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0xE6); } +void vcvtqq2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x5B); } +void vcvtqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x5B); } +void vcvtsd2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_F2 | T_MAP5 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x5A); } +void vcvtsd2usi(const Reg32e& r, const Operand& op) { int type = (T_N8 | T_F2 | T_0F | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); } +void vcvtsh2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x5A); } +void vcvtsh2si(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x2D); } +void vcvtsh2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_MAP6 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x13); } +void vcvtsh2usi(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); } +void vcvtsi2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { if (!(x1.isXMM() && x2.isXMM() && op.isBit(32|64))) XBYAK_THROW(ERR_BAD_COMBINATION) int type = (T_F3 | T_MAP5 | T_ER_R | T_MUST_EVEX | T_M_K) | (op.isBit(32) ? (T_EW0 | T_N4) : (T_EW1 | T_N8)); opVex(x1, &x2, op, type, 0x2A); } +void vcvtss2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_MAP5 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x1D); } +void vcvtss2usi(const Reg32e& r, const Operand& op) { int type = (T_N4 | T_F3 | T_0F | T_ER_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x79); } +void vcvttpd2qq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvttpd2udq(const Xmm& x, const Operand& op) { opCvt2(x, op, T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); } +void vcvttpd2uqq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x78); } +void vcvttph2dq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_F3 | T_MAP5 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x5B); } +void vcvttph2qq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x7A); } +void vcvttph2udq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_MAP5 | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B16, 0x78); } +void vcvttph2uqq(const Xmm& x, const Operand& op) { if (!op.isXMM() && !op.isMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(x, 0, op, T_N4 | T_N_VL | T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_X | T_MUST_EVEX | T_B16, 0x78); } +void vcvttph2uw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x7C); } +void vcvttph2w(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP5 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x7C); } +void vcvttps2qq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B32, 0x7A); } +void vcvttps2udq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_0F | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x78); } +void vcvttps2uqq(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_66 | T_0F | T_EW0 | T_YMM | T_SAE_Y | T_MUST_EVEX | T_B32, 0x78); } +void vcvttsd2usi(const Reg32e& r, const Operand& op) { int type = (T_N8 | T_F2 | T_0F | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); } +void vcvttsh2si(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x2C); } +void vcvttsh2usi(const Reg32e& r, const Operand& op) { int type = (T_N2 | T_F3 | T_MAP5 | T_EW0 | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); } +void vcvttss2usi(const Reg32e& r, const Operand& op) { int type = (T_N4 | T_F3 | T_0F | T_SAE_X | T_MUST_EVEX) | (r.isREG(64) ? T_EW1 : T_EW0); opVex(r, &xm0, op, type, 0x78); } +void vcvtudq2pd(const Xmm& x, const Operand& op) { checkCvt1(x, op); opVex(x, 0, op, T_N8 | T_N_VL | T_F3 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7A); } +void vcvtudq2ph(const Xmm& x, const Operand& op) { checkCvt4(x, op); opCvt(x, op, T_N16 | T_N_VL | T_F2 | T_MAP5 | T_EW0 | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); } +void vcvtudq2ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x7A); } +void vcvtuqq2pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvtuqq2ph(const Xmm& x, const Operand& op) { opCvt5(x, op, T_N16 | T_N_VL | T_F2 | T_MAP5 | T_EW1 | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvtuqq2ps(const Xmm& x, const Operand& op) { opCvt2(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x7A); } +void vcvtusi2sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F2 | T_0F | T_MUST_EVEX, T_W1 | T_EW1 | T_ER_X | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); } +void vcvtusi2sh(const Xmm& x1, const Xmm& x2, const Operand& op) { if (!(x1.isXMM() && x2.isXMM() && op.isBit(32|64))) XBYAK_THROW(ERR_BAD_COMBINATION) int type = (T_F3 | T_MAP5 | T_ER_R | T_MUST_EVEX | T_M_K) | (op.isBit(32) ? (T_EW0 | T_N4) : (T_EW1 | T_N8)); opVex(x1, &x2, op, type, 0x7B); } +void vcvtusi2ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opCvt3(x1, x2, op, T_F3 | T_0F | T_MUST_EVEX | T_ER_X, T_W1 | T_EW1 | T_N8, T_W0 | T_EW0 | T_N4, 0x7B); } +void vcvtuw2ph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); } +void vcvtw2ph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x7D); } +void vdbpsadbw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x42, imm); } +void vdivph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5E); } +void vdivsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5E); } +void vdpbf16ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x52); } +void vexp2pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xC8); } +void vexp2ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xC8); } +void vexpandpd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x88); } +void vexpandps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x88); } +void vextractf32x4(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x19, imm); } +void vextractf32x8(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1B, imm); } +void vextractf64x2(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x19, imm); } +void vextractf64x4(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1B, imm); } +void vextracti32x4(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x39, imm); } +void vextracti32x8(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3B, imm); } +void vextracti64x2(const Operand& op, const Ymm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::XMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x39, imm); } +void vextracti64x4(const Operand& op, const Zmm& r, uint8_t imm) { if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r, 0, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3B, imm); } +void vfcmaddcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x56); } +void vfcmulcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F2 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0xD6); } +void vfixupimmpd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x54, imm); } +void vfixupimmps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x54, imm); } +void vfixupimmsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); } +void vfixupimmss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_Z | T_MUST_EVEX, 0x55, imm); } +void vfmadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x98); } +void vfmadd132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x99); } +void vfmadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA8); } +void vfmadd213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xA9); } +void vfmadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB8); } +void vfmadd231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xB9); } +void vfmaddcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x56); } +void vfmaddsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x96); } +void vfmaddsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA6); } +void vfmaddsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB6); } +void vfmsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9A); } +void vfmsub132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9B); } +void vfmsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAA); } +void vfmsub213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAB); } +void vfmsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBA); } +void vfmsub231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBB); } +void vfmsubadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x97); } +void vfmsubadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xA7); } +void vfmsubadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xB7); } +void vfmulcph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_F3 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0xD6); } +void vfnmadd132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9C); } +void vfnmadd132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9D); } +void vfnmadd213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAC); } +void vfnmadd213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAD); } +void vfnmadd231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBC); } +void vfnmadd231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBD); } +void vfnmsub132ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x9E); } +void vfnmsub132sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x9F); } +void vfnmsub213ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xAE); } +void vfnmsub213sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xAF); } +void vfnmsub231ph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0xBE); } +void vfnmsub231sh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0xBF); } +void vfpclasspd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW1 | T_B64, 0x66, imm); } +void vfpclassph(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B16, 0x66, imm); } +void vfpclassps(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isBit(128|256|512)) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k.changeBit(op.getBit()), 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_YMM | T_EW0 | T_B32, 0x66, imm); } +void vfpclasssd(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW1 | T_N8, 0x67, imm); } +void vfpclasssh(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_0F3A | T_MUST_EVEX | T_EW0 | T_N2, 0x67, imm); } +void vfpclassss(const Opmask& k, const Operand& op, uint8_t imm) { if (!op.isXMEM()) XBYAK_THROW(ERR_BAD_MEM_SIZE) opVex(k, 0, op, T_66 | T_0F3A | T_MUST_EVEX | T_EW0 | T_N4, 0x67, imm); } +void vgatherdpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 1); } +void vgatherdps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x92, 0); } +void vgatherpf0dpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vgatherpf0dps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vgatherpf0qpd(const Address& addr) { opGatherFetch(addr, zm1, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf0qps(const Address& addr) { opGatherFetch(addr, zm1, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf1dpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vgatherpf1dps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vgatherpf1qpd(const Address& addr) { opGatherFetch(addr, zm2, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherpf1qps(const Address& addr) { opGatherFetch(addr, zm2, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vgatherqpd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 0); } +void vgatherqps(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x93, 2); } +void vgetexppd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x42); } +void vgetexpph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x42); } +void vgetexpps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x42); } +void vgetexpsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x43); } +void vgetexpsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); } +void vgetexpss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x43); } +void vgetmantpd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x26, imm); } +void vgetmantph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x26, imm); } +void vgetmantps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x26, imm); } +void vgetmantsd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x27, imm); } +void vgetmantsh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); } +void vgetmantss(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x27, imm); } +void vinsertf32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x18, imm); } +void vinsertf32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x1A, imm); } +void vinsertf64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x18, imm); } +void vinsertf64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x1A, imm); } +void vinserti32x4(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x38, imm); } +void vinserti32x8(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3A, imm); } +void vinserti64x2(const Ymm& r1, const Ymm& r2, const Operand& op, uint8_t imm) {if (!(r1.getKind() == r2.getKind() && op.is(Operand::MEM | Operand::XMM))) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N16 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x38, imm); } +void vinserti64x4(const Zmm& r1, const Zmm& r2, const Operand& op, uint8_t imm) {if (!op.is(Operand::MEM | Operand::YMM)) XBYAK_THROW(ERR_BAD_COMBINATION) opVex(r1, &r2, op, T_N32 | T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3A, imm); } +void vmaxph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5F); } +void vmaxsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5F); } +void vminph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5D); } +void vminsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5D); } +void vmovdqa32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqa32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqa64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqa64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu16(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu16(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu32(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu32(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu64(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu64(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F3 | T_0F | T_EW1 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovdqu8(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX | T_M_K, 0x7F); } +void vmovdqu8(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_F2 | T_0F | T_EW0 | T_YMM | T_ER_X | T_ER_Y | T_ER_Z | T_MUST_EVEX, 0x6F); } +void vmovsh(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX | T_M_K, 0x11); } +void vmovsh(const Xmm& x, const Address& addr) { opAVX_X_X_XM(x, xm0, addr, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX, 0x10); } +void vmovsh(const Xmm& x1, const Xmm& x2, const Xmm& x3) { opAVX_X_X_XM(x1, x2, x3, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_MUST_EVEX, 0x10); } +void vmovw(const Address& addr, const Xmm& x) { opAVX_X_XM_IMM(x, addr, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x7E); } +void vmovw(const Reg32e& r, const Xmm& x) { opAVX_X_X_XM(x, xm0, r, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x7E); } +void vmovw(const Xmm& x, const Operand& op) { if (!op.isREG(32|64) && !op.isMEM()) XBYAK_THROW(ERR_BAD_COMBINATION) opAVX_X_X_XM(x, xm0, op, T_N2 | T_66 | T_MAP5 | T_MUST_EVEX, 0x6E); } +void vmulph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x59); } +void vmulsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x59); } +void vp2intersectd(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW0 | T_B32, 0x68); } +void vp2intersectq(const Opmask& k, const Xmm& x, const Operand& op) { if (k.getOpmaskIdx() != 0) XBYAK_THROW(ERR_OPMASK_IS_ALREADY_SET) opAVX_K_X_XM(k, x, op, T_F2 | T_0F38 | T_YMM | T_EVEX | T_EW1 | T_B64, 0x68); } +void vp4dpwssd(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x52); } +void vp4dpwssds(const Zmm& z1, const Zmm& z2, const Address& addr) { opAVX_X_X_XM(z1, z2, addr, T_0F38 | T_F2 | T_EW0 | T_YMM | T_MUST_EVEX | T_N16, 0x53); } +void vpabsq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_MUST_EVEX | T_EW1 | T_B64 | T_YMM, 0x1F); } +void vpandd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDB); } +void vpandnd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xDF); } +void vpandnq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDF); } +void vpandq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xDB); } +void vpblendmb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x66); } +void vpblendmd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x64); } +void vpblendmq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x64); } +void vpblendmw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x66); } +void vpbroadcastb(const Xmm& x, const Reg8& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7A); } +void vpbroadcastd(const Xmm& x, const Reg32& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7C); } +void vpbroadcastmb2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW1, 0x2A); } +void vpbroadcastmw2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_YMM | T_MUST_EVEX | T_EW0, 0x3A); } +void vpbroadcastw(const Xmm& x, const Reg16& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7B); } +void vpcmpb(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3F, imm); } +void vpcmpd(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1F, imm); } +void vpcmpeqb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x74); } +void vpcmpeqd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX | T_B32, 0x76); } +void vpcmpeqq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x29); } +void vpcmpeqw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x75); } +void vpcmpgtb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x64); } +void vpcmpgtd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x66); } +void vpcmpgtq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x37); } +void vpcmpgtw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F | T_YMM | T_MUST_EVEX, 0x65); } +void vpcmpq(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1F, imm); } +void vpcmpub(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX, 0x3E, imm); } +void vpcmpud(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x1E, imm); } +void vpcmpuq(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x1E, imm); } +void vpcmpuw(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3E, imm); } +void vpcmpw(const Opmask& k, const Xmm& x, const Operand& op, uint8_t imm) { opAVX_K_X_XM(k, x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX, 0x3F, imm); } +void vpcompressd(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8B); } +void vpcompressq(const Operand& op, const Xmm& x) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8B); } +void vpconflictd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xC4); } +void vpconflictq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xC4); } +void vpermb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8D); } +void vpermi2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x75); } +void vpermi2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x76); } +void vpermi2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x77); } +void vpermi2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x77); } +void vpermi2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x76); } +void vpermi2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x75); } +void vpermt2b(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x7D); } +void vpermt2d(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7E); } +void vpermt2pd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7F); } +void vpermt2ps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x7F); } +void vpermt2q(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x7E); } +void vpermt2w(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7D); } +void vpermw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x8D); } +void vpexpandb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N1 | T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); } +void vpexpandd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x89); } +void vpexpandq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x89); } +void vpexpandw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_N2 | T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x62); } +void vpgatherdd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 0); } +void vpgatherdq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x90, 1); } +void vpgatherqd(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 2); } +void vpgatherqq(const Xmm& x, const Address& addr) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_VSIB, 0x91, 0); } +void vplzcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x44); } +void vplzcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x44); } +void vpmaxsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3D); } +void vpmaxuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3F); } +void vpminsq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x39); } +void vpminuq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x3B); } +void vpmovb2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x29); } +void vpmovd2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x39); } +void vpmovdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x31, false); } +void vpmovdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x33, true); } +void vpmovm2b(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x28); } +void vpmovm2d(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0, 0x38); } +void vpmovm2q(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x38); } +void vpmovm2w(const Xmm& x, const Opmask& k) { opVex(x, 0, k, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x28); } +void vpmovq2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x39); } +void vpmovqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x32, false); } +void vpmovqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x35, true); } +void vpmovqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x34, false); } +void vpmovsdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x21, false); } +void vpmovsdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x23, true); } +void vpmovsqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x22, false); } +void vpmovsqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x25, true); } +void vpmovsqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x24, false); } +void vpmovswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x20, true); } +void vpmovusdb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x11, false); } +void vpmovusdw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x13, true); } +void vpmovusqb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N2 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x12, false); } +void vpmovusqd(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x15, true); } +void vpmovusqw(const Operand& op, const Xmm& x) { opVmov(op, x, T_N4 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x14, false); } +void vpmovuswb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x10, true); } +void vpmovw2m(const Opmask& k, const Xmm& x) { opVex(k, 0, x, T_F3 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1, 0x29); } +void vpmovwb(const Operand& op, const Xmm& x) { opVmov(op, x, T_N8 | T_N_VL | T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K, 0x30, true); } +void vpmullq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x40); } +void vpmultishiftqb(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x83); } +void vpopcntb(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); } +void vpopcntd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x55); } +void vpopcntq(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x55); } +void vpopcntw(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x54); } +void vpord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEB); } +void vporq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEB); } +void vprold(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); } +void vprolq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 1), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vprolvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x15); } +void vprolvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x15); } +void vprord(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x72, imm); } +void vprorq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 0), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vprorvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x14); } +void vprorvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x14); } +void vpscatterdd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 0); } +void vpscatterdq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA0, 1); } +void vpscatterqd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 2); } +void vpscatterqq(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA1, 0); } +void vpshldd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71, imm); } +void vpshldq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71, imm); } +void vpshldvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x71); } +void vpshldvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x71); } +void vpshldvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70); } +void vpshldw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x70, imm); } +void vpshrdd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73, imm); } +void vpshrdq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73, imm); } +void vpshrdvd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x73); } +void vpshrdvq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x73); } +void vpshrdvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72); } +void vpshrdw(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX, 0x72, imm); } +void vpshufbitqmb(const Opmask& k, const Xmm& x, const Operand& op) { opVex(k, &x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x8F); } +void vpsllvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x12); } +void vpsraq(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_X_XM(Xmm(x.getKind(), 4), x, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x72, imm); } +void vpsraq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N16 | T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX, 0xE2); } +void vpsravq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x46); } +void vpsravw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x11); } +void vpsrlvw(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x10); } +void vpternlogd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x25, imm); } +void vpternlogq(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x25, imm); } +void vptestmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); } +void vptestmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); } +void vptestmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestnmb(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x26); } +void vptestnmd(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x27); } +void vptestnmq(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x27); } +void vptestnmw(const Opmask& k, const Xmm& x, const Operand& op) { opAVX_K_X_XM(k, x, op, T_F3 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x26); } +void vpxord(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0xEF); } +void vpxorq(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0xEF); } +void vrangepd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x50, imm); } +void vrangeps(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x50, imm); } +void vrangesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x51, imm); } +void vrangess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x51, imm); } +void vrcp14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4C); } +void vrcp14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4C); } +void vrcp14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX, 0x4D); } +void vrcp14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX, 0x4D); } +void vrcp28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCA); } +void vrcp28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCA); } +void vrcp28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCB); } +void vrcp28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCB); } +void vrcpph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_MUST_EVEX | T_B16, 0x4C); } +void vrcpsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_MUST_EVEX, 0x4D); } +void vreducepd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x56, imm); } +void vreduceph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x56, imm); } +void vreduceps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x56, imm); } +void vreducesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x57, imm); } +void vreducesh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); } +void vreducess(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x57, imm); } +void vrndscalepd(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW1 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B64, 0x09, imm); } +void vrndscaleph(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B16, 0x08, imm); } +void vrndscaleps(const Xmm& x, const Operand& op, uint8_t imm) { opAVX_X_XM_IMM(x, op, T_66 | T_0F3A | T_EW0 | T_YMM | T_SAE_Z | T_MUST_EVEX | T_B32, 0x08, imm); } +void vrndscalesd(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F3A | T_EW1 | T_SAE_X | T_MUST_EVEX, 0x0B, imm); } +void vrndscalesh(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x0A, imm); } +void vrndscaless(const Xmm& x1, const Xmm& x2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F3A | T_EW0 | T_SAE_X | T_MUST_EVEX, 0x0A, imm); } +void vrsqrt14pd(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_B64, 0x4E); } +void vrsqrt14ps(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_B32, 0x4E); } +void vrsqrt14sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x4F); } +void vrsqrt14ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX, 0x4F); } +void vrsqrt28pd(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW1 | T_B64 | T_SAE_Z, 0xCC); } +void vrsqrt28ps(const Zmm& z, const Operand& op) { opAVX_X_XM_IMM(z, op, T_66 | T_0F38 | T_MUST_EVEX | T_YMM | T_EW0 | T_B32 | T_SAE_Z, 0xCC); } +void vrsqrt28sd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_SAE_X | T_MUST_EVEX, 0xCD); } +void vrsqrt28ss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_SAE_X | T_MUST_EVEX, 0xCD); } +void vrsqrtph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_MUST_EVEX | T_B16, 0x4E); } +void vrsqrtsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_MUST_EVEX, 0x4F); } +void vscalefpd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW1 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B64, 0x2C); } +void vscalefph(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_MAP6 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x2C); } +void vscalefps(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_66 | T_0F38 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B32, 0x2C); } +void vscalefsd(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N8 | T_66 | T_0F38 | T_EW1 | T_ER_X | T_MUST_EVEX, 0x2D); } +void vscalefsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_66 | T_MAP6 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); } +void vscalefss(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N4 | T_66 | T_0F38 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x2D); } +void vscatterdpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 1); } +void vscatterdps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA2, 0); } +void vscatterpf0dpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vscatterpf0dps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vscatterpf0qpd(const Address& addr) { opGatherFetch(addr, zm5, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf0qps(const Address& addr) { opGatherFetch(addr, zm5, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf1dpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::YMM); } +void vscatterpf1dps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC6, Operand::ZMM); } +void vscatterpf1qpd(const Address& addr) { opGatherFetch(addr, zm6, T_N8 | T_66 | T_0F38 | T_EW1 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterpf1qps(const Address& addr) { opGatherFetch(addr, zm6, T_N4 | T_66 | T_0F38 | T_EW0 | T_MUST_EVEX | T_M_K | T_VSIB, 0xC7, Operand::ZMM); } +void vscatterqpd(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N8 | T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 0); } +void vscatterqps(const Address& addr, const Xmm& x) { opGather2(x, addr, T_N4 | T_66 | T_0F38 | T_EW0 | T_YMM | T_MUST_EVEX | T_M_K | T_VSIB, 0xA3, 2); } +void vshuff32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x23, imm); } +void vshuff64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x23, imm); } +void vshufi32x4(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW0 | T_B32, 0x43, imm); } +void vshufi64x2(const Ymm& y1, const Ymm& y2, const Operand& op, uint8_t imm) { opAVX_X_X_XM(y1, y2, op, T_66 | T_0F3A | T_YMM | T_MUST_EVEX | T_EW1 | T_B64, 0x43, imm); } +void vsqrtph(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_EW0 | T_YMM | T_ER_Z | T_MUST_EVEX | T_B16, 0x51); } +void vsqrtsh(const Xmm& x1, const Xmm& x2, const Operand& op) { opAVX_X_X_XM(x1, x2, op, T_N2 | T_F3 | T_MAP5 | T_EW0 | T_ER_X | T_MUST_EVEX, 0x51); } +void vsubph(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_EW0 | T_YMM | T_MUST_EVEX | T_ER_Z | T_B16, 0x5C); } +void vsubsh(const Xmm& xmm, const Operand& op1, const Operand& op2 = Operand()) { opAVX_X_X_XM(xmm, op1, op2, T_MAP5 | T_F3 | T_EW0 | T_MUST_EVEX | T_ER_X | T_N2, 0x5C); } +void vucomish(const Xmm& x, const Operand& op) { opAVX_X_XM_IMM(x, op, T_MAP5 | T_MUST_EVEX | T_EW0 | T_SAE_X | T_N2, 0x2E); } +#ifdef XBYAK64 +void kmovq(const Opmask& k, const Reg64& r) { opVex(k, 0, r, T_L0 | T_0F | T_F2 | T_W1, 0x92); } +void kmovq(const Reg64& r, const Opmask& k) { opVex(r, 0, k, T_L0 | T_0F | T_F2 | T_W1, 0x93); } +void vpbroadcastq(const Xmm& x, const Reg64& r) { opVex(x, 0, r, T_66 | T_0F38 | T_EW1 | T_YMM | T_MUST_EVEX, 0x7C); } +#endif +#endif diff --git a/xbyak/xbyak_util.h b/xbyak/xbyak_util.h new file mode 100644 index 0000000..ebf15e6 --- /dev/null +++ b/xbyak/xbyak_util.h @@ -0,0 +1,998 @@ +#ifndef XBYAK_XBYAK_UTIL_H_ +#define XBYAK_XBYAK_UTIL_H_ + +#ifdef XBYAK_ONLY_CLASS_CPU +#include <stdint.h> +#include <stdlib.h> +#include <assert.h> +#ifndef XBYAK_THROW + #define XBYAK_THROW(x) ; + #define XBYAK_THROW_RET(x, y) return y; +#endif +#else +#include <string.h> + +/** + utility class and functions for Xbyak + Xbyak::util::Clock ; rdtsc timer + Xbyak::util::Cpu ; detect CPU +*/ +#include "xbyak.h" +#endif // XBYAK_ONLY_CLASS_CPU + +#if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64) + #define XBYAK_INTEL_CPU_SPECIFIC +#endif + +#ifdef XBYAK_INTEL_CPU_SPECIFIC +#ifdef _WIN32 + #if defined(_MSC_VER) && (_MSC_VER < 1400) && defined(XBYAK32) + static inline __declspec(naked) void __cpuid(int[4], int) + { + __asm { + push ebx + push esi + mov eax, dword ptr [esp + 4 * 2 + 8] // eaxIn + cpuid + mov esi, dword ptr [esp + 4 * 2 + 4] // data + mov dword ptr [esi], eax + mov dword ptr [esi + 4], ebx + mov dword ptr [esi + 8], ecx + mov dword ptr [esi + 12], edx + pop esi + pop ebx + ret + } + } + #else + #include <intrin.h> // for __cpuid + #endif +#else + #ifndef __GNUC_PREREQ + #define __GNUC_PREREQ(major, minor) ((((__GNUC__) << 16) + (__GNUC_MINOR__)) >= (((major) << 16) + (minor))) + #endif + #if __GNUC_PREREQ(4, 3) && !defined(__APPLE__) + #include <cpuid.h> + #else + #if defined(__APPLE__) && defined(XBYAK32) // avoid err : can't find a register in class `BREG' while reloading `asm' + #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn)) + #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("pushl %%ebx\ncpuid\nmovl %%ebp, %%esi\npopl %%ebx" : "=a"(a), "=S"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn)) + #else + #define __cpuid(eaxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn)) + #define __cpuid_count(eaxIn, ecxIn, a, b, c, d) __asm__ __volatile__("cpuid\n" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "0"(eaxIn), "2"(ecxIn)) + #endif + #endif +#endif +#endif + +#ifdef XBYAK_USE_VTUNE + // -I /opt/intel/vtune_amplifier/include/ -L /opt/intel/vtune_amplifier/lib64 -ljitprofiling -ldl + #include <jitprofiling.h> + #ifdef _MSC_VER + #pragma comment(lib, "libittnotify.lib") + #endif + #ifdef __linux__ + #include <dlfcn.h> + #endif +#endif +#ifdef __linux__ + #define XBYAK_USE_PERF +#endif + +namespace Xbyak { namespace util { + +typedef enum { + SmtLevel = 1, + CoreLevel = 2 +} IntelCpuTopologyLevel; + +namespace local { + +template<uint64_t L, uint64_t H = 0> +struct TypeT { +}; + +template<uint64_t L1, uint64_t H1, uint64_t L2, uint64_t H2> +TypeT<L1 | L2, H1 | H2> operator|(TypeT<L1, H1>, TypeT<L2, H2>) { return TypeT<L1 | L2, H1 | H2>(); } + +template<typename T> +inline T max_(T x, T y) { return x >= y ? x : y; } +template<typename T> +inline T min_(T x, T y) { return x < y ? x : y; } + +} // local + +/** + CPU detection class + @note static inline const member is supported by c++17 or later, so use template hack +*/ +class Cpu { +public: + class Type { + uint64_t L; + uint64_t H; + public: + Type(uint64_t L = 0, uint64_t H = 0) : L(L), H(H) { } + template<uint64_t L_, uint64_t H_> + Type(local::TypeT<L_, H_>) : L(L_), H(H_) {} + Type& operator&=(const Type& rhs) { L &= rhs.L; H &= rhs.H; return *this; } + Type& operator|=(const Type& rhs) { L |= rhs.L; H |= rhs.H; return *this; } + Type operator&(const Type& rhs) const { Type t = *this; t &= rhs; return t; } + Type operator|(const Type& rhs) const { Type t = *this; t |= rhs; return t; } + bool operator==(const Type& rhs) const { return H == rhs.H && L == rhs.L; } + bool operator!=(const Type& rhs) const { return !operator==(rhs); } + // without explicit because backward compatilibity + operator bool() const { return (H | L) != 0; } + uint64_t getL() const { return L; } + uint64_t getH() const { return H; } + }; +private: + Type type_; + //system topology + bool x2APIC_supported_; + static const size_t maxTopologyLevels = 2; + uint32_t numCores_[maxTopologyLevels]; + + static const uint32_t maxNumberCacheLevels = 10; + uint32_t dataCacheSize_[maxNumberCacheLevels]; + uint32_t coresSharignDataCache_[maxNumberCacheLevels]; + uint32_t dataCacheLevels_; + + uint32_t get32bitAsBE(const char *x) const + { + return x[0] | (x[1] << 8) | (x[2] << 16) | (x[3] << 24); + } + uint32_t mask(int n) const + { + return (1U << n) - 1; + } + void setFamily() + { + uint32_t data[4] = {}; + getCpuid(1, data); + stepping = data[0] & mask(4); + model = (data[0] >> 4) & mask(4); + family = (data[0] >> 8) & mask(4); + // type = (data[0] >> 12) & mask(2); + extModel = (data[0] >> 16) & mask(4); + extFamily = (data[0] >> 20) & mask(8); + if (family == 0x0f) { + displayFamily = family + extFamily; + } else { + displayFamily = family; + } + if (family == 6 || family == 0x0f) { + displayModel = (extModel << 4) + model; + } else { + displayModel = model; + } + } + uint32_t extractBit(uint32_t val, uint32_t base, uint32_t end) + { + return (val >> base) & ((1u << (end - base)) - 1); + } + void setNumCores() + { + if (!has(tINTEL)) return; + + uint32_t data[4] = {}; + + /* CAUTION: These numbers are configuration as shipped by Intel. */ + getCpuidEx(0x0, 0, data); + if (data[0] >= 0xB) { + /* + if leaf 11 exists(x2APIC is supported), + we use it to get the number of smt cores and cores on socket + + leaf 0xB can be zeroed-out by a hypervisor + */ + x2APIC_supported_ = true; + for (uint32_t i = 0; i < maxTopologyLevels; i++) { + getCpuidEx(0xB, i, data); + IntelCpuTopologyLevel level = (IntelCpuTopologyLevel)extractBit(data[2], 8, 15); + if (level == SmtLevel || level == CoreLevel) { + numCores_[level - 1] = extractBit(data[1], 0, 15); + } + } + /* + Fallback values in case a hypervisor has 0xB leaf zeroed-out. + */ + numCores_[SmtLevel - 1] = local::max_(1u, numCores_[SmtLevel - 1]); + numCores_[CoreLevel - 1] = local::max_(numCores_[SmtLevel - 1], numCores_[CoreLevel - 1]); + } else { + /* + Failed to deremine num of cores without x2APIC support. + TODO: USE initial APIC ID to determine ncores. + */ + numCores_[SmtLevel - 1] = 0; + numCores_[CoreLevel - 1] = 0; + } + + } + void setCacheHierarchy() + { + if (!has(tINTEL)) return; + const uint32_t NO_CACHE = 0; + const uint32_t DATA_CACHE = 1; +// const uint32_t INSTRUCTION_CACHE = 2; + const uint32_t UNIFIED_CACHE = 3; + uint32_t smt_width = 0; + uint32_t logical_cores = 0; + uint32_t data[4] = {}; + + if (x2APIC_supported_) { + smt_width = numCores_[0]; + logical_cores = numCores_[1]; + } + + /* + Assumptions: + the first level of data cache is not shared (which is the + case for every existing architecture) and use this to + determine the SMT width for arch not supporting leaf 11. + when leaf 4 reports a number of core less than numCores_ + on socket reported by leaf 11, then it is a correct number + of cores not an upperbound. + */ + for (int i = 0; dataCacheLevels_ < maxNumberCacheLevels; i++) { + getCpuidEx(0x4, i, data); + uint32_t cacheType = extractBit(data[0], 0, 4); + if (cacheType == NO_CACHE) break; + if (cacheType == DATA_CACHE || cacheType == UNIFIED_CACHE) { + uint32_t actual_logical_cores = extractBit(data[0], 14, 25) + 1; + if (logical_cores != 0) { // true only if leaf 0xB is supported and valid + actual_logical_cores = local::min_(actual_logical_cores, logical_cores); + } + assert(actual_logical_cores != 0); + dataCacheSize_[dataCacheLevels_] = + (extractBit(data[1], 22, 31) + 1) + * (extractBit(data[1], 12, 21) + 1) + * (extractBit(data[1], 0, 11) + 1) + * (data[2] + 1); + if (cacheType == DATA_CACHE && smt_width == 0) smt_width = actual_logical_cores; + assert(smt_width != 0); + coresSharignDataCache_[dataCacheLevels_] = local::max_(actual_logical_cores / smt_width, 1u); + dataCacheLevels_++; + } + } + } + +public: + int model; + int family; + int stepping; + int extModel; + int extFamily; + int displayFamily; // family + extFamily + int displayModel; // model + extModel + + uint32_t getNumCores(IntelCpuTopologyLevel level) const { + if (!x2APIC_supported_) XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0) + switch (level) { + case SmtLevel: return numCores_[level - 1]; + case CoreLevel: return numCores_[level - 1] / numCores_[SmtLevel - 1]; + default: XBYAK_THROW_RET(ERR_X2APIC_IS_NOT_SUPPORTED, 0) + } + } + + uint32_t getDataCacheLevels() const { return dataCacheLevels_; } + uint32_t getCoresSharingDataCache(uint32_t i) const + { + if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0) + return coresSharignDataCache_[i]; + } + uint32_t getDataCacheSize(uint32_t i) const + { + if (i >= dataCacheLevels_) XBYAK_THROW_RET(ERR_BAD_PARAMETER, 0) + return dataCacheSize_[i]; + } + + /* + data[] = { eax, ebx, ecx, edx } + */ + static inline void getCpuid(uint32_t eaxIn, uint32_t data[4]) + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _WIN32 + __cpuid(reinterpret_cast<int*>(data), eaxIn); + #else + __cpuid(eaxIn, data[0], data[1], data[2], data[3]); + #endif +#else + (void)eaxIn; + (void)data; +#endif + } + static inline void getCpuidEx(uint32_t eaxIn, uint32_t ecxIn, uint32_t data[4]) + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _WIN32 + __cpuidex(reinterpret_cast<int*>(data), eaxIn, ecxIn); + #else + __cpuid_count(eaxIn, ecxIn, data[0], data[1], data[2], data[3]); + #endif +#else + (void)eaxIn; + (void)ecxIn; + (void)data; +#endif + } + static inline uint64_t getXfeature() + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + return _xgetbv(0); + #else + uint32_t eax, edx; + // xgetvb is not support on gcc 4.2 +// __asm__ volatile("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0)); + __asm__ volatile(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0)); + return ((uint64_t)edx << 32) | eax; + #endif +#else + return 0; +#endif + } + +#define XBYAK_SPLIT_ID(id) ((0 <= id && id < 64) ? (1ull << (id % 64)) : 0), (id >= 64 ? (1ull << (id % 64)) : 0) +#if (__cplusplus >= 201103) || (defined(_MSC_VER) && (_MSC_VER >= 1700)) /* VS2012 */ + #define XBYAK_DEFINE_TYPE(id, NAME) static const constexpr local::TypeT<XBYAK_SPLIT_ID(id)> NAME{} +#else + #define XBYAK_DEFINE_TYPE(id, NAME) static const local::TypeT<XBYAK_SPLIT_ID(id)> NAME +#endif + XBYAK_DEFINE_TYPE(0, tMMX); + XBYAK_DEFINE_TYPE(1, tMMX2); + XBYAK_DEFINE_TYPE(2, tCMOV); + XBYAK_DEFINE_TYPE(3, tSSE); + XBYAK_DEFINE_TYPE(4, tSSE2); + XBYAK_DEFINE_TYPE(5, tSSE3); + XBYAK_DEFINE_TYPE(6, tSSSE3); + XBYAK_DEFINE_TYPE(7, tSSE41); + XBYAK_DEFINE_TYPE(8, tSSE42); + XBYAK_DEFINE_TYPE(9, tPOPCNT); + XBYAK_DEFINE_TYPE(10, tAESNI); + XBYAK_DEFINE_TYPE(11, tAVX512_FP16); + XBYAK_DEFINE_TYPE(12, tOSXSAVE); + XBYAK_DEFINE_TYPE(13, tPCLMULQDQ); + XBYAK_DEFINE_TYPE(14, tAVX); + XBYAK_DEFINE_TYPE(15, tFMA); + XBYAK_DEFINE_TYPE(16, t3DN); + XBYAK_DEFINE_TYPE(17, tE3DN); + XBYAK_DEFINE_TYPE(18, tWAITPKG); + XBYAK_DEFINE_TYPE(19, tRDTSCP); + XBYAK_DEFINE_TYPE(20, tAVX2); + XBYAK_DEFINE_TYPE(21, tBMI1); // andn, bextr, blsi, blsmsk, blsr, tzcnt + XBYAK_DEFINE_TYPE(22, tBMI2); // bzhi, mulx, pdep, pext, rorx, sarx, shlx, shrx + XBYAK_DEFINE_TYPE(23, tLZCNT); + XBYAK_DEFINE_TYPE(24, tINTEL); + XBYAK_DEFINE_TYPE(25, tAMD); + XBYAK_DEFINE_TYPE(26, tENHANCED_REP); // enhanced rep movsb/stosb + XBYAK_DEFINE_TYPE(27, tRDRAND); + XBYAK_DEFINE_TYPE(28, tADX); // adcx, adox + XBYAK_DEFINE_TYPE(29, tRDSEED); // rdseed + XBYAK_DEFINE_TYPE(30, tSMAP); // stac + XBYAK_DEFINE_TYPE(31, tHLE); // xacquire, xrelease, xtest + XBYAK_DEFINE_TYPE(32, tRTM); // xbegin, xend, xabort + XBYAK_DEFINE_TYPE(33, tF16C); // vcvtph2ps, vcvtps2ph + XBYAK_DEFINE_TYPE(34, tMOVBE); // mobve + XBYAK_DEFINE_TYPE(35, tAVX512F); + XBYAK_DEFINE_TYPE(36, tAVX512DQ); + XBYAK_DEFINE_TYPE(37, tAVX512_IFMA); + XBYAK_DEFINE_TYPE(37, tAVX512IFMA);// = tAVX512_IFMA; + XBYAK_DEFINE_TYPE(38, tAVX512PF); + XBYAK_DEFINE_TYPE(39, tAVX512ER); + XBYAK_DEFINE_TYPE(40, tAVX512CD); + XBYAK_DEFINE_TYPE(41, tAVX512BW); + XBYAK_DEFINE_TYPE(42, tAVX512VL); + XBYAK_DEFINE_TYPE(43, tAVX512_VBMI); + XBYAK_DEFINE_TYPE(43, tAVX512VBMI); // = tAVX512_VBMI; // changed by Intel's manual + XBYAK_DEFINE_TYPE(44, tAVX512_4VNNIW); + XBYAK_DEFINE_TYPE(45, tAVX512_4FMAPS); + XBYAK_DEFINE_TYPE(46, tPREFETCHWT1); + XBYAK_DEFINE_TYPE(47, tPREFETCHW); + XBYAK_DEFINE_TYPE(48, tSHA); + XBYAK_DEFINE_TYPE(49, tMPX); + XBYAK_DEFINE_TYPE(50, tAVX512_VBMI2); + XBYAK_DEFINE_TYPE(51, tGFNI); + XBYAK_DEFINE_TYPE(52, tVAES); + XBYAK_DEFINE_TYPE(53, tVPCLMULQDQ); + XBYAK_DEFINE_TYPE(54, tAVX512_VNNI); + XBYAK_DEFINE_TYPE(55, tAVX512_BITALG); + XBYAK_DEFINE_TYPE(56, tAVX512_VPOPCNTDQ); + XBYAK_DEFINE_TYPE(57, tAVX512_BF16); + XBYAK_DEFINE_TYPE(58, tAVX512_VP2INTERSECT); + XBYAK_DEFINE_TYPE(59, tAMX_TILE); + XBYAK_DEFINE_TYPE(60, tAMX_INT8); + XBYAK_DEFINE_TYPE(61, tAMX_BF16); + XBYAK_DEFINE_TYPE(62, tAVX_VNNI); + XBYAK_DEFINE_TYPE(63, tCLFLUSHOPT); + XBYAK_DEFINE_TYPE(64, tCLDEMOTE); + XBYAK_DEFINE_TYPE(65, tMOVDIRI); + XBYAK_DEFINE_TYPE(66, tMOVDIR64B); + XBYAK_DEFINE_TYPE(67, tCLZERO); // AMD Zen + XBYAK_DEFINE_TYPE(68, tAMX_FP16); + XBYAK_DEFINE_TYPE(69, tAVX_VNNI_INT8); + XBYAK_DEFINE_TYPE(70, tAVX_NE_CONVERT); + XBYAK_DEFINE_TYPE(71, tAVX_IFMA); + XBYAK_DEFINE_TYPE(72, tRAO_INT); + XBYAK_DEFINE_TYPE(73, tCMPCCXADD); + +#undef XBYAK_SPLIT_ID +#undef XBYAK_DEFINE_TYPE + + Cpu() + : type_() + , x2APIC_supported_(false) + , numCores_() + , dataCacheSize_() + , coresSharignDataCache_() + , dataCacheLevels_(0) + { + uint32_t data[4] = {}; + const uint32_t& EAX = data[0]; + const uint32_t& EBX = data[1]; + const uint32_t& ECX = data[2]; + const uint32_t& EDX = data[3]; + getCpuid(0, data); + const uint32_t maxNum = EAX; + static const char intel[] = "ntel"; + static const char amd[] = "cAMD"; + if (ECX == get32bitAsBE(amd)) { + type_ |= tAMD; + getCpuid(0x80000001, data); + if (EDX & (1U << 31)) { + type_ |= t3DN; + // 3DNow! implies support for PREFETCHW on AMD + type_ |= tPREFETCHW; + } + + if (EDX & (1U << 29)) { + // Long mode implies support for PREFETCHW on AMD + type_ |= tPREFETCHW; + } + } + if (ECX == get32bitAsBE(intel)) { + type_ |= tINTEL; + } + + // Extended flags information + getCpuid(0x80000000, data); + const uint32_t maxExtendedNum = EAX; + if (maxExtendedNum >= 0x80000001) { + getCpuid(0x80000001, data); + + if (EDX & (1U << 31)) type_ |= t3DN; + if (EDX & (1U << 30)) type_ |= tE3DN; + if (EDX & (1U << 27)) type_ |= tRDTSCP; + if (EDX & (1U << 22)) type_ |= tMMX2; + if (EDX & (1U << 15)) type_ |= tCMOV; + if (ECX & (1U << 5)) type_ |= tLZCNT; + if (ECX & (1U << 8)) type_ |= tPREFETCHW; + } + + if (maxExtendedNum >= 0x80000008) { + getCpuid(0x80000008, data); + if (EBX & (1U << 0)) type_ |= tCLZERO; + } + + getCpuid(1, data); + if (ECX & (1U << 0)) type_ |= tSSE3; + if (ECX & (1U << 9)) type_ |= tSSSE3; + if (ECX & (1U << 19)) type_ |= tSSE41; + if (ECX & (1U << 20)) type_ |= tSSE42; + if (ECX & (1U << 22)) type_ |= tMOVBE; + if (ECX & (1U << 23)) type_ |= tPOPCNT; + if (ECX & (1U << 25)) type_ |= tAESNI; + if (ECX & (1U << 1)) type_ |= tPCLMULQDQ; + if (ECX & (1U << 27)) type_ |= tOSXSAVE; + if (ECX & (1U << 30)) type_ |= tRDRAND; + if (ECX & (1U << 29)) type_ |= tF16C; + + if (EDX & (1U << 15)) type_ |= tCMOV; + if (EDX & (1U << 23)) type_ |= tMMX; + if (EDX & (1U << 25)) type_ |= tMMX2 | tSSE; + if (EDX & (1U << 26)) type_ |= tSSE2; + + if (type_ & tOSXSAVE) { + // check XFEATURE_ENABLED_MASK[2:1] = '11b' + uint64_t bv = getXfeature(); + if ((bv & 6) == 6) { + if (ECX & (1U << 28)) type_ |= tAVX; + if (ECX & (1U << 12)) type_ |= tFMA; + // do *not* check AVX-512 state on macOS because it has on-demand AVX-512 support +#if !defined(__APPLE__) + if (((bv >> 5) & 7) == 7) +#endif + { + getCpuidEx(7, 0, data); + if (EBX & (1U << 16)) type_ |= tAVX512F; + if (type_ & tAVX512F) { + if (EBX & (1U << 17)) type_ |= tAVX512DQ; + if (EBX & (1U << 21)) type_ |= tAVX512_IFMA; + if (EBX & (1U << 26)) type_ |= tAVX512PF; + if (EBX & (1U << 27)) type_ |= tAVX512ER; + if (EBX & (1U << 28)) type_ |= tAVX512CD; + if (EBX & (1U << 30)) type_ |= tAVX512BW; + if (EBX & (1U << 31)) type_ |= tAVX512VL; + if (ECX & (1U << 1)) type_ |= tAVX512_VBMI; + if (ECX & (1U << 6)) type_ |= tAVX512_VBMI2; + if (ECX & (1U << 11)) type_ |= tAVX512_VNNI; + if (ECX & (1U << 12)) type_ |= tAVX512_BITALG; + if (ECX & (1U << 14)) type_ |= tAVX512_VPOPCNTDQ; + if (EDX & (1U << 2)) type_ |= tAVX512_4VNNIW; + if (EDX & (1U << 3)) type_ |= tAVX512_4FMAPS; + if (EDX & (1U << 8)) type_ |= tAVX512_VP2INTERSECT; + if ((type_ & tAVX512BW) && (EDX & (1U << 23))) type_ |= tAVX512_FP16; + } + } + } + } + if (maxNum >= 7) { + getCpuidEx(7, 0, data); + const uint32_t maxNumSubLeaves = EAX; + if (type_ & tAVX && (EBX & (1U << 5))) type_ |= tAVX2; + if (EBX & (1U << 3)) type_ |= tBMI1; + if (EBX & (1U << 8)) type_ |= tBMI2; + if (EBX & (1U << 9)) type_ |= tENHANCED_REP; + if (EBX & (1U << 18)) type_ |= tRDSEED; + if (EBX & (1U << 19)) type_ |= tADX; + if (EBX & (1U << 20)) type_ |= tSMAP; + if (EBX & (1U << 23)) type_ |= tCLFLUSHOPT; + if (EBX & (1U << 4)) type_ |= tHLE; + if (EBX & (1U << 11)) type_ |= tRTM; + if (EBX & (1U << 14)) type_ |= tMPX; + if (EBX & (1U << 29)) type_ |= tSHA; + if (ECX & (1U << 0)) type_ |= tPREFETCHWT1; + if (ECX & (1U << 5)) type_ |= tWAITPKG; + if (ECX & (1U << 8)) type_ |= tGFNI; + if (ECX & (1U << 9)) type_ |= tVAES; + if (ECX & (1U << 10)) type_ |= tVPCLMULQDQ; + if (ECX & (1U << 25)) type_ |= tCLDEMOTE; + if (ECX & (1U << 27)) type_ |= tMOVDIRI; + if (ECX & (1U << 28)) type_ |= tMOVDIR64B; + if (EDX & (1U << 24)) type_ |= tAMX_TILE; + if (EDX & (1U << 25)) type_ |= tAMX_INT8; + if (EDX & (1U << 22)) type_ |= tAMX_BF16; + if (maxNumSubLeaves >= 1) { + getCpuidEx(7, 1, data); + if (EAX & (1U << 3)) type_ |= tRAO_INT; + if (EAX & (1U << 4)) type_ |= tAVX_VNNI; + if (type_ & tAVX512F) { + if (EAX & (1U << 5)) type_ |= tAVX512_BF16; + } + if (EAX & (1U << 7)) type_ |= tCMPCCXADD; + if (EAX & (1U << 21)) type_ |= tAMX_FP16; + if (EAX & (1U << 23)) type_ |= tAVX_IFMA; + if (EDX & (1U << 4)) type_ |= tAVX_VNNI_INT8; + if (EDX & (1U << 5)) type_ |= tAVX_NE_CONVERT; + } + } + setFamily(); + setNumCores(); + setCacheHierarchy(); + } + void putFamily() const + { +#ifndef XBYAK_ONLY_CLASS_CPU + printf("family=%d, model=%X, stepping=%d, extFamily=%d, extModel=%X\n", + family, model, stepping, extFamily, extModel); + printf("display:family=%X, model=%X\n", displayFamily, displayModel); +#endif + } + bool has(const Type& type) const + { + return (type & type_) == type; + } +}; + +#ifndef XBYAK_ONLY_CLASS_CPU +class Clock { +public: + static inline uint64_t getRdtsc() + { +#ifdef XBYAK_INTEL_CPU_SPECIFIC + #ifdef _MSC_VER + return __rdtsc(); + #else + uint32_t eax, edx; + __asm__ volatile("rdtsc" : "=a"(eax), "=d"(edx)); + return ((uint64_t)edx << 32) | eax; + #endif +#else + // TODO: Need another impl of Clock or rdtsc-equivalent for non-x86 cpu + return 0; +#endif + } + Clock() + : clock_(0) + , count_(0) + { + } + void begin() + { + clock_ -= getRdtsc(); + } + void end() + { + clock_ += getRdtsc(); + count_++; + } + int getCount() const { return count_; } + uint64_t getClock() const { return clock_; } + void clear() { count_ = 0; clock_ = 0; } +private: + uint64_t clock_; + int count_; +}; + +#ifdef XBYAK64 +const int UseRCX = 1 << 6; +const int UseRDX = 1 << 7; + +class Pack { + static const size_t maxTblNum = 15; + Xbyak::Reg64 tbl_[maxTblNum]; + size_t n_; +public: + Pack() : tbl_(), n_(0) {} + Pack(const Xbyak::Reg64 *tbl, size_t n) { init(tbl, n); } + Pack(const Pack& rhs) + : n_(rhs.n_) + { + for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i]; + } + Pack& operator=(const Pack& rhs) + { + n_ = rhs.n_; + for (size_t i = 0; i < n_; i++) tbl_[i] = rhs.tbl_[i]; + return *this; + } + Pack(const Xbyak::Reg64& t0) + { n_ = 1; tbl_[0] = t0; } + Pack(const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 2; tbl_[0] = t0; tbl_[1] = t1; } + Pack(const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 3; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; } + Pack(const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 4; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; } + Pack(const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 5; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; } + Pack(const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 6; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; } + Pack(const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 7; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; } + Pack(const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 8; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; } + Pack(const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 9; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; } + Pack(const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 10; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; } + Pack(const Xbyak::Reg64& ta, const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 11; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; tbl_[10] = ta; } + Pack(const Xbyak::Reg64& tb, const Xbyak::Reg64& ta, const Xbyak::Reg64& t9, const Xbyak::Reg64& t8, const Xbyak::Reg64& t7, const Xbyak::Reg64& t6, const Xbyak::Reg64& t5, const Xbyak::Reg64& t4, const Xbyak::Reg64& t3, const Xbyak::Reg64& t2, const Xbyak::Reg64& t1, const Xbyak::Reg64& t0) + { n_ = 12; tbl_[0] = t0; tbl_[1] = t1; tbl_[2] = t2; tbl_[3] = t3; tbl_[4] = t4; tbl_[5] = t5; tbl_[6] = t6; tbl_[7] = t7; tbl_[8] = t8; tbl_[9] = t9; tbl_[10] = ta; tbl_[11] = tb; } + Pack& append(const Xbyak::Reg64& t) + { + if (n_ == maxTblNum) { + fprintf(stderr, "ERR Pack::can't append\n"); + XBYAK_THROW_RET(ERR_BAD_PARAMETER, *this) + } + tbl_[n_++] = t; + return *this; + } + void init(const Xbyak::Reg64 *tbl, size_t n) + { + if (n > maxTblNum) { + fprintf(stderr, "ERR Pack::init bad n=%d\n", (int)n); + XBYAK_THROW(ERR_BAD_PARAMETER) + } + n_ = n; + for (size_t i = 0; i < n; i++) { + tbl_[i] = tbl[i]; + } + } + const Xbyak::Reg64& operator[](size_t n) const + { + if (n >= n_) { + fprintf(stderr, "ERR Pack bad n=%d(%d)\n", (int)n, (int)n_); + XBYAK_THROW_RET(ERR_BAD_PARAMETER, rax) + } + return tbl_[n]; + } + size_t size() const { return n_; } + /* + get tbl[pos, pos + num) + */ + Pack sub(size_t pos, size_t num = size_t(-1)) const + { + if (num == size_t(-1)) num = n_ - pos; + if (pos + num > n_) { + fprintf(stderr, "ERR Pack::sub bad pos=%d, num=%d\n", (int)pos, (int)num); + XBYAK_THROW_RET(ERR_BAD_PARAMETER, Pack()) + } + Pack pack; + pack.n_ = num; + for (size_t i = 0; i < num; i++) { + pack.tbl_[i] = tbl_[pos + i]; + } + return pack; + } + void put() const + { + for (size_t i = 0; i < n_; i++) { + printf("%s ", tbl_[i].toString()); + } + printf("\n"); + } +}; + +class StackFrame { +#ifdef XBYAK64_WIN + static const int noSaveNum = 6; + static const int rcxPos = 0; + static const int rdxPos = 1; +#else + static const int noSaveNum = 8; + static const int rcxPos = 3; + static const int rdxPos = 2; +#endif + static const int maxRegNum = 14; // maxRegNum = 16 - rsp - rax + Xbyak::CodeGenerator *code_; + int pNum_; + int tNum_; + bool useRcx_; + bool useRdx_; + int saveNum_; + int P_; + bool makeEpilog_; + Xbyak::Reg64 pTbl_[4]; + Xbyak::Reg64 tTbl_[maxRegNum]; + Pack p_; + Pack t_; + StackFrame(const StackFrame&); + void operator=(const StackFrame&); +public: + const Pack& p; + const Pack& t; + /* + make stack frame + @param sf [in] this + @param pNum [in] num of function parameter(0 <= pNum <= 4) + @param tNum [in] num of temporary register(0 <= tNum, with UseRCX, UseRDX) #{pNum + tNum [+rcx] + [rdx]} <= 14 + @param stackSizeByte [in] local stack size + @param makeEpilog [in] automatically call close() if true + + you can use + rax + gp0, ..., gp(pNum - 1) + gt0, ..., gt(tNum-1) + rcx if tNum & UseRCX + rdx if tNum & UseRDX + rsp[0..stackSizeByte - 1] + */ + StackFrame(Xbyak::CodeGenerator *code, int pNum, int tNum = 0, int stackSizeByte = 0, bool makeEpilog = true) + : code_(code) + , pNum_(pNum) + , tNum_(tNum & ~(UseRCX | UseRDX)) + , useRcx_((tNum & UseRCX) != 0) + , useRdx_((tNum & UseRDX) != 0) + , saveNum_(0) + , P_(0) + , makeEpilog_(makeEpilog) + , p(p_) + , t(t_) + { + using namespace Xbyak; + if (pNum < 0 || pNum > 4) XBYAK_THROW(ERR_BAD_PNUM) + const int allRegNum = pNum + tNum_ + (useRcx_ ? 1 : 0) + (useRdx_ ? 1 : 0); + if (tNum_ < 0 || allRegNum > maxRegNum) XBYAK_THROW(ERR_BAD_TNUM) + const Reg64& _rsp = code->rsp; + saveNum_ = local::max_(0, allRegNum - noSaveNum); + const int *tbl = getOrderTbl() + noSaveNum; + for (int i = 0; i < saveNum_; i++) { + code->push(Reg64(tbl[i])); + } + P_ = (stackSizeByte + 7) / 8; + if (P_ > 0 && (P_ & 1) == (saveNum_ & 1)) P_++; // (rsp % 16) == 8, then increment P_ for 16 byte alignment + P_ *= 8; + if (P_ > 0) code->sub(_rsp, P_); + int pos = 0; + for (int i = 0; i < pNum; i++) { + pTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); + } + for (int i = 0; i < tNum_; i++) { + tTbl_[i] = Xbyak::Reg64(getRegIdx(pos)); + } + if (useRcx_ && rcxPos < pNum) code_->mov(code_->r10, code_->rcx); + if (useRdx_ && rdxPos < pNum) code_->mov(code_->r11, code_->rdx); + p_.init(pTbl_, pNum); + t_.init(tTbl_, tNum_); + } + /* + make epilog manually + @param callRet [in] call ret() if true + */ + void close(bool callRet = true) + { + using namespace Xbyak; + const Reg64& _rsp = code_->rsp; + const int *tbl = getOrderTbl() + noSaveNum; + if (P_ > 0) code_->add(_rsp, P_); + for (int i = 0; i < saveNum_; i++) { + code_->pop(Reg64(tbl[saveNum_ - 1 - i])); + } + + if (callRet) code_->ret(); + } + ~StackFrame() + { + if (!makeEpilog_) return; + close(); + } +private: + const int *getOrderTbl() const + { + using namespace Xbyak; + static const int tbl[] = { +#ifdef XBYAK64_WIN + Operand::RCX, Operand::RDX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, Operand::RDI, Operand::RSI, +#else + Operand::RDI, Operand::RSI, Operand::RDX, Operand::RCX, Operand::R8, Operand::R9, Operand::R10, Operand::R11, +#endif + Operand::RBX, Operand::RBP, Operand::R12, Operand::R13, Operand::R14, Operand::R15 + }; + return &tbl[0]; + } + int getRegIdx(int& pos) const + { + assert(pos < maxRegNum); + using namespace Xbyak; + const int *tbl = getOrderTbl(); + int r = tbl[pos++]; + if (useRcx_) { + if (r == Operand::RCX) { return Operand::R10; } + if (r == Operand::R10) { r = tbl[pos++]; } + } + if (useRdx_) { + if (r == Operand::RDX) { return Operand::R11; } + if (r == Operand::R11) { return tbl[pos++]; } + } + return r; + } +}; +#endif + +class Profiler { + int mode_; + const char *suffix_; + const void *startAddr_; +#ifdef XBYAK_USE_PERF + FILE *fp_; +#endif +public: + enum { + None = 0, + Perf = 1, + VTune = 2 + }; + Profiler() + : mode_(None) + , suffix_("") + , startAddr_(0) +#ifdef XBYAK_USE_PERF + , fp_(0) +#endif + { + } + // append suffix to funcName + void setNameSuffix(const char *suffix) + { + suffix_ = suffix; + } + void setStartAddr(const void *startAddr) + { + startAddr_ = startAddr; + } + void init(int mode) + { + mode_ = None; + switch (mode) { + default: + case None: + return; + case Perf: +#ifdef XBYAK_USE_PERF + close(); + { + const int pid = getpid(); + char name[128]; + snprintf(name, sizeof(name), "/tmp/perf-%d.map", pid); + fp_ = fopen(name, "a+"); + if (fp_ == 0) { + fprintf(stderr, "can't open %s\n", name); + return; + } + } + mode_ = Perf; +#endif + return; + case VTune: +#ifdef XBYAK_USE_VTUNE + dlopen("dummy", RTLD_LAZY); // force to load dlopen to enable jit profiling + if (iJIT_IsProfilingActive() != iJIT_SAMPLING_ON) { + fprintf(stderr, "VTune profiling is not active\n"); + return; + } + mode_ = VTune; +#endif + return; + } + } + ~Profiler() + { + close(); + } + void close() + { +#ifdef XBYAK_USE_PERF + if (fp_ == 0) return; + fclose(fp_); + fp_ = 0; +#endif + } + void set(const char *funcName, const void *startAddr, size_t funcSize) const + { + if (mode_ == None) return; +#if !defined(XBYAK_USE_PERF) && !defined(XBYAK_USE_VTUNE) + (void)funcName; + (void)startAddr; + (void)funcSize; +#endif +#ifdef XBYAK_USE_PERF + if (mode_ == Perf) { + if (fp_ == 0) return; + fprintf(fp_, "%llx %zx %s%s", (long long)startAddr, funcSize, funcName, suffix_); + /* + perf does not recognize the function name which is less than 3, + so append '_' at the end of the name if necessary + */ + size_t n = strlen(funcName) + strlen(suffix_); + for (size_t i = n; i < 3; i++) { + fprintf(fp_, "_"); + } + fprintf(fp_, "\n"); + fflush(fp_); + } +#endif +#ifdef XBYAK_USE_VTUNE + if (mode_ != VTune) return; + char className[] = ""; + char fileName[] = ""; + iJIT_Method_Load jmethod = {}; + jmethod.method_id = iJIT_GetNewMethodID(); + jmethod.class_file_name = className; + jmethod.source_file_name = fileName; + jmethod.method_load_address = const_cast<void*>(startAddr); + jmethod.method_size = funcSize; + jmethod.line_number_size = 0; + char buf[128]; + snprintf(buf, sizeof(buf), "%s%s", funcName, suffix_); + jmethod.method_name = buf; + iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&jmethod); +#endif + } + /* + for continuous set + funcSize = endAddr - <previous set endAddr> + */ + void set(const char *funcName, const void *endAddr) + { + set(funcName, startAddr_, (size_t)endAddr - (size_t)startAddr_); + startAddr_ = endAddr; + } +}; +#endif // XBYAK_ONLY_CLASS_CPU + +} } // end of util + +#endif |
