evoasm 0.0.2.pre7 → 0.1.0.pre2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gdbinit +41 -0
- data/.gitignore +1 -2
- data/.gitmodules +3 -0
- data/.rubocop.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.md +660 -0
- data/Makefile +1 -1
- data/README.md +17 -9
- data/Rakefile +39 -107
- data/bin/gdb +1 -1
- data/bin/gdb_loop +4 -0
- data/docs/FindingInstructions.md +17 -0
- data/docs/JIT.md +14 -0
- data/docs/SymbolicRegression.md +102 -0
- data/docs/Visualization.md +29 -0
- data/docs/examples/bit_insts.rb +44 -0
- data/docs/examples/jit.rb +26 -0
- data/docs/examples/loss.gif +0 -0
- data/docs/examples/program.png +0 -0
- data/docs/examples/sym_reg.rb +64 -0
- data/docs/examples/vis.rb +38 -0
- data/evoasm.gemspec +21 -15
- data/ext/evoasm_ext/Rakefile +3 -0
- data/ext/evoasm_ext/compile.rake +35 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.c +226 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-alloc.h +84 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.c +52 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-arch.h +101 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-bitmap.h +158 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.c +204 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-buf.h +109 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.c +124 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-domain.h +279 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-error.h +108 -0
- data/ext/evoasm_ext/{evoasm-log.c → libevoasm/src/evoasm-log.c} +36 -18
- data/ext/evoasm_ext/libevoasm/src/evoasm-log.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.c +22 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-param.h +33 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.c +192 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop-params.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.c +1323 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-pop.h +107 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.c +116 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program-io.h +60 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.c +1827 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-program.h +167 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.c +65 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-rand.h +76 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.c +106 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-signal.h +58 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-util.h +112 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.c +925 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm-x64.h +277 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.c +28 -0
- data/ext/evoasm_ext/libevoasm/src/evoasm.h +35 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-enums.h +2077 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.c +191203 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-insts.h +1713 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.c +348 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-misc.h +93 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.c +51 -0
- data/ext/evoasm_ext/libevoasm/src/gen/evoasm-x64-params.h +509 -0
- data/lib/evoasm.rb +28 -11
- data/lib/evoasm/buffer.rb +105 -0
- data/lib/evoasm/capstone.rb +100 -0
- data/lib/evoasm/domain.rb +116 -0
- data/lib/evoasm/error.rb +37 -16
- data/lib/evoasm/exception_error.rb +19 -0
- data/lib/evoasm/ffi_ext.rb +53 -0
- data/lib/evoasm/libevoasm.rb +286 -0
- data/lib/evoasm/libevoasm/x64_enums.rb +1967 -0
- data/lib/evoasm/parameter.rb +20 -0
- data/lib/evoasm/population.rb +145 -0
- data/lib/evoasm/population/parameters.rb +227 -0
- data/lib/evoasm/population/plotter.rb +89 -0
- data/lib/evoasm/prng.rb +64 -0
- data/lib/evoasm/program.rb +195 -12
- data/lib/evoasm/program/io.rb +144 -0
- data/lib/evoasm/test.rb +8 -0
- data/lib/evoasm/version.rb +1 -1
- data/lib/evoasm/x64.rb +115 -0
- data/lib/evoasm/x64/cpu_state.rb +95 -0
- data/lib/evoasm/x64/instruction.rb +109 -0
- data/lib/evoasm/x64/operand.rb +156 -0
- data/lib/evoasm/x64/parameters.rb +211 -0
- data/test/helpers/population_helper.rb +128 -0
- data/test/helpers/test_helper.rb +1 -0
- data/test/helpers/x64_helper.rb +24 -0
- data/test/integration/bitwise_reverse_test.rb +41 -0
- data/test/integration/gcd_test.rb +52 -0
- data/test/integration/popcnt_test.rb +46 -0
- data/test/integration/sym_reg_test.rb +68 -0
- data/test/unit/evoasm/buffer_test.rb +48 -0
- data/test/unit/evoasm/capstone_test.rb +18 -0
- data/test/unit/evoasm/domain_test.rb +55 -0
- data/test/unit/evoasm/population/parameters_test.rb +106 -0
- data/test/unit/evoasm/population_test.rb +96 -0
- data/test/unit/evoasm/prng_test.rb +47 -0
- data/test/unit/evoasm/x64/cpu_state_test.rb +73 -0
- data/test/unit/evoasm/x64/encoding_test.rb +320 -0
- data/test/unit/evoasm/x64/instruction_access_test.rb +177 -0
- data/test/unit/evoasm/x64/instruction_encoding_test.rb +780 -0
- data/test/unit/evoasm/x64/instruction_test.rb +62 -0
- data/test/unit/evoasm/x64/parameters_test.rb +65 -0
- data/test/unit/evoasm/x64_test.rb +52 -0
- metadata +195 -89
- data/Gemfile.rake +0 -8
- data/Gemfile.rake.lock +0 -51
- data/LICENSE.txt +0 -373
- data/data/tables/README.md +0 -19
- data/data/tables/x64.csv +0 -1684
- data/data/templates/evoasm-x64.c.erb +0 -319
- data/data/templates/evoasm-x64.h.erb +0 -126
- data/examples/abs.yml +0 -20
- data/examples/popcnt.yml +0 -17
- data/examples/sym_reg.yml +0 -26
- data/exe/evoasm-search +0 -13
- data/ext/evoasm_ext/evoasm-alloc.c +0 -145
- data/ext/evoasm_ext/evoasm-alloc.h +0 -59
- data/ext/evoasm_ext/evoasm-arch.c +0 -44
- data/ext/evoasm_ext/evoasm-arch.h +0 -161
- data/ext/evoasm_ext/evoasm-bitmap.h +0 -114
- data/ext/evoasm_ext/evoasm-buf.c +0 -130
- data/ext/evoasm_ext/evoasm-buf.h +0 -47
- data/ext/evoasm_ext/evoasm-error.c +0 -31
- data/ext/evoasm_ext/evoasm-error.h +0 -75
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +0 -121
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +0 -86
- data/ext/evoasm_ext/evoasm-log.h +0 -69
- data/ext/evoasm_ext/evoasm-misc.c +0 -23
- data/ext/evoasm_ext/evoasm-misc.h +0 -282
- data/ext/evoasm_ext/evoasm-param.h +0 -37
- data/ext/evoasm_ext/evoasm-search.c +0 -2145
- data/ext/evoasm_ext/evoasm-search.h +0 -214
- data/ext/evoasm_ext/evoasm-util.h +0 -40
- data/ext/evoasm_ext/evoasm-x64.c +0 -275624
- data/ext/evoasm_ext/evoasm-x64.h +0 -5436
- data/ext/evoasm_ext/evoasm.c +0 -7
- data/ext/evoasm_ext/evoasm.h +0 -23
- data/ext/evoasm_ext/evoasm_ext.c +0 -1757
- data/ext/evoasm_ext/extconf.rb +0 -31
- data/lib/evoasm/cli.rb +0 -6
- data/lib/evoasm/cli/search.rb +0 -127
- data/lib/evoasm/core_ext.rb +0 -1
- data/lib/evoasm/core_ext/array.rb +0 -9
- data/lib/evoasm/core_ext/integer.rb +0 -10
- data/lib/evoasm/core_ext/kwstruct.rb +0 -13
- data/lib/evoasm/core_ext/range.rb +0 -5
- data/lib/evoasm/examples.rb +0 -27
- data/lib/evoasm/gen.rb +0 -8
- data/lib/evoasm/gen/enum.rb +0 -169
- data/lib/evoasm/gen/name_util.rb +0 -80
- data/lib/evoasm/gen/state.rb +0 -176
- data/lib/evoasm/gen/state_dsl.rb +0 -152
- data/lib/evoasm/gen/strio.rb +0 -27
- data/lib/evoasm/gen/translator.rb +0 -1102
- data/lib/evoasm/gen/version.rb +0 -5
- data/lib/evoasm/gen/x64.rb +0 -237
- data/lib/evoasm/gen/x64/funcs.rb +0 -495
- data/lib/evoasm/gen/x64/inst.rb +0 -781
- data/lib/evoasm/search.rb +0 -40
- data/lib/evoasm/tasks/gen_task.rb +0 -86
- data/lib/evoasm/tasks/template_task.rb +0 -52
- data/test/test_helper.rb +0 -1
- data/test/x64/test_helper.rb +0 -19
- data/test/x64/x64_test.rb +0 -87
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2016 Julian Aron Prenner <jap@polyadic.com>
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#pragma once
|
|
19
|
+
|
|
20
|
+
#define EVOASM_MAX(a,b) (((a) > (b)) ? (a) : (b))
|
|
21
|
+
#define EVOASM_MIN(a,b) (((a) < (b)) ? (a) : (b))
|
|
22
|
+
#define EVOASM_CLAMP(x, min, max) (((x) > (max)) ? (max) : (((x) < (min)) ? (min) : (x)))
|
|
23
|
+
|
|
24
|
+
#define EVOASM_ALIGN_DOWN(s, a) ((s) &~ ((a) - 1))
|
|
25
|
+
#define EVOASM_ALIGN_UP(s, a) EVOASM_ALIGN_DOWN(((s) + (a) - 1), a)
|
|
26
|
+
|
|
27
|
+
#define EVOASM_ARY_LEN(ary) (sizeof(ary) / sizeof(ary[0]))
|
|
28
|
+
|
|
29
|
+
#ifdef __GNUC__
|
|
30
|
+
# define evoasm_unlikely(e) (__builtin_expect(e, 0))
|
|
31
|
+
# define evoasm_likely(e) (__builtin_expect(e, 1))
|
|
32
|
+
# define evoasm_used __attribute__((used))
|
|
33
|
+
# define evoasm_printf(x, y) __attribute__((__format__(__printf__, x, y)))
|
|
34
|
+
#else
|
|
35
|
+
# define evoasm_unlikely(e) (e)
|
|
36
|
+
# define evoasm_likely(e) (e)
|
|
37
|
+
# define evoasm_used
|
|
38
|
+
# define evoasm_printf
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
#if defined(__GNUC__)
|
|
42
|
+
# define evoasm_check_return __attribute__((warn_unused_result))
|
|
43
|
+
# define evoasm_force_inline __attribute__((always_inline))
|
|
44
|
+
# define evoasm_packed(decl) decl __attribute__((__packed__))
|
|
45
|
+
# define evoasm_aligned(align) __attribute__ ((aligned(align)))
|
|
46
|
+
#elif defined(_MSC_VER)
|
|
47
|
+
# define evoasm_check_return _Check_return_
|
|
48
|
+
# define evoasm_force_inline __forceinline
|
|
49
|
+
# define evoasm_packed(decl) __pragma(pack(push, 1)) decl __pragma(pack(pop))
|
|
50
|
+
# define evoasm_aligned(align) __declspec(align(align))
|
|
51
|
+
#else
|
|
52
|
+
# define evoasm_check_return
|
|
53
|
+
# define evoasm_force_inline
|
|
54
|
+
# define evoasm_packed(decl)
|
|
55
|
+
# define evoasm_aligned(align)
|
|
56
|
+
#endif
|
|
57
|
+
|
|
58
|
+
#define EVOASM_MEMCPY_N(dst, src, n) memcpy(dst, src, (n) * sizeof(*(src)))
|
|
59
|
+
#define EVOASM_MEMSET_N(ptr, val, n) memset(ptr, val, (n) * sizeof(*(ptr)))
|
|
60
|
+
|
|
61
|
+
#define EVOASM_DEF_ALLOC_FUNC(type) \
|
|
62
|
+
evoasm_##type##_t *evoasm_##type##_alloc() { return evoasm_malloc(sizeof(evoasm_##type##_t)); }
|
|
63
|
+
|
|
64
|
+
#define EVOASM_DEF_FREE_FUNC(type) \
|
|
65
|
+
void evoasm_##type##_free(evoasm_##type##_t *ptr) { evoasm_free(ptr); }
|
|
66
|
+
|
|
67
|
+
#define EVOASM_DECL_ALLOC_FUNC(type) \
|
|
68
|
+
evoasm_##type##_t *evoasm_##type##_alloc();
|
|
69
|
+
|
|
70
|
+
#define EVOASM_DECL_FREE_FUNC(type) \
|
|
71
|
+
void evoasm_##type##_free(evoasm_##type##_t *ptr);
|
|
72
|
+
|
|
73
|
+
#define EVOASM_DEF_ALLOC_FREE_FUNCS(type) \
|
|
74
|
+
EVOASM_DEF_ALLOC_FUNC(type) \
|
|
75
|
+
EVOASM_DEF_FREE_FUNC(type) \
|
|
76
|
+
|
|
77
|
+
#define EVOASM_DECL_ALLOC_FREE_FUNCS(type) \
|
|
78
|
+
EVOASM_DECL_ALLOC_FUNC(type) \
|
|
79
|
+
EVOASM_DECL_FREE_FUNC(type) \
|
|
80
|
+
|
|
81
|
+
#define EVOASM_DEF_ZERO_INIT_FUNC(type) \
|
|
82
|
+
void evoasm_##type##_init(evoasm_##type##_t *ptr) {\
|
|
83
|
+
static evoasm_##type##_t zero = {0}; \
|
|
84
|
+
*ptr = zero; \
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#define EVOASM_DEF_EMPTY_DESTROY_FUNC(type) \
|
|
88
|
+
void evoasm_##type##_destroy(evoasm_##type##_t *ptr) {}
|
|
89
|
+
|
|
90
|
+
#define EVOASM_DEF_GETTER(type, field, value_type) \
|
|
91
|
+
value_type evoasm_##type##_get_##field(evoasm_##type##_t *ptr) { \
|
|
92
|
+
return (value_type) ptr->field; \
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
#define EVOASM_DEF_BOOL_GETTER(type, field) \
|
|
96
|
+
bool evoasm_##type##_is_##field(evoasm_##type##_t *ptr) { \
|
|
97
|
+
return ptr->field; \
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
#define EVOASM_DEF_SETTER(type, field, value_type, field_type) \
|
|
101
|
+
void evoasm_##type##_set_##field(evoasm_##type##_t *ptr, value_type value) { \
|
|
102
|
+
ptr->field = (field_type) value; \
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
#define EVOASM_SWAP(type, a, b) do { type s = (a); (a) = (b); (b) = s;} while (0)
|
|
106
|
+
|
|
107
|
+
#if defined(__linux__) || defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))
|
|
108
|
+
#define EVOASM_UNIX
|
|
109
|
+
#endif
|
|
110
|
+
|
|
111
|
+
#define EVOASM_CB_CONTINUE true
|
|
112
|
+
#define EVOASM_CB_STOP false
|
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2016 Julian Aron Prenner <jap@polyadic.com>
|
|
3
|
+
*
|
|
4
|
+
* This program is free software: you can redistribute it and/or modify
|
|
5
|
+
* it under the terms of the GNU Affero General Public License as published by
|
|
6
|
+
* the Free Software Foundation, either version 3 of the License, or
|
|
7
|
+
* (at your option) any later version.
|
|
8
|
+
*
|
|
9
|
+
* This program is distributed in the hope that it will be useful,
|
|
10
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
* GNU Affero General Public License for more details.
|
|
13
|
+
*
|
|
14
|
+
* You should have received a copy of the GNU Affero General Public License
|
|
15
|
+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include "evoasm-x64.h"
|
|
19
|
+
#include "evoasm.h"
|
|
20
|
+
#include "evoasm-signal.h"
|
|
21
|
+
|
|
22
|
+
EVOASM_DEF_LOG_TAG("x64")
|
|
23
|
+
|
|
24
|
+
uint8_t evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_NONE] = {0};
|
|
25
|
+
|
|
26
|
+
static evoasm_x64_reg_id_t evoasm_x64_sysv_callee_save_regs[] = {
|
|
27
|
+
EVOASM_X64_REG_BP,
|
|
28
|
+
EVOASM_X64_REG_B,
|
|
29
|
+
EVOASM_X64_REG_12,
|
|
30
|
+
EVOASM_X64_REG_13,
|
|
31
|
+
EVOASM_X64_REG_14,
|
|
32
|
+
EVOASM_X64_REG_15,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
static evoasm_success_t
|
|
36
|
+
evoasm_x64_func_emit_prolog_or_epilog(evoasm_x64_abi_t abi, evoasm_buf_t *buf, bool prolog) {
|
|
37
|
+
size_t regs_len = EVOASM_ARY_LEN(evoasm_x64_sysv_callee_save_regs);
|
|
38
|
+
evoasm_x64_params_t params = {0};
|
|
39
|
+
|
|
40
|
+
for(size_t i = 0; i < regs_len; i++) {
|
|
41
|
+
evoasm_x64_reg_id_t reg = evoasm_x64_sysv_callee_save_regs[prolog ? i : (regs_len - 1 - i)];
|
|
42
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg);
|
|
43
|
+
|
|
44
|
+
if(prolog) {
|
|
45
|
+
EVOASM_X64_ENC(push_r64);
|
|
46
|
+
} else {
|
|
47
|
+
EVOASM_X64_ENC(pop_r64);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if(!prolog) {
|
|
52
|
+
EVOASM_X64_ENC(ret);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return true;
|
|
56
|
+
|
|
57
|
+
enc_failed:
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
evoasm_success_t
|
|
62
|
+
evoasm_x64_emit_func_prolog(evoasm_x64_abi_t abi, evoasm_buf_t *buf) {
|
|
63
|
+
return evoasm_x64_func_emit_prolog_or_epilog(abi, buf, true);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
evoasm_success_t
|
|
67
|
+
evoasm_x64_emit_func_epilog(evoasm_x64_abi_t abi, evoasm_buf_t *buf) {
|
|
68
|
+
return evoasm_x64_func_emit_prolog_or_epilog(abi, buf, false);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
evoasm_success_t
|
|
72
|
+
evoasm_x64_init() {
|
|
73
|
+
extern evoasm_arch_info_t _evoasm_arch_infos[EVOASM_ARCH_NONE];
|
|
74
|
+
extern evoasm_arch_id_t _evoasm_current_arch;
|
|
75
|
+
uint64_t features;
|
|
76
|
+
EVOASM_TRY(cpuid_failed, evoasm_x64_get_features, &features);
|
|
77
|
+
|
|
78
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_GP] = 8;
|
|
79
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_RFLAGS] = 8;
|
|
80
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_IP] = 8;
|
|
81
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_MXCSR] = 4;
|
|
82
|
+
|
|
83
|
+
#ifdef EVOASM_X64_ENABLE_AVX512
|
|
84
|
+
uint64_t avx512 = EVOASM_X64_FEATURE_AVX512F |
|
|
85
|
+
EVOASM_X64_FEATURE_AVX512DQ |
|
|
86
|
+
EVOASM_X64_FEATURE_AVX512IFMA |
|
|
87
|
+
EVOASM_X64_FEATURE_AVX512PF |
|
|
88
|
+
EVOASM_X64_FEATURE_AVX512ER |
|
|
89
|
+
EVOASM_X64_FEATURE_AVX512CD |
|
|
90
|
+
EVOASM_X64_FEATURE_AVX512BW |
|
|
91
|
+
EVOASM_X64_FEATURE_AVX512VL;
|
|
92
|
+
|
|
93
|
+
if(x64->features & avx512) {
|
|
94
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 64;
|
|
95
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_ZMM] = 64;
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
#endif
|
|
99
|
+
if(features & EVOASM_X64_FEATURE_AVX2) {
|
|
100
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 32;
|
|
101
|
+
} else {
|
|
102
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 16;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
_evoasm_arch_infos[EVOASM_ARCH_X64].features = features;
|
|
106
|
+
_evoasm_current_arch = EVOASM_ARCH_X64;
|
|
107
|
+
|
|
108
|
+
evoasm_signal_install();
|
|
109
|
+
|
|
110
|
+
return true;
|
|
111
|
+
|
|
112
|
+
cpuid_failed:
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
evoasm_x64_inst_t *
|
|
117
|
+
evoasm_x64_inst(evoasm_x64_inst_id_t inst_id) {
|
|
118
|
+
return evoasm_x64_inst_(inst_id);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
evoasm_success_t
|
|
122
|
+
evoasm_x64_inst_enc(evoasm_x64_inst_t *inst, evoasm_x64_params_t *params, evoasm_buf_ref_t *buf_ref) {
|
|
123
|
+
return evoasm_x64_inst_enc_(inst, params, buf_ref);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
evoasm_success_t
|
|
127
|
+
evoasm_x64_inst_enc_basic(evoasm_x64_inst_t *inst, evoasm_x64_basic_params_t *params, evoasm_buf_ref_t *buf_ref) {
|
|
128
|
+
return evoasm_x64_inst_enc_basic_(inst, params, buf_ref);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
evoasm_success_t
|
|
132
|
+
evoasm_x64_enc(evoasm_x64_inst_id_t inst_id, evoasm_x64_params_t *params, evoasm_buf_ref_t *buf_ref) {
|
|
133
|
+
return evoasm_x64_enc_(inst_id, params, buf_ref);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
evoasm_success_t
|
|
137
|
+
evoasm_x64_enc_basic(evoasm_x64_inst_id_t inst_id, evoasm_x64_basic_params_t *params, evoasm_buf_ref_t *buf_ref) {
|
|
138
|
+
return evoasm_x64_enc_basic_(inst_id, params, buf_ref);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
evoasm_x64_operand_t *
|
|
142
|
+
evoasm_x64_inst_get_operand(evoasm_x64_inst_t *inst, size_t idx) {
|
|
143
|
+
return &inst->operands[idx];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
size_t
|
|
147
|
+
evoasm_x64_inst_get_n_operands(evoasm_x64_inst_t *inst) {
|
|
148
|
+
return inst->n_operands;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
#define EVOASM_X64_OPERAND_DEF_GETTER(field, type) EVOASM_DEF_GETTER(x64_operand, field, type)
|
|
152
|
+
#define EVOASM_X64_OPERAND_DEF_BOOL_GETTER(field) EVOASM_DEF_BOOL_GETTER(x64_operand, field)
|
|
153
|
+
|
|
154
|
+
EVOASM_X64_OPERAND_DEF_BOOL_GETTER(read)
|
|
155
|
+
|
|
156
|
+
EVOASM_X64_OPERAND_DEF_BOOL_GETTER(written)
|
|
157
|
+
|
|
158
|
+
EVOASM_X64_OPERAND_DEF_BOOL_GETTER(implicit)
|
|
159
|
+
|
|
160
|
+
EVOASM_X64_OPERAND_DEF_BOOL_GETTER(maybe_written)
|
|
161
|
+
|
|
162
|
+
EVOASM_X64_OPERAND_DEF_BOOL_GETTER(mnem)
|
|
163
|
+
EVOASM_X64_OPERAND_DEF_GETTER(word, evoasm_x64_operand_word_t)
|
|
164
|
+
|
|
165
|
+
EVOASM_X64_OPERAND_DEF_GETTER(type, evoasm_x64_operand_type_t)
|
|
166
|
+
|
|
167
|
+
EVOASM_X64_OPERAND_DEF_GETTER(reg_type, evoasm_x64_reg_type_t)
|
|
168
|
+
|
|
169
|
+
EVOASM_X64_OPERAND_DEF_GETTER(imm, int8_t)
|
|
170
|
+
|
|
171
|
+
EVOASM_X64_OPERAND_DEF_GETTER(param_idx, size_t)
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
evoasm_x64_reg_id_t
|
|
175
|
+
evoasm_x64_operand_get_reg_id(evoasm_x64_operand_t *operand) {
|
|
176
|
+
return evoasm_x64_operand_get_reg_id_(operand);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
evoasm_x64_operand_size_t
|
|
180
|
+
evoasm_x64_operand_get_size(evoasm_x64_operand_t *operand) {
|
|
181
|
+
return (evoasm_x64_operand_size_t) operand->size;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
evoasm_x64_operand_size_t
|
|
185
|
+
evoasm_x64_operand_get_reg_size(evoasm_x64_operand_t *operand) {
|
|
186
|
+
return evoasm_x64_operand_get_reg_size_(operand);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
evoasm_x64_operand_size_t
|
|
190
|
+
evoasm_x64_operand_get_index_reg_size(evoasm_x64_operand_t *operand) {
|
|
191
|
+
return (evoasm_x64_operand_size_t) operand->size;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
evoasm_x64_operand_size_t evoasm_x64_operand_get_mem_size(evoasm_x64_operand_t *operand) {
|
|
195
|
+
if(operand->type != EVOASM_X64_OPERAND_TYPE_MEM && operand->type != EVOASM_X64_OPERAND_TYPE_RM && operand->type != EVOASM_X64_OPERAND_TYPE_VSIB) {
|
|
196
|
+
return EVOASM_X64_OPERAND_SIZE_NONE;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
switch(operand->word) {
|
|
200
|
+
case EVOASM_X64_OPERAND_WORD_LB:
|
|
201
|
+
case EVOASM_X64_OPERAND_WORD_HB:
|
|
202
|
+
return EVOASM_X64_OPERAND_SIZE_8;
|
|
203
|
+
case EVOASM_X64_OPERAND_WORD_W:
|
|
204
|
+
return EVOASM_X64_OPERAND_SIZE_16;
|
|
205
|
+
case EVOASM_X64_OPERAND_WORD_DW:
|
|
206
|
+
return EVOASM_X64_OPERAND_SIZE_32;
|
|
207
|
+
case EVOASM_X64_OPERAND_WORD_LQW:
|
|
208
|
+
case EVOASM_X64_OPERAND_WORD_HQW:
|
|
209
|
+
return EVOASM_X64_OPERAND_SIZE_64;
|
|
210
|
+
case EVOASM_X64_OPERAND_WORD_DQW:
|
|
211
|
+
return EVOASM_X64_OPERAND_SIZE_128;
|
|
212
|
+
case EVOASM_X64_OPERAND_WORD_VW:
|
|
213
|
+
switch(evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM]) {
|
|
214
|
+
case 16:
|
|
215
|
+
return EVOASM_X64_OPERAND_SIZE_128;
|
|
216
|
+
case 32:
|
|
217
|
+
return EVOASM_X64_OPERAND_SIZE_256;
|
|
218
|
+
case 64:
|
|
219
|
+
return EVOASM_X64_OPERAND_SIZE_512;
|
|
220
|
+
default:
|
|
221
|
+
evoasm_assert_not_reached();
|
|
222
|
+
}
|
|
223
|
+
default:
|
|
224
|
+
evoasm_assert_not_reached();
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
evoasm_param_t *
|
|
229
|
+
evoasm_x64_inst_get_param(evoasm_x64_inst_t *inst, size_t idx) {
|
|
230
|
+
return &inst->params[idx];
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
size_t
|
|
234
|
+
evoasm_x64_inst_get_n_params(evoasm_x64_inst_t *inst) {
|
|
235
|
+
return inst->n_params;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
bool
|
|
239
|
+
evoasm_x64_inst_is_basic(evoasm_x64_inst_t *inst) {
|
|
240
|
+
return inst->basic_enc_func != NULL;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const char *
|
|
244
|
+
evoasm_x64_inst_get_mnem(evoasm_x64_inst_t *inst) {
|
|
245
|
+
return (const char *) inst->mnem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
void
|
|
249
|
+
evoasm_x64_params_init(evoasm_x64_params_t *params) {
|
|
250
|
+
static evoasm_x64_params_t zero_params = {0};
|
|
251
|
+
*params = zero_params;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
void
|
|
255
|
+
evoasm_x64_basic_params_init(evoasm_x64_basic_params_t *params) {
|
|
256
|
+
static evoasm_x64_basic_params_t zero_params = {0};
|
|
257
|
+
*params = zero_params;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
static bool
|
|
261
|
+
evoasm_x64_is_useful_inst(evoasm_x64_inst_id_t inst) {
|
|
262
|
+
switch(inst) {
|
|
263
|
+
case EVOASM_X64_INST_CRC32_R32_RM8:
|
|
264
|
+
case EVOASM_X64_INST_CRC32_R32_RM16:
|
|
265
|
+
case EVOASM_X64_INST_CRC32_R32_RM32:
|
|
266
|
+
case EVOASM_X64_INST_CRC32_R64_RM8:
|
|
267
|
+
case EVOASM_X64_INST_CRC32_R64_RM64:
|
|
268
|
+
case EVOASM_X64_INST_CPUID:
|
|
269
|
+
case EVOASM_X64_INST_RDRAND_R16:
|
|
270
|
+
case EVOASM_X64_INST_RDRAND_R32:
|
|
271
|
+
case EVOASM_X64_INST_RDRAND_R64:
|
|
272
|
+
case EVOASM_X64_INST_RDSEED_R16:
|
|
273
|
+
case EVOASM_X64_INST_RDSEED_R32:
|
|
274
|
+
case EVOASM_X64_INST_RDSEED_R64:
|
|
275
|
+
case EVOASM_X64_INST_AESDEC_XMM_XMMM128:
|
|
276
|
+
case EVOASM_X64_INST_AESDECLAST_XMM_XMMM128:
|
|
277
|
+
case EVOASM_X64_INST_AESENC_XMM_XMMM128:
|
|
278
|
+
case EVOASM_X64_INST_AESENCLAST_XMM_XMMM128:
|
|
279
|
+
case EVOASM_X64_INST_AESIMC_XMM_XMMM128:
|
|
280
|
+
case EVOASM_X64_INST_AESKEYGENASSIST_XMM_XMMM128_IMM8:
|
|
281
|
+
case EVOASM_X64_INST_LOOP_REL8:
|
|
282
|
+
case EVOASM_X64_INST_LOOPE_REL8:
|
|
283
|
+
case EVOASM_X64_INST_LOOPNE_REL8:
|
|
284
|
+
return false;
|
|
285
|
+
default:
|
|
286
|
+
return true;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
size_t
|
|
291
|
+
evoasm_x64_insts(uint64_t flags, uint64_t features, uint64_t operand_types, uint64_t reg_types,
|
|
292
|
+
evoasm_x64_inst_id_t *insts) {
|
|
293
|
+
size_t len = 0;
|
|
294
|
+
bool include_useless = (flags & EVOASM_X64_INSTS_FLAG_INCLUDE_USELESS) != 0;
|
|
295
|
+
bool only_basic = (flags & EVOASM_X64_INSTS_FLAG_ONLY_BASIC) != 0;
|
|
296
|
+
|
|
297
|
+
for(size_t i = 0; i < EVOASM_X64_INST_NONE; i++) {
|
|
298
|
+
if(!include_useless && !evoasm_x64_is_useful_inst((evoasm_x64_inst_id_t) i)) goto skip;
|
|
299
|
+
|
|
300
|
+
evoasm_x64_inst_t *inst = (evoasm_x64_inst_t *) &EVOASM_X64_INSTS_VAR_NAME[i];
|
|
301
|
+
if(only_basic && !evoasm_x64_inst_is_basic(inst)) goto skip;
|
|
302
|
+
|
|
303
|
+
if((inst->features & ~features) != 0) goto skip;
|
|
304
|
+
|
|
305
|
+
if(!include_useless && inst->n_operands == 0) goto skip;
|
|
306
|
+
|
|
307
|
+
for(size_t j = 0; j < inst->n_operands; j++) {
|
|
308
|
+
evoasm_x64_operand_t *operand = &inst->operands[j];
|
|
309
|
+
|
|
310
|
+
if(((1ull << operand->type) & operand_types) == 0) goto skip;
|
|
311
|
+
|
|
312
|
+
if(operand->type == EVOASM_X64_OPERAND_TYPE_REG ||
|
|
313
|
+
operand->type == EVOASM_X64_OPERAND_TYPE_RM) {
|
|
314
|
+
if(!include_useless &&
|
|
315
|
+
(operand->reg_id == EVOASM_X64_REG_SP ||
|
|
316
|
+
operand->reg_id == EVOASM_X64_REG_IP))
|
|
317
|
+
goto skip;
|
|
318
|
+
|
|
319
|
+
if(((1ull << operand->reg_type) & reg_types) == 0) goto skip;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
insts[len++] = (evoasm_x64_inst_id_t) i;
|
|
324
|
+
skip:;
|
|
325
|
+
}
|
|
326
|
+
return len;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
static uint64_t *
|
|
331
|
+
evoasm_x64_cpu_state_get_reg_data(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_reg_id_t reg) {
|
|
332
|
+
switch(reg) {
|
|
333
|
+
case EVOASM_X64_REG_A:
|
|
334
|
+
return cpu_state->rax;
|
|
335
|
+
case EVOASM_X64_REG_C:
|
|
336
|
+
return cpu_state->rcx;
|
|
337
|
+
case EVOASM_X64_REG_D:
|
|
338
|
+
return cpu_state->rdx;
|
|
339
|
+
case EVOASM_X64_REG_B:
|
|
340
|
+
return cpu_state->rbx;
|
|
341
|
+
case EVOASM_X64_REG_SP:
|
|
342
|
+
return cpu_state->rsp;
|
|
343
|
+
case EVOASM_X64_REG_BP:
|
|
344
|
+
return cpu_state->rbp;
|
|
345
|
+
case EVOASM_X64_REG_SI:
|
|
346
|
+
return cpu_state->rsi;
|
|
347
|
+
case EVOASM_X64_REG_DI:
|
|
348
|
+
return cpu_state->rdi;
|
|
349
|
+
case EVOASM_X64_REG_8:
|
|
350
|
+
return cpu_state->r8;
|
|
351
|
+
case EVOASM_X64_REG_9:
|
|
352
|
+
return cpu_state->r9;
|
|
353
|
+
case EVOASM_X64_REG_10:
|
|
354
|
+
return cpu_state->r10;
|
|
355
|
+
case EVOASM_X64_REG_11:
|
|
356
|
+
return cpu_state->r11;
|
|
357
|
+
case EVOASM_X64_REG_12:
|
|
358
|
+
return cpu_state->r12;
|
|
359
|
+
case EVOASM_X64_REG_13:
|
|
360
|
+
return cpu_state->r13;
|
|
361
|
+
case EVOASM_X64_REG_14:
|
|
362
|
+
return cpu_state->r14;
|
|
363
|
+
case EVOASM_X64_REG_15:
|
|
364
|
+
return cpu_state->r15;
|
|
365
|
+
case EVOASM_X64_REG_MM0:
|
|
366
|
+
return cpu_state->mm0;
|
|
367
|
+
case EVOASM_X64_REG_MM1:
|
|
368
|
+
return cpu_state->mm1;
|
|
369
|
+
case EVOASM_X64_REG_MM2:
|
|
370
|
+
return cpu_state->mm2;
|
|
371
|
+
case EVOASM_X64_REG_MM3:
|
|
372
|
+
return cpu_state->mm3;
|
|
373
|
+
case EVOASM_X64_REG_MM4:
|
|
374
|
+
return cpu_state->mm4;
|
|
375
|
+
case EVOASM_X64_REG_MM5:
|
|
376
|
+
return cpu_state->mm5;
|
|
377
|
+
case EVOASM_X64_REG_MM6:
|
|
378
|
+
return cpu_state->mm6;
|
|
379
|
+
case EVOASM_X64_REG_MM7:
|
|
380
|
+
return cpu_state->mm7;
|
|
381
|
+
case EVOASM_X64_REG_XMM0:
|
|
382
|
+
return cpu_state->xmm0;
|
|
383
|
+
case EVOASM_X64_REG_XMM1:
|
|
384
|
+
return cpu_state->xmm1;
|
|
385
|
+
case EVOASM_X64_REG_XMM2:
|
|
386
|
+
return cpu_state->xmm2;
|
|
387
|
+
case EVOASM_X64_REG_XMM3:
|
|
388
|
+
return cpu_state->xmm3;
|
|
389
|
+
case EVOASM_X64_REG_XMM4:
|
|
390
|
+
return cpu_state->xmm4;
|
|
391
|
+
case EVOASM_X64_REG_XMM5:
|
|
392
|
+
return cpu_state->xmm5;
|
|
393
|
+
case EVOASM_X64_REG_XMM6:
|
|
394
|
+
return cpu_state->xmm6;
|
|
395
|
+
case EVOASM_X64_REG_XMM7:
|
|
396
|
+
return cpu_state->xmm7;
|
|
397
|
+
case EVOASM_X64_REG_XMM8:
|
|
398
|
+
return cpu_state->xmm8;
|
|
399
|
+
case EVOASM_X64_REG_XMM9:
|
|
400
|
+
return cpu_state->xmm9;
|
|
401
|
+
case EVOASM_X64_REG_XMM10:
|
|
402
|
+
return cpu_state->xmm10;
|
|
403
|
+
case EVOASM_X64_REG_XMM11:
|
|
404
|
+
return cpu_state->xmm11;
|
|
405
|
+
case EVOASM_X64_REG_XMM12:
|
|
406
|
+
return cpu_state->xmm12;
|
|
407
|
+
case EVOASM_X64_REG_XMM13:
|
|
408
|
+
return cpu_state->xmm13;
|
|
409
|
+
case EVOASM_X64_REG_XMM14:
|
|
410
|
+
return cpu_state->xmm14;
|
|
411
|
+
case EVOASM_X64_REG_XMM15:
|
|
412
|
+
return cpu_state->xmm15;
|
|
413
|
+
case EVOASM_X64_REG_ZMM16:
|
|
414
|
+
return cpu_state->zmm16;
|
|
415
|
+
case EVOASM_X64_REG_ZMM17:
|
|
416
|
+
return cpu_state->zmm17;
|
|
417
|
+
case EVOASM_X64_REG_ZMM18:
|
|
418
|
+
return cpu_state->zmm18;
|
|
419
|
+
case EVOASM_X64_REG_ZMM19:
|
|
420
|
+
return cpu_state->zmm19;
|
|
421
|
+
case EVOASM_X64_REG_ZMM20:
|
|
422
|
+
return cpu_state->zmm20;
|
|
423
|
+
case EVOASM_X64_REG_ZMM21:
|
|
424
|
+
return cpu_state->zmm21;
|
|
425
|
+
case EVOASM_X64_REG_ZMM22:
|
|
426
|
+
return cpu_state->zmm22;
|
|
427
|
+
case EVOASM_X64_REG_ZMM23:
|
|
428
|
+
return cpu_state->zmm23;
|
|
429
|
+
case EVOASM_X64_REG_ZMM24:
|
|
430
|
+
return cpu_state->zmm24;
|
|
431
|
+
case EVOASM_X64_REG_ZMM25:
|
|
432
|
+
return cpu_state->zmm25;
|
|
433
|
+
case EVOASM_X64_REG_ZMM26:
|
|
434
|
+
return cpu_state->zmm26;
|
|
435
|
+
case EVOASM_X64_REG_ZMM27:
|
|
436
|
+
return cpu_state->zmm27;
|
|
437
|
+
case EVOASM_X64_REG_ZMM28:
|
|
438
|
+
return cpu_state->zmm28;
|
|
439
|
+
case EVOASM_X64_REG_ZMM29:
|
|
440
|
+
return cpu_state->zmm29;
|
|
441
|
+
case EVOASM_X64_REG_ZMM30:
|
|
442
|
+
return cpu_state->zmm30;
|
|
443
|
+
case EVOASM_X64_REG_ZMM31:
|
|
444
|
+
return cpu_state->zmm31;
|
|
445
|
+
case EVOASM_X64_REG_RFLAGS:
|
|
446
|
+
return cpu_state->rflags;
|
|
447
|
+
case EVOASM_X64_REG_IP:
|
|
448
|
+
return cpu_state->ip;
|
|
449
|
+
case EVOASM_X64_REG_MXCSR:
|
|
450
|
+
return cpu_state->mxcsr;
|
|
451
|
+
default:
|
|
452
|
+
evoasm_assert_not_reached();
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
static evoasm_success_t
|
|
457
|
+
evoasm_x64_emit_rip_load_store(uint8_t *data,
|
|
458
|
+
evoasm_x64_reg_id_t tmp_reg1,
|
|
459
|
+
evoasm_x64_reg_id_t tmp_reg2,
|
|
460
|
+
evoasm_buf_t *buf,
|
|
461
|
+
bool load) {
|
|
462
|
+
|
|
463
|
+
evoasm_x64_params_t params = {0};
|
|
464
|
+
|
|
465
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg1);
|
|
466
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
467
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
468
|
+
|
|
469
|
+
if(load) {
|
|
470
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg1);
|
|
471
|
+
EVOASM_X64_ENC(jmp_rm64);
|
|
472
|
+
} else {
|
|
473
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg2);
|
|
474
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, EVOASM_X64_REG_IP);
|
|
475
|
+
EVOASM_X64_ENC(lea_r64_m64);
|
|
476
|
+
|
|
477
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg1);
|
|
478
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, tmp_reg2);
|
|
479
|
+
EVOASM_X64_ENC(mov_rm64_r64);
|
|
480
|
+
}
|
|
481
|
+
return true;
|
|
482
|
+
|
|
483
|
+
enc_failed:
|
|
484
|
+
return false;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
static evoasm_success_t
|
|
488
|
+
evoasm_x64_emit_pop_push(evoasm_x64_reg_id_t reg_id, evoasm_buf_t *buf, bool pop) {
|
|
489
|
+
evoasm_x64_params_t params = {0};
|
|
490
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg_id);
|
|
491
|
+
if(pop) {
|
|
492
|
+
EVOASM_X64_ENC(pop_r64);
|
|
493
|
+
} else {
|
|
494
|
+
EVOASM_X64_ENC(push_r64);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
return true;
|
|
498
|
+
|
|
499
|
+
enc_failed:
|
|
500
|
+
return false;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
evoasm_success_t
|
|
504
|
+
evoasm_x64_emit_pop(evoasm_x64_reg_id_t reg_id, evoasm_buf_t *buf) {
|
|
505
|
+
return evoasm_x64_emit_pop_push(reg_id, buf, true);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
evoasm_success_t
|
|
509
|
+
evoasm_x64_emit_push(evoasm_x64_reg_id_t reg_id, evoasm_buf_t *buf) {
|
|
510
|
+
return evoasm_x64_emit_pop_push(reg_id, buf, false);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
static evoasm_success_t
|
|
514
|
+
evoasm_x64_emit_rflags_load_store(uint8_t *data,
|
|
515
|
+
evoasm_x64_reg_id_t tmp_reg1,
|
|
516
|
+
evoasm_x64_reg_id_t tmp_reg2,
|
|
517
|
+
evoasm_buf_t *buf,
|
|
518
|
+
bool load) {
|
|
519
|
+
|
|
520
|
+
evoasm_x64_params_t params = {0};
|
|
521
|
+
|
|
522
|
+
|
|
523
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg1);
|
|
524
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
525
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
526
|
+
|
|
527
|
+
if(load) {
|
|
528
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg2);
|
|
529
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg1);
|
|
530
|
+
EVOASM_X64_ENC(mov_r64_rm64);
|
|
531
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_push, tmp_reg2, buf);
|
|
532
|
+
EVOASM_X64_ENC(popfq);
|
|
533
|
+
} else {
|
|
534
|
+
EVOASM_X64_ENC(pushfq);
|
|
535
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_pop, tmp_reg2, buf);
|
|
536
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg1);
|
|
537
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, tmp_reg2);
|
|
538
|
+
EVOASM_X64_ENC(mov_rm64_r64);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
return true;
|
|
542
|
+
|
|
543
|
+
enc_failed:
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
|
|
548
|
+
static evoasm_success_t
|
|
549
|
+
evoasm_x64_emit_mm_load_store(evoasm_reg_id_t reg,
|
|
550
|
+
uint8_t *data,
|
|
551
|
+
evoasm_x64_reg_id_t tmp_reg,
|
|
552
|
+
evoasm_buf_t *buf,
|
|
553
|
+
bool load) {
|
|
554
|
+
|
|
555
|
+
evoasm_x64_params_t params = {0};
|
|
556
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg);
|
|
557
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
558
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
if(load) {
|
|
562
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg);
|
|
563
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
564
|
+
EVOASM_X64_ENC(movq_mm_mmm64);
|
|
565
|
+
} else {
|
|
566
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
567
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, reg);
|
|
568
|
+
EVOASM_X64_ENC(movq_mmm64_mm);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
return true;
|
|
572
|
+
|
|
573
|
+
enc_failed:
|
|
574
|
+
return false;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
static evoasm_success_t
|
|
578
|
+
evoasm_x64_emit_gp_load_store(evoasm_reg_id_t reg,
|
|
579
|
+
uint8_t *data,
|
|
580
|
+
evoasm_x64_reg_id_t tmp_reg,
|
|
581
|
+
evoasm_buf_t *buf,
|
|
582
|
+
bool load) {
|
|
583
|
+
|
|
584
|
+
evoasm_x64_params_t params = {0};
|
|
585
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg);
|
|
586
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
587
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
if(load) {
|
|
591
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg);
|
|
592
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
593
|
+
EVOASM_X64_ENC(mov_r64_rm64);
|
|
594
|
+
} else {
|
|
595
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
596
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, reg);
|
|
597
|
+
EVOASM_X64_ENC(mov_rm64_r64);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
return true;
|
|
601
|
+
|
|
602
|
+
enc_failed:
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
static evoasm_success_t
|
|
607
|
+
evoasm_x64_emit_xmm_load_store(evoasm_reg_id_t reg,
|
|
608
|
+
uint8_t *data,
|
|
609
|
+
evoasm_x64_reg_id_t tmp_reg,
|
|
610
|
+
evoasm_buf_t *buf,
|
|
611
|
+
bool load) {
|
|
612
|
+
|
|
613
|
+
evoasm_x64_params_t params = {0};
|
|
614
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg);
|
|
615
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
616
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
617
|
+
|
|
618
|
+
if(load) {
|
|
619
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg);
|
|
620
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
621
|
+
} else {
|
|
622
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
623
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, reg);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
if(evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] == 32) {
|
|
627
|
+
if(load) {
|
|
628
|
+
EVOASM_X64_ENC(vmovdqa_ymm_ymmm256);
|
|
629
|
+
} else {
|
|
630
|
+
EVOASM_X64_ENC(vmovdqa_ymmm256_ymm);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
#ifdef EVOASM_X64_ENABLE_AVX512
|
|
634
|
+
else if(evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] == 64) {
|
|
635
|
+
goto unsupported;
|
|
636
|
+
}
|
|
637
|
+
#endif
|
|
638
|
+
else {
|
|
639
|
+
if(load) {
|
|
640
|
+
EVOASM_X64_ENC(movdqa_xmm_xmmm128);
|
|
641
|
+
} else {
|
|
642
|
+
EVOASM_X64_ENC(movdqa_xmmm128_xmm);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
return true;
|
|
647
|
+
|
|
648
|
+
enc_failed:
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
|
|
653
|
+
static evoasm_success_t
|
|
654
|
+
evoasm_x64_emit_mxcsr_load_store(uint8_t *data,
|
|
655
|
+
evoasm_x64_reg_id_t tmp_reg,
|
|
656
|
+
evoasm_buf_t *buf,
|
|
657
|
+
bool load) {
|
|
658
|
+
|
|
659
|
+
evoasm_x64_params_t params = {0};
|
|
660
|
+
|
|
661
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, tmp_reg);
|
|
662
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, (evoasm_param_val_t) (uintptr_t) data);
|
|
663
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
|
664
|
+
|
|
665
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, tmp_reg);
|
|
666
|
+
if(load) {
|
|
667
|
+
EVOASM_X64_ENC(ldmxcsr_m32);
|
|
668
|
+
} else {
|
|
669
|
+
EVOASM_X64_ENC(stmxcsr_m32);
|
|
670
|
+
}
|
|
671
|
+
return true;
|
|
672
|
+
|
|
673
|
+
enc_failed:
|
|
674
|
+
return false;
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
|
|
678
|
+
static evoasm_success_t
|
|
679
|
+
evoasm_x64_emit_load_store(evoasm_x64_reg_id_t reg_id,
|
|
680
|
+
uint8_t *data,
|
|
681
|
+
evoasm_x64_reg_id_t tmp_reg1,
|
|
682
|
+
evoasm_x64_reg_id_t tmp_reg2,
|
|
683
|
+
evoasm_buf_t *buf,
|
|
684
|
+
bool load) {
|
|
685
|
+
|
|
686
|
+
evoasm_x64_reg_type_t reg_type = evoasm_x64_get_reg_type(reg_id);
|
|
687
|
+
|
|
688
|
+
switch(reg_type) {
|
|
689
|
+
case EVOASM_X64_REG_TYPE_GP: {
|
|
690
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_gp_load_store, reg_id, data, tmp_reg1, buf, load);
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
case EVOASM_X64_REG_TYPE_XMM: {
|
|
694
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_xmm_load_store, reg_id, data, tmp_reg1, buf, load);
|
|
695
|
+
break;
|
|
696
|
+
}
|
|
697
|
+
case EVOASM_X64_REG_TYPE_MM: {
|
|
698
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_mm_load_store, reg_id, data, tmp_reg1, buf, load);
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
case EVOASM_X64_REG_TYPE_IP: {
|
|
702
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_rip_load_store, data, tmp_reg1, tmp_reg2, buf, load);
|
|
703
|
+
break;
|
|
704
|
+
}
|
|
705
|
+
case EVOASM_X64_REG_TYPE_RFLAGS: {
|
|
706
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_rflags_load_store, data, tmp_reg1, tmp_reg2, buf, load);
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
case EVOASM_X64_REG_TYPE_MXCSR: {
|
|
710
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_mxcsr_load_store, data, tmp_reg1, buf, load);
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
default: {
|
|
714
|
+
#ifdef EVOASM_X64_ENABLE_AVX512
|
|
715
|
+
unsupported:
|
|
716
|
+
#endif
|
|
717
|
+
evoasm_log_fatal("non-gpr register type (%d) (unimplemented)", reg_type);
|
|
718
|
+
evoasm_assert_not_reached();
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
return true;
|
|
723
|
+
|
|
724
|
+
enc_failed:
|
|
725
|
+
return false;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
void
|
|
729
|
+
evoasm_x64_cpu_state_set(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_reg_id_t reg, const uint64_t *data,
|
|
730
|
+
size_t len) {
|
|
731
|
+
size_t bytes_len = EVOASM_MIN(evoasm_x64_reg_type_sizes[evoasm_x64_get_reg_type(reg)], len * sizeof(uint64_t));
|
|
732
|
+
memcpy(evoasm_x64_cpu_state_get_reg_data(cpu_state, reg), data, bytes_len);
|
|
733
|
+
|
|
734
|
+
if(reg == EVOASM_X64_REG_RFLAGS) {
|
|
735
|
+
/* Mask away dangerous and useless flags */
|
|
736
|
+
cpu_state->rflags[0] &= 0x8c5;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
void
|
|
741
|
+
evoasm_x64_cpu_state_memset(evoasm_x64_cpu_state_t *cpu_state, int value) {
|
|
742
|
+
memset(cpu_state, value, sizeof(evoasm_x64_cpu_state_t));
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
size_t
|
|
746
|
+
evoasm_x64_cpu_state_get(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_reg_id_t reg, evoasm_x64_operand_word_t word, uint64_t *data, size_t len) {
|
|
747
|
+
size_t size = evoasm_x64_reg_type_sizes[evoasm_x64_get_reg_type(reg)];
|
|
748
|
+
size_t cpy_len = EVOASM_MIN(len * sizeof(uint64_t), size);
|
|
749
|
+
memcpy(data, evoasm_x64_cpu_state_get_reg_data(cpu_state, reg), cpy_len);
|
|
750
|
+
|
|
751
|
+
size_t n_elems = EVOASM_MAX(1, cpy_len / sizeof(uint64_t));
|
|
752
|
+
size_t clear_from_idx = n_elems;
|
|
753
|
+
|
|
754
|
+
if(reg == EVOASM_X64_REG_RFLAGS) {
|
|
755
|
+
/* Mask away dangerous and useless flags */
|
|
756
|
+
data[0] &= 0x8c5;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
switch(word) {
|
|
760
|
+
case EVOASM_X64_OPERAND_WORD_LB:
|
|
761
|
+
data[0] &= 0x00FF;
|
|
762
|
+
clear_from_idx = 1;
|
|
763
|
+
break;
|
|
764
|
+
case EVOASM_X64_OPERAND_WORD_HB:
|
|
765
|
+
data[0] &= 0xFF00;
|
|
766
|
+
clear_from_idx = 1;
|
|
767
|
+
break;
|
|
768
|
+
case EVOASM_X64_OPERAND_WORD_W:
|
|
769
|
+
data[0] &= 0xFFFF;
|
|
770
|
+
clear_from_idx = 1;
|
|
771
|
+
break;
|
|
772
|
+
case EVOASM_X64_OPERAND_WORD_DW:
|
|
773
|
+
data[0] &= 0xFFFFFFFF;
|
|
774
|
+
clear_from_idx = 1;
|
|
775
|
+
break;
|
|
776
|
+
case EVOASM_X64_OPERAND_WORD_LQW:
|
|
777
|
+
data[0] &= 0xFFFFFFFFFFFFFFFF;
|
|
778
|
+
clear_from_idx = 1;
|
|
779
|
+
break;
|
|
780
|
+
case EVOASM_X64_OPERAND_WORD_HQW:
|
|
781
|
+
data[0] = 0;
|
|
782
|
+
clear_from_idx = 2;
|
|
783
|
+
break;
|
|
784
|
+
case EVOASM_X64_OPERAND_WORD_DQW:
|
|
785
|
+
clear_from_idx = 2;
|
|
786
|
+
break;
|
|
787
|
+
case EVOASM_X64_OPERAND_WORD_VW:
|
|
788
|
+
break;
|
|
789
|
+
case EVOASM_X64_OPERAND_WORD_NONE:
|
|
790
|
+
break;
|
|
791
|
+
default:
|
|
792
|
+
evoasm_assert_not_reached();
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
for(size_t i = clear_from_idx; i < n_elems; i++) data[i] = 0;
|
|
796
|
+
|
|
797
|
+
return n_elems;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
bool
|
|
801
|
+
evoasm_x64_cpu_state_get_rflags_flag(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_rflags_flag_t flag) {
|
|
802
|
+
uint64_t rflags = cpu_state->rflags[0];
|
|
803
|
+
|
|
804
|
+
switch(flag) {
|
|
805
|
+
case EVOASM_X64_RFLAGS_FLAG_OF:
|
|
806
|
+
return (rflags & (1 << 11)) != 0;
|
|
807
|
+
case EVOASM_X64_RFLAGS_FLAG_SF:
|
|
808
|
+
return (rflags & (1 << 7)) != 0;
|
|
809
|
+
case EVOASM_X64_RFLAGS_FLAG_ZF:
|
|
810
|
+
return (rflags & (1 << 6)) != 0;
|
|
811
|
+
case EVOASM_X64_RFLAGS_FLAG_PF:
|
|
812
|
+
return (rflags & (1 << 2)) != 0;
|
|
813
|
+
case EVOASM_X64_RFLAGS_FLAG_CF:
|
|
814
|
+
return (rflags & (1 << 0)) != 0;
|
|
815
|
+
default:
|
|
816
|
+
evoasm_assert_not_reached();
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
void
|
|
821
|
+
evoasm_x64_cpu_state_clone(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_cpu_state_t *cloned_cpu_state) {
|
|
822
|
+
*cloned_cpu_state = *cpu_state;
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
static_assert(CHAR_BIT == 8, "CHAR_BIT must be 8");
|
|
826
|
+
|
|
827
|
+
void
|
|
828
|
+
evoasm_x64_cpu_state_xor(evoasm_x64_cpu_state_t *cpu_state,
|
|
829
|
+
evoasm_x64_cpu_state_t *other_cpu_state,
|
|
830
|
+
evoasm_x64_cpu_state_t *xored_cpu_state) {
|
|
831
|
+
size_t size = sizeof(evoasm_x64_cpu_state_t);
|
|
832
|
+
uint8_t *data = (uint8_t *) cpu_state;
|
|
833
|
+
uint8_t *other_data = (uint8_t *) other_cpu_state;
|
|
834
|
+
uint8_t *xored_data = (uint8_t *) xored_cpu_state;
|
|
835
|
+
|
|
836
|
+
for(size_t i = 0; i < size; i++) {
|
|
837
|
+
xored_data[i] = data[i] ^ other_data[i];
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
void
|
|
842
|
+
evoasm_x64_cpu_state_init(evoasm_x64_cpu_state_t *cpu_state, evoasm_x64_cpu_state_flags_t flags) {
|
|
843
|
+
static evoasm_x64_cpu_state_t zero_cpu_state = {0};
|
|
844
|
+
*cpu_state = zero_cpu_state;
|
|
845
|
+
cpu_state->flags = flags;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
|
|
849
|
+
EVOASM_DEF_EMPTY_DESTROY_FUNC(x64_cpu_state)
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
evoasm_x64_cpu_state_t *
|
|
853
|
+
evoasm_x64_cpu_state_alloc() {
|
|
854
|
+
return evoasm_aligned_alloc(32, sizeof(evoasm_x64_cpu_state_t));
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
void
|
|
858
|
+
evoasm_x64_cpu_state_free(evoasm_x64_cpu_state_t *cpu_state) {
|
|
859
|
+
evoasm_free(cpu_state);
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
evoasm_success_t
|
|
863
|
+
evoasm_x64_cpu_state_emit_load_store(evoasm_x64_cpu_state_t *cpu_state,
|
|
864
|
+
evoasm_buf_t *buf, bool load) {
|
|
865
|
+
|
|
866
|
+
bool ip = cpu_state->flags & EVOASM_X64_CPU_STATE_FLAG_IP;
|
|
867
|
+
bool sp = cpu_state->flags & EVOASM_X64_CPU_STATE_FLAG_SP;
|
|
868
|
+
bool mxcsr = cpu_state->flags & EVOASM_X64_CPU_STATE_FLAG_MXCSR;
|
|
869
|
+
bool rflags = cpu_state->flags & EVOASM_X64_CPU_STATE_FLAG_RFLAGS;
|
|
870
|
+
|
|
871
|
+
static const evoasm_x64_reg_id_t tmp_reg1 = EVOASM_X64_REG_14;
|
|
872
|
+
static const evoasm_x64_reg_id_t tmp_reg2 = EVOASM_X64_REG_15;
|
|
873
|
+
|
|
874
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_push, tmp_reg1, buf);
|
|
875
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_push, tmp_reg2, buf);
|
|
876
|
+
|
|
877
|
+
for(evoasm_x64_reg_id_t reg_id = (evoasm_x64_reg_id_t) 0; reg_id < EVOASM_X64_REG_NONE; reg_id++) {
|
|
878
|
+
if(reg_id == tmp_reg1 || reg_id == tmp_reg2) continue;
|
|
879
|
+
#ifndef EVOASM_X64_ENABLE_AVX512
|
|
880
|
+
if(reg_id >= EVOASM_X64_REG_ZMM16) continue;
|
|
881
|
+
#endif
|
|
882
|
+
|
|
883
|
+
if(!ip && reg_id == EVOASM_X64_REG_IP) continue;
|
|
884
|
+
if(!sp && reg_id == EVOASM_X64_REG_SP) continue;
|
|
885
|
+
if(!mxcsr && reg_id == EVOASM_X64_REG_MXCSR) continue;
|
|
886
|
+
if(!rflags && reg_id == EVOASM_X64_REG_RFLAGS) continue;
|
|
887
|
+
|
|
888
|
+
uint8_t *data = (uint8_t *) evoasm_x64_cpu_state_get_reg_data(cpu_state, reg_id);
|
|
889
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_load_store, reg_id, data, tmp_reg1, tmp_reg2, buf, load);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_pop, tmp_reg2, buf);
|
|
893
|
+
{
|
|
894
|
+
uint8_t *data = (uint8_t *) evoasm_x64_cpu_state_get_reg_data(cpu_state, tmp_reg2);
|
|
895
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_load_store, tmp_reg2, data, tmp_reg1, EVOASM_X64_REG_NONE, buf, load);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_pop, tmp_reg1, buf);
|
|
899
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_push, tmp_reg2, buf);
|
|
900
|
+
{
|
|
901
|
+
uint8_t *data = (uint8_t *) evoasm_x64_cpu_state_get_reg_data(cpu_state, tmp_reg1);
|
|
902
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_load_store, tmp_reg1, data, tmp_reg2, EVOASM_X64_REG_NONE, buf, load);
|
|
903
|
+
}
|
|
904
|
+
EVOASM_TRY(enc_failed, evoasm_x64_emit_pop, tmp_reg2, buf);
|
|
905
|
+
|
|
906
|
+
return true;
|
|
907
|
+
|
|
908
|
+
enc_failed:
|
|
909
|
+
return false;
|
|
910
|
+
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
evoasm_success_t
|
|
914
|
+
evoasm_x64_cpu_state_emit_load(evoasm_x64_cpu_state_t *cpu_state, evoasm_buf_t *buf) {
|
|
915
|
+
return evoasm_x64_cpu_state_emit_load_store(cpu_state, buf, true);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
evoasm_success_t
|
|
919
|
+
evoasm_x64_cpu_state_emit_store(evoasm_x64_cpu_state_t *cpu_state, evoasm_buf_t *buf) {
|
|
920
|
+
return evoasm_x64_cpu_state_emit_load_store(cpu_state, buf, false);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
EVOASM_DEF_ALLOC_FREE_FUNCS(x64_params)
|
|
924
|
+
|
|
925
|
+
EVOASM_DEF_ALLOC_FREE_FUNCS(x64_basic_params)
|