evoasm 0.0.2.pre7
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 +7 -0
- data/.gemrelease +2 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/Gemfile.rake +8 -0
- data/Gemfile.rake.lock +51 -0
- data/LICENSE.txt +373 -0
- data/Makefile +6 -0
- data/README.md +43 -0
- data/Rakefile +128 -0
- data/bin/gdb +2 -0
- data/data/tables/README.md +19 -0
- data/data/tables/x64.csv +1684 -0
- data/data/templates/evoasm-x64.c.erb +319 -0
- data/data/templates/evoasm-x64.h.erb +126 -0
- data/evoasm.gemspec +30 -0
- data/examples/abs.yml +20 -0
- data/examples/popcnt.yml +17 -0
- data/examples/sym_reg.yml +26 -0
- data/exe/evoasm-search +13 -0
- data/ext/evoasm_ext/evoasm-alloc.c +145 -0
- data/ext/evoasm_ext/evoasm-alloc.h +59 -0
- data/ext/evoasm_ext/evoasm-arch.c +44 -0
- data/ext/evoasm_ext/evoasm-arch.h +161 -0
- data/ext/evoasm_ext/evoasm-bitmap.h +114 -0
- data/ext/evoasm_ext/evoasm-buf.c +130 -0
- data/ext/evoasm_ext/evoasm-buf.h +47 -0
- data/ext/evoasm_ext/evoasm-error.c +31 -0
- data/ext/evoasm_ext/evoasm-error.h +75 -0
- data/ext/evoasm_ext/evoasm-free-list.c.tmpl +121 -0
- data/ext/evoasm_ext/evoasm-free-list.h.tmpl +86 -0
- data/ext/evoasm_ext/evoasm-log.c +108 -0
- data/ext/evoasm_ext/evoasm-log.h +69 -0
- data/ext/evoasm_ext/evoasm-misc.c +23 -0
- data/ext/evoasm_ext/evoasm-misc.h +282 -0
- data/ext/evoasm_ext/evoasm-param.h +37 -0
- data/ext/evoasm_ext/evoasm-search.c +2145 -0
- data/ext/evoasm_ext/evoasm-search.h +214 -0
- data/ext/evoasm_ext/evoasm-util.h +40 -0
- data/ext/evoasm_ext/evoasm-x64.c +275624 -0
- data/ext/evoasm_ext/evoasm-x64.h +5436 -0
- data/ext/evoasm_ext/evoasm.c +7 -0
- data/ext/evoasm_ext/evoasm.h +23 -0
- data/ext/evoasm_ext/evoasm_ext.c +1757 -0
- data/ext/evoasm_ext/extconf.rb +31 -0
- data/lib/evoasm/cli/search.rb +127 -0
- data/lib/evoasm/cli.rb +6 -0
- data/lib/evoasm/core_ext/array.rb +9 -0
- data/lib/evoasm/core_ext/integer.rb +10 -0
- data/lib/evoasm/core_ext/kwstruct.rb +13 -0
- data/lib/evoasm/core_ext/range.rb +5 -0
- data/lib/evoasm/core_ext.rb +1 -0
- data/lib/evoasm/error.rb +20 -0
- data/lib/evoasm/examples.rb +27 -0
- data/lib/evoasm/gen/enum.rb +169 -0
- data/lib/evoasm/gen/name_util.rb +80 -0
- data/lib/evoasm/gen/state.rb +176 -0
- data/lib/evoasm/gen/state_dsl.rb +152 -0
- data/lib/evoasm/gen/strio.rb +27 -0
- data/lib/evoasm/gen/translator.rb +1102 -0
- data/lib/evoasm/gen/version.rb +5 -0
- data/lib/evoasm/gen/x64/funcs.rb +495 -0
- data/lib/evoasm/gen/x64/inst.rb +781 -0
- data/lib/evoasm/gen/x64.rb +237 -0
- data/lib/evoasm/gen.rb +8 -0
- data/lib/evoasm/program.rb +23 -0
- data/lib/evoasm/search.rb +40 -0
- data/lib/evoasm/tasks/gen_task.rb +86 -0
- data/lib/evoasm/tasks/template_task.rb +52 -0
- data/lib/evoasm/version.rb +3 -0
- data/lib/evoasm.rb +22 -0
- data/test/test_helper.rb +1 -0
- data/test/x64/test_helper.rb +19 -0
- data/test/x64/x64_test.rb +87 -0
- metadata +221 -0
@@ -0,0 +1,319 @@
|
|
1
|
+
/* AUTOGENERATED FILE, DO NOT EDIT */
|
2
|
+
|
3
|
+
#include "evoasm-x64.h"
|
4
|
+
#include "evoasm-error.h"
|
5
|
+
#include "evoasm-alloc.h"
|
6
|
+
|
7
|
+
static const char *_evoasm_log_tag = "x64";
|
8
|
+
|
9
|
+
uint8_t evoasm_x64_reg_type_sizes[EVOASM_X64_N_REG_TYPES] = {0};
|
10
|
+
|
11
|
+
static int64_t
|
12
|
+
evoasm_x64_disp_size(evoasm_x64 *x64, evoasm_arch_param_val *param_vals, evoasm_bitmap *set_params) {
|
13
|
+
evoasm_arch_param_val val = param_vals[EVOASM_X64_PARAM_DISP];
|
14
|
+
if(!evoasm_bitmap_get(set_params, EVOASM_X64_PARAM_DISP)) return 0;
|
15
|
+
if(val >= INT8_MIN && val <= INT8_MAX) return 8;
|
16
|
+
if(val >= INT32_MIN && val <= INT32_MAX) return 32;
|
17
|
+
return 0;
|
18
|
+
}
|
19
|
+
|
20
|
+
static int8_t
|
21
|
+
evoasm_x64_reg_code(evoasm_x64 *x64, evoasm_x64_reg_id reg) {
|
22
|
+
switch(reg) {
|
23
|
+
<% Evoasm::Gen::X64::REGISTERS.fetch_values(:gp, :mm, :xmm, :zmm).each do |regs| %>
|
24
|
+
<% regs.each_with_index do |reg, index| %>
|
25
|
+
case <%= reg_name_to_c reg %>: return <%= index %>;
|
26
|
+
<%end %>
|
27
|
+
<%end %>
|
28
|
+
default:
|
29
|
+
evoasm_fatal("invalid register id %d", reg);
|
30
|
+
evoasm_assert_not_reached();
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
/* PERMUTATION TABLES */
|
35
|
+
<%= permutation_tables %>
|
36
|
+
/* ------------------- */
|
37
|
+
|
38
|
+
/* FUNCS */
|
39
|
+
<%= called_funcs %>
|
40
|
+
/* ------------------- */
|
41
|
+
|
42
|
+
<%= pref_funcs %>
|
43
|
+
<%= inst_funcs %>
|
44
|
+
<%= param_domains %>
|
45
|
+
<%= inst_params %>
|
46
|
+
<%= inst_operands %>
|
47
|
+
|
48
|
+
<%= insts_c %>
|
49
|
+
|
50
|
+
static evoasm_x64_reg_id evoasm_x64_sysv_callee_save_regs[] = {
|
51
|
+
EVOASM_X64_REG_BP,
|
52
|
+
EVOASM_X64_REG_B,
|
53
|
+
EVOASM_X64_REG_12,
|
54
|
+
EVOASM_X64_REG_13,
|
55
|
+
EVOASM_X64_REG_14,
|
56
|
+
EVOASM_X64_REG_15,
|
57
|
+
};
|
58
|
+
|
59
|
+
static evoasm_success
|
60
|
+
evoasm_x64_func_prolog_or_epilog(evoasm_x64 *x64, evoasm_buf *buf, evoasm_x64_abi abi, bool prolog) {
|
61
|
+
evoasm_arch *arch = (evoasm_arch *) x64;
|
62
|
+
unsigned i;
|
63
|
+
size_t regs_len = EVOASM_ARY_LEN(evoasm_x64_sysv_callee_save_regs);
|
64
|
+
evoasm_x64_params params = {0};
|
65
|
+
|
66
|
+
/* touch RSP and RBX so we don't get a read access violation for PUSH */
|
67
|
+
//evoasm_arch_write_access(arch, (evoasm_bitmap *) &arch->acc, EVOASM_X64_REG_SP);
|
68
|
+
|
69
|
+
for(i = 0; i < regs_len; i++) {
|
70
|
+
evoasm_x64_reg_id reg = evoasm_x64_sysv_callee_save_regs[prolog ? i : (regs_len - 1 - i)];
|
71
|
+
evoasm_arch_write_access(arch, (evoasm_bitmap *) &arch->acc, reg);
|
72
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, reg);
|
73
|
+
|
74
|
+
if(prolog) {
|
75
|
+
EVOASM_X64_ENC(push_r64);
|
76
|
+
}
|
77
|
+
else {
|
78
|
+
EVOASM_X64_ENC(pop_r64);
|
79
|
+
}
|
80
|
+
evoasm_arch_save(arch, buf);
|
81
|
+
}
|
82
|
+
|
83
|
+
if(!prolog) {
|
84
|
+
EVOASM_X64_ENC(ret);
|
85
|
+
evoasm_arch_save(arch, buf);
|
86
|
+
}
|
87
|
+
|
88
|
+
return true;
|
89
|
+
|
90
|
+
enc_failed:
|
91
|
+
return false;
|
92
|
+
}
|
93
|
+
|
94
|
+
evoasm_success
|
95
|
+
evoasm_x64_func_prolog(evoasm_x64 *x64, evoasm_buf *buf, evoasm_x64_abi abi) {
|
96
|
+
return evoasm_x64_func_prolog_or_epilog(x64, buf, abi, true);
|
97
|
+
}
|
98
|
+
|
99
|
+
evoasm_success
|
100
|
+
evoasm_x64_func_epilog(evoasm_x64 *x64, evoasm_buf *buf, evoasm_x64_abi abi) {
|
101
|
+
return evoasm_x64_func_prolog_or_epilog(x64, buf, abi, false);
|
102
|
+
}
|
103
|
+
|
104
|
+
static evoasm_success
|
105
|
+
evoasm_x64_load_cpuid(evoasm_x64 *x64) {
|
106
|
+
evoasm_buf buf;
|
107
|
+
evoasm_x64_params params = {0};
|
108
|
+
bool retval = true;
|
109
|
+
|
110
|
+
uint32_t vals[<%= Evoasm::Gen::X64::CPUID.size %>][<%= Evoasm::Gen::X64::CPUID.max_by{|k, v| v.size}.size %>] = {0};
|
111
|
+
evoasm_arch *arch = (evoasm_arch *) x64;
|
112
|
+
|
113
|
+
evoasm_debug("Running CPUID...");
|
114
|
+
|
115
|
+
EVOASM_TRY(alloc_failed, evoasm_buf_init, &buf, EVOASM_BUF_TYPE_MMAP, 512);
|
116
|
+
|
117
|
+
EVOASM_TRY(enc_failed, evoasm_x64_func_prolog, x64, &buf, EVOASM_X64_ABI_SYSV);
|
118
|
+
|
119
|
+
<% remaining_flags = features.keys %>
|
120
|
+
<% io = StrIO.new %>
|
121
|
+
<% Evoasm::Gen::X64::CPUID.each_with_index do |((eax_val, ecx_val), out_regs), index0| %>
|
122
|
+
|
123
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, EVOASM_X64_REG_A);
|
124
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, <%= eax_val %>);
|
125
|
+
EVOASM_X64_ENC(mov_r32_imm32);
|
126
|
+
evoasm_arch_save(arch, &buf);
|
127
|
+
|
128
|
+
<% if ecx_val %>
|
129
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, EVOASM_X64_REG_C);
|
130
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, <%= ecx_val %>);
|
131
|
+
EVOASM_X64_ENC(mov_r32_imm32);
|
132
|
+
evoasm_arch_save(arch, &buf);
|
133
|
+
<% end %>
|
134
|
+
|
135
|
+
EVOASM_X64_ENC(cpuid);
|
136
|
+
evoasm_arch_save(arch, &buf);
|
137
|
+
|
138
|
+
<% out_regs.each.with_index do |(reg, flags), index1| %>
|
139
|
+
|
140
|
+
{
|
141
|
+
evoasm_arch_param_val addr_imm;
|
142
|
+
addr_imm = (evoasm_arch_param_val)(uintptr_t) &vals[<%= index0 %>][<%= index1 %>];
|
143
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG0, EVOASM_X64_REG_DI);
|
144
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_IMM0, addr_imm);
|
145
|
+
EVOASM_X64_ENC(mov_r64_imm64);
|
146
|
+
evoasm_arch_save(arch, &buf);
|
147
|
+
|
148
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG1, <%= reg_name_to_c reg %>);
|
149
|
+
EVOASM_X64_SET(EVOASM_X64_PARAM_REG_BASE, EVOASM_X64_REG_DI);
|
150
|
+
EVOASM_X64_ENC(mov_rm32_r32);
|
151
|
+
evoasm_arch_save(arch, &buf);
|
152
|
+
EVOASM_X64_UNSET(EVOASM_X64_PARAM_ADDRESS_SIZE);
|
153
|
+
EVOASM_X64_UNSET(EVOASM_X64_PARAM_REG_BASE);
|
154
|
+
|
155
|
+
<% flags.each_with_index do |flag, bit_index| %>
|
156
|
+
<% if remaining_flags.delete(flag) %>
|
157
|
+
<% io.indent 1 do %>
|
158
|
+
<% io.puts "if(vals[#{index0}][#{index1}] & (1 << #{bit_index})) {" %>
|
159
|
+
<% io.puts " x64->features |= #{feature_name_to_c flag};" %>
|
160
|
+
<% io.puts %{ evoasm_info("Found support for #{flag.upcase}");} %>
|
161
|
+
<% io.puts "} else {" %>
|
162
|
+
<% io.puts %{ evoasm_info("Missing support for #{flag.upcase}");} %>
|
163
|
+
<% io.puts "}" %>
|
164
|
+
<% end %>
|
165
|
+
<% end %>
|
166
|
+
<% end %>
|
167
|
+
}
|
168
|
+
<% end%>
|
169
|
+
<% end %>
|
170
|
+
|
171
|
+
EVOASM_TRY(enc_failed, evoasm_x64_func_epilog, x64, &buf, EVOASM_X64_ABI_SYSV);
|
172
|
+
|
173
|
+
/*evoasm_buf_dump(&buf, stderr);*/
|
174
|
+
|
175
|
+
EVOASM_TRY(enc_failed, evoasm_buf_protect, &buf, EVOASM_MPROT_RX);
|
176
|
+
evoasm_buf_exec(&buf);
|
177
|
+
|
178
|
+
<%= io.string %>
|
179
|
+
|
180
|
+
cleanup:
|
181
|
+
EVOASM_TRY(destroy_failed, evoasm_buf_destroy, &buf);
|
182
|
+
return retval;
|
183
|
+
enc_failed:
|
184
|
+
retval = false;
|
185
|
+
goto cleanup;
|
186
|
+
destroy_failed:
|
187
|
+
return false;
|
188
|
+
alloc_failed:
|
189
|
+
return false;
|
190
|
+
|
191
|
+
}
|
192
|
+
|
193
|
+
static uint16_t
|
194
|
+
evoasm_x64_insts(evoasm_x64 *x64, const evoasm_x64_inst **insts) {
|
195
|
+
uint16_t len = 0;
|
196
|
+
const evoasm_x64_inst *inst;
|
197
|
+
/* Assuming that at least some feature is found */
|
198
|
+
|
199
|
+
<% insts.each do |inst| %>
|
200
|
+
inst = &<%= insts_var_name %>[<%= inst.index %>];
|
201
|
+
if((inst->features & ~x64->features) == 0) insts[len++] = inst;
|
202
|
+
<% end %>
|
203
|
+
|
204
|
+
return len;
|
205
|
+
}
|
206
|
+
|
207
|
+
const evoasm_x64_inst *
|
208
|
+
evoasm_x64_get_inst(evoasm_x64 *x64, unsigned index, bool ignore_features) {
|
209
|
+
const evoasm_x64_inst *inst = &<%= insts_var_name %>[index];
|
210
|
+
if(ignore_features || (inst->features & ~x64->features) == 0) return inst;
|
211
|
+
return NULL;
|
212
|
+
}
|
213
|
+
|
214
|
+
static evoasm_arch_cls evoasm_x64_cls = {
|
215
|
+
EVOASM_ARCH_X64,
|
216
|
+
EVOASM_X64_N_INSTS,
|
217
|
+
EVOASM_X64_N_PARAMS,
|
218
|
+
15,
|
219
|
+
(evoasm_arch_insts_func) evoasm_x64_insts,
|
220
|
+
};
|
221
|
+
|
222
|
+
|
223
|
+
evoasm_success
|
224
|
+
evoasm_x64_init(evoasm_x64 *x64) {
|
225
|
+
static evoasm_x64 zero_x64 = {0};
|
226
|
+
evoasm_arch *arch = (evoasm_arch *) x64;
|
227
|
+
*x64 = zero_x64;
|
228
|
+
|
229
|
+
evoasm_arch_init(arch, &evoasm_x64_cls);
|
230
|
+
EVOASM_TRY(cpuid_failed, evoasm_x64_load_cpuid, x64);
|
231
|
+
|
232
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_GP] = 8;
|
233
|
+
|
234
|
+
#ifdef EVOASM_X64_ENABLE_AVX512
|
235
|
+
uint64_t avx512 = EVOASM_X64_FEATURE_AVX512F |
|
236
|
+
EVOASM_X64_FEATURE_AVX512DQ |
|
237
|
+
EVOASM_X64_FEATURE_AVX512IFMA |
|
238
|
+
EVOASM_X64_FEATURE_AVX512PF |
|
239
|
+
EVOASM_X64_FEATURE_AVX512ER |
|
240
|
+
EVOASM_X64_FEATURE_AVX512CD |
|
241
|
+
EVOASM_X64_FEATURE_AVX512BW |
|
242
|
+
EVOASM_X64_FEATURE_AVX512VL;
|
243
|
+
|
244
|
+
if(x64->features & avx512) {
|
245
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 64;
|
246
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_ZMM] = 64;
|
247
|
+
}
|
248
|
+
else
|
249
|
+
#endif
|
250
|
+
if(x64->features & EVOASM_X64_FEATURE_AVX2) {
|
251
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 32;
|
252
|
+
} else {
|
253
|
+
evoasm_x64_reg_type_sizes[EVOASM_X64_REG_TYPE_XMM] = 16;
|
254
|
+
}
|
255
|
+
return true;
|
256
|
+
|
257
|
+
cpuid_failed:
|
258
|
+
evoasm_arch_destroy(arch);
|
259
|
+
return false;
|
260
|
+
}
|
261
|
+
|
262
|
+
void
|
263
|
+
evoasm_x64_destroy(evoasm_x64 *x64) {
|
264
|
+
evoasm_arch *arch = (evoasm_arch *) x64;
|
265
|
+
evoasm_arch_destroy(arch);
|
266
|
+
}
|
267
|
+
|
268
|
+
<% if options[:ruby] %>
|
269
|
+
|
270
|
+
extern VALUE evoasm_cX64Instruction;
|
271
|
+
|
272
|
+
static ID _rb_x64_inst_ids[<%= insts.size %>];
|
273
|
+
static ID _rb_x64_reg_ids[<%= reg_names.n %>];
|
274
|
+
static ID _rb_x64_param_ids[<%= param_names.n %>];
|
275
|
+
static ID _rb_x64_reg_type_ids[<%= Evoasm::Gen::X64::REGISTERS.size %>];
|
276
|
+
static ID _rb_x64_operand_type_ids[<%= Evoasm::Gen::X64::REGISTERS.size %>];
|
277
|
+
|
278
|
+
ID *rb_x64_inst_ids =_rb_x64_inst_ids ;
|
279
|
+
ID *rb_x64_reg_ids = _rb_x64_reg_ids;
|
280
|
+
ID *rb_x64_param_ids = _rb_x64_param_ids;
|
281
|
+
ID *rb_x64_operand_type_ids= _rb_x64_operand_type_ids;
|
282
|
+
ID *rb_x64_reg_type_ids = _rb_x64_reg_type_ids;
|
283
|
+
|
284
|
+
void evoasm_x64_ruby_define_consts() {
|
285
|
+
|
286
|
+
<% Evoasm::Gen::X64::Inst::OPERAND_TYPES.each_with_index do |operand_type, index| %>
|
287
|
+
rb_x64_operand_type_ids[<%= index %>] = rb_intern("<%= operand_type %>");
|
288
|
+
<% end %>
|
289
|
+
|
290
|
+
|
291
|
+
<% Evoasm::Gen::X64::REGISTERS.keys.each_with_index do |reg_type, index| %>
|
292
|
+
rb_x64_reg_type_ids[<%= index %>] = rb_intern("<%= reg_type.to_s %>");
|
293
|
+
<% end %>
|
294
|
+
|
295
|
+
<% param_names.each do |name, index| %>
|
296
|
+
rb_x64_param_ids[<%= index %>] = rb_intern("<%= name.to_s %>");
|
297
|
+
<% end %>
|
298
|
+
|
299
|
+
<% features.each do |name, index| %>
|
300
|
+
rb_define_const(evoasm_cX64Instruction,
|
301
|
+
"FEATURE_<%= name.upcase %>",
|
302
|
+
INT2FIX(<%= feature_name_to_c name %>));
|
303
|
+
<% end %>
|
304
|
+
|
305
|
+
<% inst_flags.each do |name, index| %>
|
306
|
+
rb_define_const(evoasm_cX64Instruction,
|
307
|
+
"FLAG_<%= name.upcase %>",
|
308
|
+
INT2FIX(<%= inst_flag_to_c name %>));
|
309
|
+
<% end %>
|
310
|
+
|
311
|
+
<% insts.each_with_index do |inst, index| %>
|
312
|
+
rb_x64_inst_ids[<%= index %>] = rb_intern("<%= inst.name.to_s %>");
|
313
|
+
<% end %>
|
314
|
+
|
315
|
+
<% reg_names.each do |name, index| %>
|
316
|
+
rb_x64_reg_ids[<%= index %>] = rb_intern("<%= name =~ /^\d/ ? 'R' : '' %><%= name.to_s %>");
|
317
|
+
<% end %>
|
318
|
+
}
|
319
|
+
<% end %>
|
@@ -0,0 +1,126 @@
|
|
1
|
+
/* vim: set filetype=c: */
|
2
|
+
/* AUTOGENERATED FILE, DO NOT EDIT */
|
3
|
+
|
4
|
+
#pragma once
|
5
|
+
|
6
|
+
#include "evoasm.h"
|
7
|
+
#include "evoasm-util.h"
|
8
|
+
|
9
|
+
#include <stdint.h>
|
10
|
+
|
11
|
+
<%= features.to_c %>
|
12
|
+
|
13
|
+
<%= inst_flags.to_c %>
|
14
|
+
|
15
|
+
<%= exceptions.to_c %>
|
16
|
+
|
17
|
+
<%= reg_types.to_c typedef: false %>
|
18
|
+
|
19
|
+
extern uint8_t evoasm_x64_reg_type_sizes[EVOASM_X64_N_REG_TYPES];
|
20
|
+
|
21
|
+
<%= reg_names.to_c %>
|
22
|
+
|
23
|
+
static inline enum evoasm_x64_reg_type
|
24
|
+
evoasm_x64_reg_type(evoasm_x64_reg_id reg) {
|
25
|
+
switch(reg) {
|
26
|
+
<% Evoasm::Gen::X64::REGISTERS.each do |reg_type, regs| %>
|
27
|
+
<% regs.each do |reg| %>
|
28
|
+
case <%= reg_name_to_c reg %>: return <%= reg_type_to_c reg_type %>;
|
29
|
+
<% end %>
|
30
|
+
<% end %>
|
31
|
+
default: evoasm_assert_not_reached();
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
<%= param_names.to_c %>
|
36
|
+
|
37
|
+
typedef enum {
|
38
|
+
<% insts.each do |inst| %>
|
39
|
+
<%= inst_name_to_c inst %> = <%= inst.index %>,
|
40
|
+
<% end %>
|
41
|
+
EVOASM_X64_N_INSTS = <%= insts.size %>,
|
42
|
+
} evoasm_x64_inst_id;
|
43
|
+
|
44
|
+
typedef struct {
|
45
|
+
_EVOASM_ARCH_PARAMS_HEADER
|
46
|
+
evoasm_arch_param_val vals[EVOASM_X64_N_PARAMS];
|
47
|
+
} evoasm_x64_params;
|
48
|
+
|
49
|
+
_Static_assert(EVOASM_X64_N_PARAMS <= EVOASM_ARCH_MAX_PARAMS, "Too much parameters. Redeclar EVOASM_ARCH_MAX_PARAMS and evoasm_arch_params_bitmap.");
|
50
|
+
|
51
|
+
typedef struct {
|
52
|
+
evoasm_arch base;
|
53
|
+
uint64_t features;
|
54
|
+
} evoasm_x64;
|
55
|
+
|
56
|
+
<%= operand_types.to_c %>
|
57
|
+
|
58
|
+
<%= bit_masks.to_c %>
|
59
|
+
#define <%= bit_mask_to_c 0..63 %> (<%= bit_mask_to_c 0..31 %> | <%= bit_mask_to_c 32..63 %>)
|
60
|
+
#define <%= bit_mask_to_c 0..127 %> (<%= bit_mask_to_c 0..63 %> | <%= bit_mask_to_c 64..127 %>)
|
61
|
+
|
62
|
+
typedef struct {
|
63
|
+
unsigned acc_r: 1;
|
64
|
+
unsigned acc_w: 1;
|
65
|
+
unsigned acc_u: 1;
|
66
|
+
unsigned acc_c: 1;
|
67
|
+
unsigned implicit: 1;
|
68
|
+
unsigned param_idx: 5;
|
69
|
+
unsigned type: EVOASM_X64_OPERAND_TYPE_BITSIZE;
|
70
|
+
unsigned size: EVOASM_OPERAND_SIZE_BITSIZE_WITH_N;
|
71
|
+
unsigned reg_id: EVOASM_X64_REG_BITSIZE_WITH_N;
|
72
|
+
unsigned reg_type: EVOASM_X64_REG_TYPE_BITSIZE_WITH_N;
|
73
|
+
unsigned acc_w_mask: EVOASM_X64_BIT_MASK_BITSIZE;
|
74
|
+
} evoasm_x64_operand;
|
75
|
+
|
76
|
+
typedef struct {
|
77
|
+
evoasm_inst base;
|
78
|
+
uint64_t features;
|
79
|
+
evoasm_x64_operand *operands;
|
80
|
+
uint8_t n_operands;
|
81
|
+
uint32_t exceptions;
|
82
|
+
uint32_t flags;
|
83
|
+
} evoasm_x64_inst;
|
84
|
+
|
85
|
+
#define EVOASM_X64_ENC(inst) \
|
86
|
+
EVOASM_TRY(enc_failed, evoasm_x64_##inst, x64, params.vals, (evoasm_bitmap *) ¶ms.set)
|
87
|
+
|
88
|
+
#define EVOASM_X64_SET(param, val) \
|
89
|
+
evoasm_arch_params_set(params.vals, (evoasm_bitmap *) ¶ms.set, param, val)
|
90
|
+
|
91
|
+
#define EVOASM_X64_UNSET(param) \
|
92
|
+
evoasm_arch_params_unset(params.vals, (evoasm_bitmap *) ¶ms.set, param)
|
93
|
+
|
94
|
+
typedef enum {
|
95
|
+
EVOASM_X64_ABI_SYSV
|
96
|
+
} evoasm_x64_abi;
|
97
|
+
|
98
|
+
void
|
99
|
+
evoasm_x64_destroy(evoasm_x64 *x64);
|
100
|
+
|
101
|
+
evoasm_success
|
102
|
+
evoasm_x64_init(evoasm_x64 *x64);
|
103
|
+
|
104
|
+
evoasm_success
|
105
|
+
evoasm_x64_func_prolog(evoasm_x64 *x64, evoasm_buf *buf, evoasm_x64_abi abi);
|
106
|
+
|
107
|
+
evoasm_success
|
108
|
+
evoasm_x64_func_epilog(evoasm_x64 *x64, evoasm_buf *buf, evoasm_x64_abi abi);
|
109
|
+
|
110
|
+
const evoasm_x64_inst *
|
111
|
+
evoasm_x64_get_inst(evoasm_x64 *x64, unsigned index, bool ignore_features);
|
112
|
+
|
113
|
+
<% insts.each do |inst| %>
|
114
|
+
<%= func_prototype_to_c(inst.name, static: false) %>;
|
115
|
+
<% end %>
|
116
|
+
<% if options[:ruby] %>
|
117
|
+
|
118
|
+
#include <ruby.h>
|
119
|
+
|
120
|
+
extern ID *rb_x64_inst_ids;
|
121
|
+
extern ID *rb_x64_reg_ids;
|
122
|
+
extern ID *rb_x64_param_ids;
|
123
|
+
extern ID *rb_x64_operand_type_ids;
|
124
|
+
extern ID *rb_x64_reg_type_ids;
|
125
|
+
void evoasm_x64_ruby_define_consts();
|
126
|
+
<% end %>
|
data/evoasm.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'evoasm/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "evoasm"
|
8
|
+
spec.version = Evoasm::VERSION
|
9
|
+
spec.authors = ["Julian Aron Prenner (furunkel)"]
|
10
|
+
spec.email = ["furunkel@polyadic.com"]
|
11
|
+
spec.summary = %q{An AIMGP (Automatic Induction of Machine code by Genetic Programming) engine}
|
12
|
+
spec.homepage = "https://github.com/furunkel/evoasm/"
|
13
|
+
spec.license = "MPL-2.0"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.bindir = 'exe'
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
spec.extensions = spec.files.grep(%r{extconf.rb})
|
21
|
+
|
22
|
+
spec.add_dependency "pry", "~> 0.10"
|
23
|
+
spec.add_dependency "pastel", "~> 0.6"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.7"
|
26
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
27
|
+
spec.add_development_dependency "rake-compiler", "~> 0.9"
|
28
|
+
spec.add_development_dependency 'erubis', '~> 2.6'
|
29
|
+
spec.add_development_dependency "minitest", "~> 5.8"
|
30
|
+
end
|
data/examples/abs.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
instructions:
|
2
|
+
grep_v: cmov
|
3
|
+
reg_types: [gp]
|
4
|
+
examples:
|
5
|
+
1: 1
|
6
|
+
-1: 1
|
7
|
+
2: 2
|
8
|
+
-2: 2
|
9
|
+
100: 100
|
10
|
+
-100: 100
|
11
|
+
23: 23
|
12
|
+
1024: 1024
|
13
|
+
-1024: 1024
|
14
|
+
200000: 200000
|
15
|
+
-200000: 200000
|
16
|
+
1234: 1234
|
17
|
+
-1234: 1234
|
18
|
+
|
19
|
+
program_size: 1..5
|
20
|
+
population_size: 1600
|
data/examples/popcnt.yml
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
instructions:
|
2
|
+
reg_types: [xmm]
|
3
|
+
grep: (add|mul|sqrt).*?sd
|
4
|
+
# sqrt(x**3 + 2 * x)
|
5
|
+
examples:
|
6
|
+
0.0: 0.0
|
7
|
+
0.5: 1.0606601717798212
|
8
|
+
1.0: 1.7320508075688772
|
9
|
+
1.5: 2.5248762345905194
|
10
|
+
2.0: 3.4641016151377544
|
11
|
+
2.5: 4.541475531146237
|
12
|
+
3.0: 5.744562646538029
|
13
|
+
3.5: 7.0622234459127675
|
14
|
+
4.0: 8.48528137423857
|
15
|
+
4.5: 10.00624804809475
|
16
|
+
5.0: 11.61895003862225
|
17
|
+
kernel_size: 5..15
|
18
|
+
program_size: 1
|
19
|
+
population_size: 1600
|
20
|
+
max_loss: 0.0
|
21
|
+
parameters: [reg0, reg1, reg2, reg3]
|
22
|
+
domains:
|
23
|
+
reg0: ®s [XMM0, XMM1, XMM2, XMM3]
|
24
|
+
reg1: *regs
|
25
|
+
reg2: *regs
|
26
|
+
reg3: *regs
|
data/exe/evoasm-search
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# filetype=ruby
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'evoasm'
|
6
|
+
require 'evoasm/cli'
|
7
|
+
rescue LoadError
|
8
|
+
$LOAD_PATH.unshift File.expand_path File.join(__dir__, '../lib')
|
9
|
+
retry
|
10
|
+
end
|
11
|
+
|
12
|
+
search = Evoasm::Cli::Search.new ARGV[0], ARGV[1..-1]
|
13
|
+
search.start!
|
@@ -0,0 +1,145 @@
|
|
1
|
+
#include "evoasm-alloc.h"
|
2
|
+
|
3
|
+
#include <stdlib.h>
|
4
|
+
#include <errno.h>
|
5
|
+
|
6
|
+
void *
|
7
|
+
evoasm_malloc(size_t size) {
|
8
|
+
void *ptr = malloc(size);
|
9
|
+
if(EVOASM_UNLIKELY(!ptr)) {
|
10
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
11
|
+
NULL, "Allocationg %zu bytes via malloc failed", size);
|
12
|
+
return NULL;
|
13
|
+
}
|
14
|
+
return ptr;
|
15
|
+
}
|
16
|
+
|
17
|
+
void *
|
18
|
+
evoasm_calloc(size_t n, size_t size) {
|
19
|
+
void *ptr = calloc(n, size);
|
20
|
+
|
21
|
+
if(EVOASM_UNLIKELY(!ptr)) {
|
22
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
23
|
+
NULL, "Allocationg %zux%zu () bytes via calloc failed", n, size, n * size);
|
24
|
+
return NULL;
|
25
|
+
}
|
26
|
+
return ptr;
|
27
|
+
}
|
28
|
+
|
29
|
+
void *
|
30
|
+
evoasm_realloc(void *ptr, size_t size) {
|
31
|
+
void *new_ptr = realloc(ptr, size);
|
32
|
+
|
33
|
+
if(EVOASM_UNLIKELY(!ptr)) {
|
34
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
35
|
+
NULL, "Allocating %zu bytes via realloc failed", size);
|
36
|
+
return NULL;
|
37
|
+
}
|
38
|
+
return new_ptr;
|
39
|
+
}
|
40
|
+
|
41
|
+
void
|
42
|
+
evoasm_free(void *ptr) {
|
43
|
+
free(ptr);
|
44
|
+
}
|
45
|
+
|
46
|
+
void *
|
47
|
+
evoasm_mmap(size_t size, void *p) {
|
48
|
+
/* Note that mmap considers the pointer passed soley as a hint address
|
49
|
+
* and returns a valid address (possibly at a different address) in any case.
|
50
|
+
* VirtualAlloc, on the other hand, will return NULL if the address is
|
51
|
+
* not available
|
52
|
+
*/
|
53
|
+
void *mem;
|
54
|
+
|
55
|
+
#if defined(_WIN32)
|
56
|
+
retry:
|
57
|
+
mem = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
|
58
|
+
if(mem == NULL) {
|
59
|
+
if(p != NULL) {
|
60
|
+
goto retry;
|
61
|
+
} else {
|
62
|
+
goto error;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
return mem;
|
66
|
+
#elif defined(_POSIX_VERSION)
|
67
|
+
mem = mmap(p, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
68
|
+
if(mem == MAP_FAILED) {
|
69
|
+
goto error;
|
70
|
+
}
|
71
|
+
#else
|
72
|
+
#error
|
73
|
+
#endif
|
74
|
+
return mem;
|
75
|
+
|
76
|
+
error:
|
77
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
78
|
+
NULL, "Allocationg %zu bytes via mmap failed: %s", size, strerror(errno));
|
79
|
+
return NULL;
|
80
|
+
}
|
81
|
+
|
82
|
+
evoasm_success
|
83
|
+
evoasm_munmap(void *p, size_t size) {
|
84
|
+
bool ret;
|
85
|
+
#if defined(_WIN32)
|
86
|
+
ret = VirtualFree(p, size, MEM_DECOMMIT);
|
87
|
+
#elif defined(_POSIX_VERSION)
|
88
|
+
ret = (munmap(p, size) == 0);
|
89
|
+
#else
|
90
|
+
# error
|
91
|
+
#endif
|
92
|
+
|
93
|
+
if(!ret) {
|
94
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
95
|
+
NULL, "Unmapping %zu bytes via munmap failed: %s", size, strerror(errno));
|
96
|
+
}
|
97
|
+
|
98
|
+
return ret;
|
99
|
+
}
|
100
|
+
|
101
|
+
evoasm_success
|
102
|
+
evoasm_mprot(void *p, size_t size, int mode)
|
103
|
+
{
|
104
|
+
|
105
|
+
#if defined(_WIN32)
|
106
|
+
if(VirtualProtect(p, size, mode, NULL) != 0) {
|
107
|
+
goto error;
|
108
|
+
}
|
109
|
+
#elif defined(_POSIX_VERSION)
|
110
|
+
if(mprotect(p, size, mode) != 0) {
|
111
|
+
goto error;
|
112
|
+
}
|
113
|
+
#else
|
114
|
+
#error
|
115
|
+
#endif
|
116
|
+
return true;
|
117
|
+
|
118
|
+
error:
|
119
|
+
evoasm_set_error(EVOASM_ERROR_TYPE_MEMORY, EVOASM_ERROR_CODE_NONE,
|
120
|
+
NULL, "Changing memory protection failed: %s", strerror(errno));
|
121
|
+
return false;
|
122
|
+
}
|
123
|
+
|
124
|
+
static long _evoasm_page_size = -1;
|
125
|
+
|
126
|
+
static long
|
127
|
+
evoasm_query_page_size() {
|
128
|
+
#if defined(_WIN32)
|
129
|
+
SYSTEM_INFO si;
|
130
|
+
GetSystemInfo(&si);
|
131
|
+
return si.dwPageSize;
|
132
|
+
#elif defined(_POSIX_VERSION)
|
133
|
+
return sysconf(_SC_PAGESIZE);
|
134
|
+
#else
|
135
|
+
#error
|
136
|
+
#endif
|
137
|
+
}
|
138
|
+
|
139
|
+
long
|
140
|
+
evoasm_page_size() {
|
141
|
+
if(_evoasm_page_size == -1) {
|
142
|
+
_evoasm_page_size = evoasm_query_page_size();
|
143
|
+
}
|
144
|
+
return _evoasm_page_size;
|
145
|
+
}
|