37 _mod(mod), _code_segment_base(alloc.start_code()) {
38 const std::size_t code_size = 4 * 16;
40 _code_end = _code_start + code_size;
44 fpe_handler = emit_error_handler(&on_fp_error);
45 call_indirect_handler = emit_error_handler(&on_call_indirect_error);
46 type_error_handler = emit_error_handler(&on_type_error);
47 stack_overflow_handler = emit_error_handler(&on_stack_overflow);
49 assert(code == _code_end);
53 const std::size_t host_functions_size = (40 + 10 * Context::async_backtrace()) * num_imported;
54 _code_start = _mod.
allocator.
alloc<
unsigned char>(host_functions_size);
55 _code_end = _code_start + host_functions_size;
57 for(
uint32_t i = 0; i < num_imported; ++i) {
61 assert(code == _code_end);
64 if (_mod.
tables.size() > 0) {
68 _table_element_size = 17;
69 const std::size_t table_size = _table_element_size*_mod.
tables[0].table.size();
71 _code_end = _code_start + table_size;
77 emit_bytes(0x81, 0xfa);
80 emit_bytes(0x0f, 0x84);
84 fix_branch(emit_branch_target32(), type_error_handler);
89 fix_branch(emit_branch_target32(), call_indirect_handler);
91 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
92 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
93 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
96 assert(code == _code_end);
106 const std::size_t instruction_size_ratio_upper_bound =
use_softfloat?(Context::async_backtrace()?63:49):79;
109 _code_end = _code_start + code_size;
115 emit_bytes(0x48, 0x89, 0xe5);
122 _local_count =
count;
123 if (_local_count > 0) {
125 emit_bytes(0x48, 0x31, 0xc0);
126 if (_local_count > 14) {
129 emit_operand32(_local_count);
135 emit_bytes(0xff, 0xc9);
137 emit_bytes(0x0f, 0x85);
140 for (
uint32_t i = 0; i < _local_count; ++i) {
150 void * epilogue_start = code;
156 if (_local_count & 0xF0000000u) unimplemented();
157 emit_multipop(_local_count);
166 auto icount = fixed_size_instr(16);
167 emit_error_handler(&on_unreachable);
178 auto icount = fixed_size_instr(9);
182 emit_bytes(0x85, 0xC0);
184 emit_bytes(0x0F, 0x84);
185 return emit_branch_target32();
188 auto icount = fixed_size_instr(5);
194 auto icount = variable_size_instr(5, 17);
196 emit_multipop(depth_change);
199 return emit_branch_target32();
202 auto icount = variable_size_instr(9, 26);
206 emit_bytes(0x85, 0xC0);
208 if(depth_change == 0u || depth_change == 0x80000001u) {
210 emit_bytes(0x0F, 0x85);
211 return emit_branch_target32();
214 emit_bytes(0x0f, 0x84);
215 void* skip = emit_branch_target32();
217 emit_multipop(depth_change);
220 void* result = emit_branch_target32();
231 assert(!
stack.empty() &&
"The parser is supposed to handle the number of elements in br_table.");
241 _this->emit_bytes(0x3d);
242 _this->emit_operand32(mid);
244 _this->emit_bytes(0x0f, 0x83);
245 void* mid_label =
_this->emit_branch_target32();
246 stack.push_back({mid,max,mid_label});
251 if (depth_change == 0u || depth_change == 0x80000001u) {
256 _this->emit_bytes(0xe9);
257 return _this->emit_branch_target32();
261 _this->emit_multipop(depth_change);
263 _this->emit_bytes(0xe9);
264 return _this->emit_branch_target32();
272 assert(
stack.empty() &&
"unexpected default.");
285 std::vector<stack_item>
stack;
293 return {
this, 0, { {0, table_size+1,
nullptr} } };
297 auto& vec = _function_relocations;
298 if(funcnum >= vec.size()) vec.resize(funcnum + 1);
299 if(
void** addr = std::get_if<void*>(&vec[funcnum])) {
302 std::get<std::vector<void*>>(vec[funcnum]).push_back(ptr);
306 auto& vec = _function_relocations;
307 if(funcnum >= vec.size()) vec.resize(funcnum + 1);
308 for(
void* branch : std::get<std::vector<void*>>(vec[funcnum])) {
311 vec[funcnum] = func_start;
315 auto icount = variable_size_instr(15, 23);
316 emit_check_call_depth();
319 void * branch = emit_branch_target32();
325 emit_check_call_depth_end();
329 auto icount = variable_size_instr(43, 51);
330 emit_check_call_depth();
331 auto& table = _mod.
tables[0].table;
336 emit_bytes(0x48, 0x3d);
337 emit_operand32(table.size());
339 emit_bytes(0x0f, 0x83);
340 fix_branch(emit_branch_target32(), call_indirect_handler);
342 emit_bytes(0x48, 0x8d, 0x15);
343 fix_branch(emit_branch_target32(), jmp_table);
345 assert(_table_element_size <= 127);
346 emit_bytes(0x6b, 0xc0, _table_element_size);
348 emit_bytes(0x48, 0x01, 0xd0);
351 emit_operand32(functypeidx);
353 emit_bytes(0xff, 0xd0);
358 emit_check_call_depth_end();
367 auto icount = fixed_size_instr(13);
373 emit_bytes(0x85, 0xc0);
375 emit_bytes(0x48, 0x0f, 0x45, 0x0c, 0x24);
377 emit_bytes(0x48, 0x89, 0x0c, 0x24);
381 auto icount = fixed_size_instr(8);
394 if (local_idx < _ft->param_types.size()) {
396 emit_bytes(0x48, 0x8b, 0x85);
397 emit_operand32(8 * (_ft->
param_types.size() - local_idx + 1));
402 emit_bytes(0x48, 0x8b, 0x85);
403 emit_operand32(-8 * (local_idx - _ft->
param_types.size() + 1));
410 auto icount = fixed_size_instr(8);
411 if (local_idx < _ft->param_types.size()) {
415 emit_bytes(0x48, 0x89, 0x85);
416 emit_operand32(8 * (_ft->
param_types.size() - local_idx + 1));
421 emit_bytes(0x48, 0x89, 0x85);
422 emit_operand32(-8 * (local_idx - _ft->
param_types.size() + 1));
427 auto icount = fixed_size_instr(9);
428 if (local_idx < _ft->param_types.size()) {
434 emit_bytes(0x48, 0x89, 0x85);
435 emit_operand32(8 * (_ft->
param_types.size() - local_idx + 1));
442 emit_bytes(0x48, 0x89, 0x85);
443 emit_operand32(-8 * (local_idx - _ft->
param_types.size() + 1));
448 auto icount = variable_size_instr(13, 14);
449 auto& gl = _mod.
globals[globalidx];
450 void *ptr = &gl.current.value;
451 switch(gl.type.content_type) {
455 emit_bytes(0x48, 0xb8);
456 emit_operand_ptr(ptr);
458 emit_bytes(0x8b, 0x00);
465 emit_bytes(0x48, 0xb8);
466 emit_operand_ptr(ptr);
468 emit_bytes(0x48, 0x8b, 0x00);
475 auto icount = fixed_size_instr(14);
476 auto& gl = _mod.
globals[globalidx];
477 void *ptr = &gl.current.value;
481 emit_bytes(0x48, 0xb8);
482 emit_operand_ptr(ptr);
484 emit_bytes(0x48, 0x89, 0x08);
488 auto icount = variable_size_instr(7, 15);
490 emit_load_impl(offset, 0x8b, 0x00);
494 auto icount = variable_size_instr(8, 16);
496 emit_load_impl(offset, 0x48, 0x8b, 0x00);
500 auto icount = variable_size_instr(7, 15);
502 emit_load_impl(offset, 0x8b, 0x00);
506 auto icount = variable_size_instr(8, 16);
508 emit_load_impl(offset, 0x48, 0x8b, 0x00);
512 auto icount = variable_size_instr(8, 16);
514 emit_load_impl(offset, 0x0F, 0xbe, 0x00);
518 auto icount = variable_size_instr(8, 16);
520 emit_load_impl(offset, 0x0F, 0xbf, 0x00);
524 auto icount = variable_size_instr(8, 16);
526 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
530 auto icount = variable_size_instr(8, 16);
532 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
536 auto icount = variable_size_instr(9, 17);
538 emit_load_impl(offset, 0x48, 0x0F, 0xbe, 0x00);
542 auto icount = variable_size_instr(9, 17);
544 emit_load_impl(offset, 0x48, 0x0F, 0xbf, 0x00);
548 auto icount = variable_size_instr(8, 16);
550 emit_load_impl(offset, 0x48, 0x63, 0x00);
554 auto icount = variable_size_instr(8, 16);
556 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
560 auto icount = variable_size_instr(8, 16);
562 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
566 auto icount = variable_size_instr(7, 15);
568 emit_load_impl(offset, 0x8b, 0x00);
572 auto icount = variable_size_instr(7, 15);
574 emit_store_impl(offset, 0x89, 0x08);
578 auto icount = variable_size_instr(8, 16);
580 emit_store_impl(offset, 0x48, 0x89, 0x08);
584 auto icount = variable_size_instr(7, 15);
586 emit_store_impl(offset, 0x89, 0x08);
590 auto icount = variable_size_instr(8, 16);
592 emit_store_impl(offset, 0x48, 0x89, 0x08);
596 auto icount = variable_size_instr(7, 15);
598 emit_store_impl(offset, 0x88, 0x08);
602 auto icount = variable_size_instr(8, 16);
604 emit_store_impl(offset, 0x66, 0x89, 0x08);
608 auto icount = variable_size_instr(7, 15);
610 emit_store_impl(offset, 0x88, 0x08);
614 auto icount = variable_size_instr(8, 16);
616 emit_store_impl(offset, 0x66, 0x89, 0x08);
620 auto icount = variable_size_instr(7, 15);
622 emit_store_impl(offset, 0x89, 0x08);
626 auto icount = variable_size_instr(17, 35);
627 emit_setup_backtrace();
633 emit_bytes(0x48, 0xb8);
634 emit_operand_ptr(¤t_memory);
636 emit_bytes(0xff, 0xd0);
641 emit_restore_backtrace();
646 auto icount = variable_size_instr(21, 39);
649 emit_setup_backtrace();
655 emit_bytes(0x48, 0x89, 0xc6);
657 emit_bytes(0x48, 0xb8);
658 emit_operand_ptr(&grow_memory);
660 emit_bytes(0xff, 0xd0);
665 emit_restore_backtrace();
671 auto icount = fixed_size_instr(6);
674 emit_operand32(
value);
680 auto icount = fixed_size_instr(11);
682 emit_bytes(0x48, 0xb8);
683 emit_operand64(
value);
689 auto icount = fixed_size_instr(6);
692 emit_operandf32(
value);
697 auto icount = fixed_size_instr(11);
699 emit_bytes(0x48, 0xb8);
700 emit_operandf64(
value);
706 auto icount = fixed_size_instr(10);
710 emit_bytes(0x48, 0x31, 0xc9);
712 emit_bytes(0x85, 0xc0);
714 emit_bytes(0x0f, 0x94, 0xc1);
721 auto icount = fixed_size_instr(11);
723 emit_i32_relop(0x94);
727 auto icount = fixed_size_instr(11);
729 emit_i32_relop(0x95);
733 auto icount = fixed_size_instr(11);
735 emit_i32_relop(0x9c);
739 auto icount = fixed_size_instr(11);
741 emit_i32_relop(0x92);
745 auto icount = fixed_size_instr(11);
747 emit_i32_relop(0x9f);
751 auto icount = fixed_size_instr(11);
753 emit_i32_relop(0x97);
757 auto icount = fixed_size_instr(11);
759 emit_i32_relop(0x9e);
763 auto icount = fixed_size_instr(11);
765 emit_i32_relop(0x96);
769 auto icount = fixed_size_instr(11);
771 emit_i32_relop(0x9d);
775 auto icount = fixed_size_instr(11);
777 emit_i32_relop(0x93);
781 auto icount = fixed_size_instr(11);
785 emit_bytes(0x48, 0x31, 0xc9);
787 emit_bytes(0x48, 0x85, 0xc0);
789 emit_bytes(0x0f, 0x94, 0xc1);
795 auto icount = fixed_size_instr(12);
797 emit_i64_relop(0x94);
801 auto icount = fixed_size_instr(12);
803 emit_i64_relop(0x95);
807 auto icount = fixed_size_instr(12);
809 emit_i64_relop(0x9c);
813 auto icount = fixed_size_instr(12);
815 emit_i64_relop(0x92);
819 auto icount = fixed_size_instr(12);
821 emit_i64_relop(0x9f);
825 auto icount = fixed_size_instr(12);
827 emit_i64_relop(0x97);
831 auto icount = fixed_size_instr(12);
833 emit_i64_relop(0x9e);
837 auto icount = fixed_size_instr(12);
839 emit_i64_relop(0x96);
843 auto icount = fixed_size_instr(12);
845 emit_i64_relop(0x9d);
849 auto icount = fixed_size_instr(12);
851 emit_i64_relop(0x93);
854#ifdef SYS_VM_SOFTFLOAT
856 static uint64_t adapt_result(
bool val) {
861 std::memcpy(&result, &val,
sizeof(
float32_t));
869 static auto adapt_f32_unop(
float32_t arg) {
882 static auto adapt_f64_unop(
float64_t arg) {
894 static float32_t to_softfloat(
float arg) { return ::to_softfloat32(arg); }
895 static float64_t to_softfloat(
double arg) { return ::to_softfloat64(arg); }
897 static T to_softfloat(
T arg) {
return arg; }
898 static float from_softfloat(
float32_t arg) { return ::from_softfloat32(arg); }
899 static double from_softfloat(
float64_t arg) { return ::from_softfloat64(arg); }
901 static T from_softfloat(
T arg) {
return arg; }
904 using softfloat_arg_t =
decltype(to_softfloat(
T{}));
906 template<auto F,
typename T>
907 static auto adapt_float_convert(softfloat_arg_t<T> arg) {
908 auto result = to_softfloat(F(from_softfloat(arg)));
909 if constexpr (
sizeof(result) == 4 &&
sizeof(
T) == 8) {
911 std::memcpy(&buffer, &result,
sizeof(result));
918 template<auto F,
typename R,
typename T>
919 static constexpr auto choose_unop(
R(*)(
T)) {
920 if constexpr(
sizeof(
R) == 4 &&
sizeof(
T) == 8) {
921 return static_cast<uint64_t(*)(softfloat_arg_t<T>)
>(&adapt_float_convert<F, T>);
923 return static_cast<softfloat_arg_t<R>(*)(softfloat_arg_t<T>)
>(&adapt_float_convert<F, T>);
931 constexpr auto choose_fn() {
933 if constexpr (std::is_same_v<
decltype(F), float(*)(float)>) {
934 return &adapt_f32_unop<F>;
935 }
else if constexpr(std::is_same_v<
decltype(F), float(*)(float,float)>) {
936 return &adapt_f32_binop<F>;
937 }
else if constexpr(std::is_same_v<
decltype(F), bool(*)(float,float)>) {
938 return &adapt_f32_cmp<F>;
939 }
else if constexpr (std::is_same_v<
decltype(F), double(*)(double)>) {
940 return &adapt_f64_unop<F>;
941 }
else if constexpr(std::is_same_v<
decltype(F), double(*)(double,double)>) {
942 return &adapt_f64_binop<F>;
943 }
else if constexpr(std::is_same_v<
decltype(F), bool(*)(double,double)>) {
944 return &adapt_f64_cmp<F>;
946 return choose_unop<F>(F);
953 template<
auto F,
typename R,
typename...
A>
954 static R softfloat_trap_fn(
A...
a) {
962 template<
auto F,
typename R,
typename...
A>
963 static constexpr auto make_softfloat_trap_fn(
R(*)(
A...)) ->
R(*)(
A...) {
964 return softfloat_trap_fn<F,
R,
A...>;
968 static constexpr decltype(
auto) softfloat_trap() {
969 return *make_softfloat_trap_fn<F>(F);
972 #define CHOOSE_FN(name) choose_fn<&name>()
976 #define CHOOSE_FN(name) nullptr
981 auto icount = softfloat_instr(25,45,59);
982 emit_f32_relop(0x00,
CHOOSE_FN(_sysio_f32_eq),
false,
false);
986 auto icount = softfloat_instr(24,47,61);
987 emit_f32_relop(0x00,
CHOOSE_FN(_sysio_f32_eq),
false,
true);
991 auto icount = softfloat_instr(25,45,59);
992 emit_f32_relop(0x01,
CHOOSE_FN(_sysio_f32_lt),
false,
false);
996 auto icount = softfloat_instr(25,45,59);
997 emit_f32_relop(0x01,
CHOOSE_FN(_sysio_f32_lt),
true,
false);
1001 auto icount = softfloat_instr(25,45,59);
1002 emit_f32_relop(0x02,
CHOOSE_FN(_sysio_f32_le),
false,
false);
1006 auto icount = softfloat_instr(25,45,59);
1007 emit_f32_relop(0x02,
CHOOSE_FN(_sysio_f32_le),
true,
false);
1012 auto icount = softfloat_instr(25,47,61);
1013 emit_f64_relop(0x00,
CHOOSE_FN(_sysio_f64_eq),
false,
false);
1017 auto icount = softfloat_instr(24,49,63);
1018 emit_f64_relop(0x00,
CHOOSE_FN(_sysio_f64_eq),
false,
true);
1022 auto icount = softfloat_instr(25,47,61);
1023 emit_f64_relop(0x01,
CHOOSE_FN(_sysio_f64_lt),
false,
false);
1027 auto icount = softfloat_instr(25,47,61);
1028 emit_f64_relop(0x01,
CHOOSE_FN(_sysio_f64_lt),
true,
false);
1032 auto icount = softfloat_instr(25,47,61);
1033 emit_f64_relop(0x02,
CHOOSE_FN(_sysio_f64_le),
false,
false);
1037 auto icount = softfloat_instr(25,47,61);
1038 emit_f64_relop(0x02,
CHOOSE_FN(_sysio_f64_le),
true,
false);
1044 unsigned a, b, c,
d;
1045 return __get_cpuid_count(7, 0, &
a, &b, &c, &
d) && (b & bit_BMI) &&
1046 __get_cpuid(0x80000001, &
a, &b, &c, &
d) && (c & bit_LZCNT);
1055 auto icount = fixed_size_instr(
has_tzcnt()?6:18);
1060 emit_bytes(0xb9, 0xff, 0xff, 0xff, 0xff);
1062 emit_bytes(0x0f, 0xbd, 0xc0);
1064 emit_bytes(0x0f, 0x44, 0xc1);
1066 emit_bytes(0x83, 0xe8, 0x1f);
1068 emit_bytes(0xf7, 0xd8);
1075 emit_bytes(0xf3, 0x0f, 0xbd, 0xc0);
1082 auto icount = fixed_size_instr(
has_tzcnt()?6:13);
1087 emit_bytes(0xb9, 0x20, 0x00, 0x00, 0x00);
1089 emit_bytes(0x0f, 0xbc, 0xc0);
1091 emit_bytes(0x0f, 0x44, 0xc1);
1098 emit_bytes(0xf3, 0x0f, 0xbc, 0xc0);
1105 auto icount = fixed_size_instr(6);
1109 emit_bytes(0xf3, 0x0f, 0xb8, 0xc0);
1117 auto icount = fixed_size_instr(5);
1118 emit_i32_binop(0x01, 0xc8, 0x50);
1121 auto icount = fixed_size_instr(5);
1122 emit_i32_binop(0x29, 0xc8, 0x50);
1125 auto icount = fixed_size_instr(6);
1126 emit_i32_binop(0x0f, 0xaf, 0xc1, 0x50);
1130 auto icount = fixed_size_instr(6);
1131 emit_i32_binop(0x99, 0xf7, 0xf9, 0x50);
1134 auto icount = fixed_size_instr(7);
1135 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x50);
1138 auto icount = fixed_size_instr(22);
1144 emit_bytes(0x83, 0xf9, 0xff);
1146 emit_bytes(0x0f, 0x84);
1147 void* minus1 = emit_branch_target32();
1151 emit_bytes(0xf7, 0xf9);
1154 void* end = emit_branch_target32();
1158 emit_bytes(0x31, 0xd2);
1165 auto icount = fixed_size_instr(7);
1166 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x52);
1169 auto icount = fixed_size_instr(5);
1170 emit_i32_binop(0x21, 0xc8, 0x50);
1173 auto icount = fixed_size_instr(5);
1174 emit_i32_binop(0x09, 0xc8, 0x50);
1177 auto icount = fixed_size_instr(5);
1178 emit_i32_binop(0x31, 0xc8, 0x50);
1181 auto icount = fixed_size_instr(5);
1182 emit_i32_binop(0xd3, 0xe0, 0x50);
1185 auto icount = fixed_size_instr(5);
1186 emit_i32_binop(0xd3, 0xf8, 0x50);
1189 auto icount = fixed_size_instr(5);
1190 emit_i32_binop(0xd3, 0xe8, 0x50);
1193 auto icount = fixed_size_instr(5);
1194 emit_i32_binop(0xd3, 0xc0, 0x50);
1197 auto icount = fixed_size_instr(5);
1198 emit_i32_binop(0xd3, 0xc8, 0x50);
1204 auto icount = fixed_size_instr(
has_tzcnt()?7:24);
1209 emit_bytes(0x48, 0xc7, 0xc1, 0xff, 0xff, 0xff, 0xff);
1211 emit_bytes(0x48, 0x0f, 0xbd, 0xc0);
1213 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1215 emit_bytes(0x48, 0x83, 0xe8, 0x3f);
1217 emit_bytes(0x48, 0xf7, 0xd8);
1224 emit_bytes(0xf3, 0x48, 0x0f, 0xbd, 0xc0);
1231 auto icount = fixed_size_instr(
has_tzcnt()?7:17);
1236 emit_bytes(0x48, 0xc7, 0xc1, 0x40, 0x00, 0x00, 0x00);
1238 emit_bytes(0x48, 0x0f, 0xbc, 0xc0);
1240 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1247 emit_bytes(0xf3, 0x48, 0x0f, 0xbc, 0xc0);
1254 auto icount = fixed_size_instr(7);
1258 emit_bytes(0xf3, 0x48, 0x0f, 0xb8, 0xc0);
1266 auto icount = fixed_size_instr(6);
1267 emit_i64_binop(0x48, 0x01, 0xc8, 0x50);
1270 auto icount = fixed_size_instr(6);
1271 emit_i64_binop(0x48, 0x29, 0xc8, 0x50);
1274 auto icount = fixed_size_instr(7);
1275 emit_i64_binop(0x48, 0x0f, 0xaf, 0xc1, 0x50);
1279 auto icount = fixed_size_instr(8);
1280 emit_i64_binop(0x48, 0x99, 0x48, 0xf7, 0xf9, 0x50);
1283 auto icount = fixed_size_instr(9);
1284 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x50);
1287 auto icount = fixed_size_instr(25);
1293 emit_bytes(0x48, 0x83, 0xf9, 0xff);
1295 emit_bytes(0x0f, 0x84);
1296 void* minus1 = emit_branch_target32();
1298 emit_bytes(0x48, 0x99);
1300 emit_bytes(0x48, 0xf7, 0xf9);
1303 void* end = emit_branch_target32();
1307 emit_bytes(0x31, 0xd2);
1314 auto icount = fixed_size_instr(9);
1315 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x52);
1318 auto icount = fixed_size_instr(6);
1319 emit_i64_binop(0x48, 0x21, 0xc8, 0x50);
1322 auto icount = fixed_size_instr(6);
1323 emit_i64_binop(0x48, 0x09, 0xc8, 0x50);
1326 auto icount = fixed_size_instr(6);
1327 emit_i64_binop(0x48, 0x31, 0xc8, 0x50);
1330 auto icount = fixed_size_instr(6);
1331 emit_i64_binop(0x48, 0xd3, 0xe0, 0x50);
1334 auto icount = fixed_size_instr(6);
1335 emit_i64_binop(0x48, 0xd3, 0xf8, 0x50);
1338 auto icount = fixed_size_instr(6);
1339 emit_i64_binop(0x48, 0xd3, 0xe8, 0x50);
1342 auto icount = fixed_size_instr(6);
1343 emit_i64_binop(0x48, 0xd3, 0xc0, 0x50);
1346 auto icount = fixed_size_instr(6);
1347 emit_i64_binop(0x48, 0xd3, 0xc8, 0x50);
1353 auto icount = fixed_size_instr(7);
1358 emit_operand32(0x7fffffff);
1364 auto icount = fixed_size_instr(7);
1369 emit_operand32(0x80000000);
1375 auto icount = softfloat_instr(12, 36, 54);
1377 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_ceil));
1380 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0a);
1382 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1386 auto icount = softfloat_instr(12, 36, 54);
1388 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_floor));
1391 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x09);
1393 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1397 auto icount = softfloat_instr(12, 36, 54);
1399 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_trunc));
1402 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0b);
1404 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1408 auto icount = softfloat_instr(12, 36, 54);
1410 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_nearest));
1413 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x08);
1415 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1419 auto icount = softfloat_instr(10, 36, 54);
1421 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_sqrt));
1424 emit_bytes(0xf3, 0x0f, 0x51, 0x04, 0x24);
1426 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1432 auto icount = softfloat_instr(21, 44, 58);
1433 emit_f32_binop(0x58,
CHOOSE_FN(_sysio_f32_add));
1436 auto icount = softfloat_instr(21, 44, 58);
1437 emit_f32_binop(0x5c,
CHOOSE_FN(_sysio_f32_sub));
1440 auto icount = softfloat_instr(21, 44, 58);
1441 emit_f32_binop(0x59,
CHOOSE_FN(_sysio_f32_mul));
1444 auto icount = softfloat_instr(21, 44, 58);
1445 emit_f32_binop(0x5e,
CHOOSE_FN(_sysio_f32_div));
1448 auto icount = softfloat_instr(47, 44, 58);
1450 emit_f32_binop_softfloat(
CHOOSE_FN(_sysio_f32_min));
1454 emit_bytes(0x8b, 0x04, 0x24);
1456 emit_bytes(0x85, 0xc0);
1458 emit_bytes(0x0f, 0x84);
1459 void* zero = emit_branch_target32();
1461 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1463 emit_bytes(0xf3, 0x0f, 0x5d, 0x04, 0x24);
1466 void* done = emit_branch_target32();
1470 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1472 emit_bytes(0xf3, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1476 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1478 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1481 auto icount = softfloat_instr(47, 44, 58);
1483 emit_f32_binop_softfloat(
CHOOSE_FN(_sysio_f32_max));
1487 emit_bytes(0x8b, 0x04, 0x24);
1489 emit_bytes(0x85, 0xc0);
1491 emit_bytes(0x0f, 0x84);
1492 void* zero = emit_branch_target32();
1494 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1496 emit_bytes(0xf3, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1499 void* done = emit_branch_target32();
1503 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1505 emit_bytes(0xf3, 0x0f, 0x5f, 0x04, 0x24);
1509 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1511 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1515 auto icount = fixed_size_instr(16);
1520 emit_operand32(0x80000000);
1524 emit_bytes(0x81, 0xe1);
1525 emit_operand32(0x7fffffff);
1527 emit_bytes(0x09, 0xc8);
1535 auto icount = fixed_size_instr(15);
1539 emit_bytes(0x48, 0xb8);
1540 emit_operand64(0x7fffffffffffffffull);
1542 emit_bytes(0x48, 0x21, 0xc8);
1548 auto icount = fixed_size_instr(15);
1552 emit_bytes(0x48, 0xb8);
1553 emit_operand64(0x8000000000000000ull);
1555 emit_bytes(0x48, 0x31, 0xc8);
1561 auto icount = softfloat_instr(12, 38, 56);
1563 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_ceil));
1566 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0a);
1568 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1572 auto icount = softfloat_instr(12, 38, 56);
1574 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_floor));
1577 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x09);
1579 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1583 auto icount = softfloat_instr(12, 38, 56);
1585 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_trunc));
1588 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0b);
1590 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1594 auto icount = softfloat_instr(12, 38, 56);
1596 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_nearest));
1599 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x08);
1601 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1605 auto icount = softfloat_instr(10, 38, 56);
1607 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_sqrt));
1610 emit_bytes(0xf2, 0x0f, 0x51, 0x04, 0x24);
1612 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1618 auto icount = softfloat_instr(21, 47, 61);
1619 emit_f64_binop(0x58,
CHOOSE_FN(_sysio_f64_add));
1622 auto icount = softfloat_instr(21, 47, 61);
1623 emit_f64_binop(0x5c,
CHOOSE_FN(_sysio_f64_sub));
1626 auto icount = softfloat_instr(21, 47, 61);
1627 emit_f64_binop(0x59,
CHOOSE_FN(_sysio_f64_mul));
1630 auto icount = softfloat_instr(21, 47, 61);
1631 emit_f64_binop(0x5e,
CHOOSE_FN(_sysio_f64_div));
1634 auto icount = softfloat_instr(49, 47, 61);
1636 emit_f64_binop_softfloat(
CHOOSE_FN(_sysio_f64_min));
1640 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1642 emit_bytes(0x48, 0x85, 0xc0);
1644 emit_bytes(0x0f, 0x84);
1645 void* zero = emit_branch_target32();
1647 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1649 emit_bytes(0xf2, 0x0f, 0x5d, 0x04, 0x24);
1652 void* done = emit_branch_target32();
1656 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1658 emit_bytes(0xf2, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1662 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1664 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1667 auto icount = softfloat_instr(49, 47, 61);
1669 emit_f64_binop_softfloat(
CHOOSE_FN(_sysio_f64_max));
1673 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1675 emit_bytes(0x48, 0x85, 0xc0);
1677 emit_bytes(0x0f, 0x84);
1678 void* zero = emit_branch_target32();
1680 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1682 emit_bytes(0xf2, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1685 void* done = emit_branch_target32();
1689 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1691 emit_bytes(0xf2, 0x0f, 0x5f, 0x04, 0x24);
1695 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1697 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1701 auto icount = fixed_size_instr(25);
1705 emit_bytes(0x48, 0xb8);
1706 emit_operand64(0x8000000000000000ull);
1708 emit_bytes(0x48, 0x21, 0xc1);
1712 emit_bytes(0x48, 0xf7, 0xd0);
1714 emit_bytes(0x48, 0x21, 0xd0);
1716 emit_bytes(0x48, 0x09, 0xc8);
1725 auto icount = fixed_size_instr(6);
1728 emit_bytes(0x31, 0xc0);
1730 emit_bytes(0x89, 0x44, 0x24, 0x04);
1734 auto icount = softfloat_instr(33, 36, 54);
1736 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32s>()));
1739 emit_f2i(0xf3, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1741 emit_bytes(0x89, 0x04 ,0x24);
1745 auto icount = softfloat_instr(46, 36, 54);
1747 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32u>()));
1750 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1752 emit_bytes(0x89, 0x04 ,0x24);
1754 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1756 emit_bytes(0x85, 0xc0);
1758 emit_bytes(0x0f, 0x85);
1759 fix_branch(emit_branch_target32(), fpe_handler);
1762 auto icount = softfloat_instr(34, 38, 56);
1764 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32s>()));
1767 emit_f2i(0xf2, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1769 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1773 auto icount = softfloat_instr(47, 38, 56);
1775 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32u>()));
1778 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1780 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1782 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1784 emit_bytes(0x85, 0xc0);
1786 emit_bytes(0x0f, 0x85);
1787 fix_branch(emit_branch_target32(), fpe_handler);
1791 auto icount = fixed_size_instr(8);
1793 emit_bytes(0x48, 0x63, 0x04, 0x24);
1795 emit_bytes(0x48, 0x89, 0x04, 0x24);
1801 auto icount = softfloat_instr(35, 37, 55);
1803 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64s>()));
1806 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1808 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1811 auto icount = softfloat_instr(101, 37, 55);
1813 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64u>()));
1817 emit_operand32(0x5f000000);
1819 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1821 emit_bytes(0x89, 0x04, 0x24);
1823 emit_bytes(0xf3, 0x0f, 0x10, 0x0c, 0x24);
1825 emit_bytes(0x0f, 0x28, 0xd0);
1827 emit_bytes(0xf3, 0x0f, 0x5c, 0xd1);
1829 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0xc2);
1831 emit_bytes(0x48, 0xb9);
1832 emit_operand64(0x8000000000000000);
1834 emit_bytes(0x48, 0x31, 0xc1);
1836 emit_bytes(0xf3, 0x48, 0x0f, 0x2c, 0xc0);
1838 emit_bytes(0x48, 0x31, 0xd2);
1840 emit_bytes(0x0f, 0x2e, 0xc8);
1842 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1844 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1846 emit_bytes(0x48, 0x89, 0x04, 0x24);
1848 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1850 emit_bytes(0x0f, 0x82);
1851 fix_branch(emit_branch_target32(), fpe_handler);
1854 auto icount = softfloat_instr(35, 38, 56);
1856 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64s>()));
1859 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1861 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1864 auto icount = softfloat_instr(109, 38, 56);
1866 return emit_softfloat_unop(
CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64u>()));
1869 emit_bytes(0x48, 0xb8);
1870 emit_operand64(0x43e0000000000000);
1872 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1874 emit_bytes(0x48, 0x89, 0x04, 0x24);
1876 emit_bytes(0xf2, 0x0f, 0x10, 0x0c, 0x24);
1878 emit_bytes(0x66, 0x0f, 0x28, 0xd0);
1880 emit_bytes(0xf2, 0x0f, 0x5c, 0xd1);
1882 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0xc2);
1884 emit_bytes(0x48, 0xb9);
1885 emit_operand64(0x8000000000000000);
1887 emit_bytes(0x48, 0x31, 0xc1);
1889 emit_bytes(0xf2, 0x48, 0x0f, 0x2c, 0xc0);
1891 emit_bytes(0x48, 0x31, 0xd2);
1893 emit_bytes(0x66, 0x0f, 0x2e, 0xc8);
1895 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1897 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1899 emit_bytes(0x48, 0x89, 0x04, 0x24);
1901 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1903 emit_bytes(0x0f, 0x82);
1904 fix_branch(emit_branch_target32(), fpe_handler);
1908 auto icount = softfloat_instr(10, 36, 54);
1910 return emit_softfloat_unop(
CHOOSE_FN(_sysio_i32_to_f32));
1913 emit_bytes(0xf3, 0x0f, 0x2a, 0x04, 0x24);
1915 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1918 auto icount = softfloat_instr(11, 36, 54);
1920 return emit_softfloat_unop(
CHOOSE_FN(_sysio_ui32_to_f32));
1924 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1926 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1929 auto icount = softfloat_instr(11, 38, 56);
1931 return emit_softfloat_unop(
CHOOSE_FN(_sysio_i64_to_f32));
1934 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1936 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1939 auto icount = softfloat_instr(55, 38, 56);
1941 return emit_softfloat_unop(
CHOOSE_FN(_sysio_ui64_to_f32));
1944 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1946 emit_bytes(0x48, 0x85, 0xc0);
1948 emit_bytes(0x0f, 0x88);
1949 void * large = emit_branch_target32();
1951 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1954 void* done = emit_branch_target32();
1958 emit_bytes(0x48, 0x89, 0xc1);
1960 emit_bytes(0x48, 0xd1, 0xe8);
1962 emit_bytes(0x83, 0xe1, 0x01);
1964 emit_bytes(0x48, 0x09, 0xc8);
1966 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1968 emit_bytes(0xf3, 0x0f, 0x58, 0xc0);
1972 emit_bytes(0x31, 0xc0);
1974 emit_bytes(0x89, 0x44, 0x24, 0x04);
1976 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1979 auto icount = softfloat_instr(16, 38, 56);
1981 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f64_demote));
1984 emit_bytes(0xf2, 0x0f, 0x5a, 0x04, 0x24);
1986 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1989 emit_bytes(0x31, 0xc0);
1991 emit_bytes(0x89, 0x44, 0x24, 0x04);
1994 auto icount = softfloat_instr(10, 37, 55);
1996 return emit_softfloat_unop(
CHOOSE_FN(_sysio_i32_to_f64));
1999 emit_bytes(0xf2, 0x0f, 0x2a, 0x04, 0x24);
2001 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2004 auto icount = softfloat_instr(11, 37, 55);
2006 return emit_softfloat_unop(
CHOOSE_FN(_sysio_ui32_to_f64));
2009 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2011 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2014 auto icount = softfloat_instr(11, 38, 56);
2016 return emit_softfloat_unop(
CHOOSE_FN(_sysio_i64_to_f64));
2019 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2021 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2024 auto icount = softfloat_instr(49, 38, 56);
2026 return emit_softfloat_unop(
CHOOSE_FN(_sysio_ui64_to_f64));
2029 emit_bytes(0x48, 0x8b, 0x04, 0x24);
2031 emit_bytes(0x48, 0x85, 0xc0);
2033 emit_bytes(0x0f, 0x88);
2034 void * large = emit_branch_target32();
2036 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2039 void* done = emit_branch_target32();
2043 emit_bytes(0x48, 0x89, 0xc1);
2045 emit_bytes(0x48, 0xd1, 0xe8);
2047 emit_bytes(0x83, 0xe1, 0x01);
2049 emit_bytes(0x48, 0x09, 0xc8);
2051 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2053 emit_bytes(0xf2, 0x0f, 0x58, 0xc0);
2057 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2060 auto icount = softfloat_instr(10, 37, 55);
2062 return emit_softfloat_unop(
CHOOSE_FN(_sysio_f32_promote));
2065 emit_bytes(0xf3, 0x0f, 0x5a, 0x04, 0x24);
2067 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2081 auto branch_ =
static_cast<uint8_t*
>(branch);
2082 auto target_ =
static_cast<uint8_t*
>(target);
2083 auto relative =
static_cast<uint32_t>(target_ - (branch_ + 4));
2084 if((target_ - (branch_ + 4)) > 0x7FFFFFFFll ||
2085 (target_ - (branch_ + 4)) < -0x80000000ll) unimplemented();
2086 memcpy(branch, &relative, 4);
2092 memcpy(branch, &target, 8);
2098 body.
jit_code_offset = _code_start - (
unsigned char*)_code_segment_base;
2110 auto fixed_size_instr(std::size_t expected_bytes) {
2111 return scope_guard{[
this, expected_code=code+expected_bytes](){
2112#ifdef SYS_VM_VALIDATE_JIT_SIZE
2113 assert(code == expected_code);
2118 auto variable_size_instr(std::size_t
min, std::size_t max) {
2119 return scope_guard{[
this, min_code=code+
min,max_code=code+max](){
2120#ifdef SYS_VM_VALIDATE_JIT_SIZE
2121 assert(min_code <= code && code <= max_code);
2126 auto softfloat_instr(std::size_t hard_expected, std::size_t soft_expected, std::size_t softbt_expected) {
2127 return fixed_size_instr(
use_softfloat?(Context::async_backtrace()?softbt_expected:soft_expected):hard_expected);
2131 void * _code_segment_base;
2132 const func_type* _ft;
2133 unsigned char * _code_start;
2134 unsigned char * _code_end;
2135 unsigned char * code;
2136 std::vector<std::variant<std::vector<void*>,
void*>> _function_relocations;
2138 void* call_indirect_handler;
2139 void* type_error_handler;
2140 void* stack_overflow_handler;
2145 void emit_byte(
uint8_t val) { *code++ = val; }
2146 void emit_bytes() {}
2147 template<
class...
T>
2148 void emit_bytes(
uint8_t val0,
T... vals) {
2150 emit_bytes(vals...);
2152 void emit_operand32(
uint32_t val) {
memcpy(code, &val,
sizeof(val)); code +=
sizeof(val); }
2153 void emit_operand64(
uint64_t val) {
memcpy(code, &val,
sizeof(val)); code +=
sizeof(val); }
2154 void emit_operandf32(
float val) {
memcpy(code, &val,
sizeof(val)); code +=
sizeof(val); }
2155 void emit_operandf64(
double val) {
memcpy(code, &val,
sizeof(val)); code +=
sizeof(val); }
2157 void emit_operand_ptr(
T* val) {
memcpy(code, &val,
sizeof(val)); code +=
sizeof(val); }
2159 void* emit_branch_target32() {
2160 void * result = code;
2161 emit_operand32(3735928555u -
static_cast<uint32_t>(
reinterpret_cast<uintptr_t>(code)));
2165 void emit_check_call_depth() {
2167 emit_bytes(0xff, 0xcb);
2169 emit_bytes(0x0f, 0x84);
2170 fix_branch(emit_branch_target32(), stack_overflow_handler);
2172 void emit_check_call_depth_end() {
2174 emit_bytes(0xff, 0xc3);
2177 static void unimplemented() {
SYS_VM_ASSERT(
false, wasm_parse_exception,
"Sorry, not implemented."); }
2182 if (
count & 0x80000000) {
2184 emit_bytes(0x48, 0x8b, 0x04, 0x24);
2186 if(
count & 0x70000000) {
2192 emit_bytes(0x48, 0x81, 0xc4);
2193 emit_operand32(
count * 8);
2194 if (
count & 0x80000000) {
2201 template<
class...
T>
2202 void emit_load_impl(
uint32_t offset,
T... loadop) {
2205 if (offset & 0x80000000) {
2208 emit_operand32(offset);
2210 emit_bytes(0x48, 0x01, 0xc8);
2211 }
else if (offset != 0) {
2213 emit_bytes(0x48, 0x05);
2214 emit_operand32(offset);
2217 emit_bytes(0x48, 0x01, 0xf0);
2219 emit_bytes(
static_cast<uint8_t>(loadop)...);
2224 template<
class...
T>
2225 void emit_store_impl(
uint32_t offset,
T... storeop) {
2230 if (offset & 0x80000000) {
2233 emit_operand32(offset);
2235 emit_bytes(0x48, 0x01, 0xc8);
2236 }
else if (offset != 0) {
2238 emit_bytes(0x48, 0x05);
2239 emit_operand32(offset);
2242 emit_bytes(0x48, 0x01, 0xf0);
2244 emit_bytes(
static_cast<uint8_t>(storeop)...);;
2253 emit_bytes(0x48, 0x31, 0xd2);
2255 emit_bytes(0x39, 0xc1);
2257 emit_bytes(0x0f,
opcode, 0xc2);
2262 template<
class...
T>
2269 emit_bytes(0x48, 0x31, 0xd2);
2271 emit_bytes(0x48, 0x39, 0xc1);
2273 emit_bytes(0x0f,
opcode, 0xc2);
2278 template<
typename T,
typename U>
2279 void emit_softfloat_unop(
T(*softfloatfun)(
U)) {
2280 auto extra = emit_setup_backtrace();
2285 if constexpr(
sizeof(
U) == 4) {
2287 emit_bytes(0x8b, 0x7c, 0x24, 0x10 + extra);
2290 emit_bytes(0x48, 0x8b, 0x7c, 0x24, 0x10 + extra);
2294 emit_bytes(0x48, 0xb8);
2295 emit_operand_ptr(softfloatfun);
2297 emit_bytes(0xff, 0xd0);
2298 emit_restore_stack();
2303 emit_restore_backtrace();
2304 if constexpr(
sizeof(
T) == 4) {
2305 static_assert(
sizeof(
U) == 4,
"Can only push 4-byte item if the upper 4 bytes are already 0");
2307 emit_bytes(0x89, 0x04, 0x24);
2310 emit_bytes(0x48, 0x89, 0x04, 0x24);
2315 auto extra = emit_setup_backtrace();
2321 emit_bytes(0x8b, 0x74, 0x24, 0x10 + extra);
2323 emit_bytes(0x8b, 0x7c, 0x24, 0x18 + extra);
2326 emit_bytes(0x48, 0xb8);
2327 emit_operand_ptr(softfloatfun);
2329 emit_bytes(0xff, 0xd0);
2330 emit_restore_stack();
2335 emit_restore_backtrace_basic();
2337 emit_bytes(0x48, 0x83, 0xc4, 0x08 + extra);
2339 emit_bytes(0x89, 0x04, 0x24);
2343 auto extra = emit_setup_backtrace();
2349 emit_bytes(0x48, 0x8b, 0x74, 0x24, 0x10 + extra);
2351 emit_bytes(0x48, 0x8b, 0x7c, 0x24, 0x18 + extra);
2354 emit_bytes(0x48, 0xb8);
2355 emit_operand_ptr(softfloatfun);
2357 emit_bytes(0xff, 0xd0);
2358 emit_restore_stack();
2363 emit_restore_backtrace_basic();
2365 emit_bytes(0x48, 0x83, 0xc4, 0x08 + extra);
2367 emit_bytes(0x48, 0x89, 0x04, 0x24);
2372 auto extra = emit_setup_backtrace();
2379 emit_bytes(0x8b, 0x74, 0x24, 0x18 + extra);
2381 emit_bytes(0x8b, 0x7c, 0x24, 0x10 + extra);
2384 emit_bytes(0x8b, 0x74, 0x24, 0x10 + extra);
2386 emit_bytes(0x8b, 0x7c, 0x24, 0x18 + extra);
2390 emit_bytes(0x48, 0xb8);
2391 emit_operand_ptr(softfloatfun);
2393 emit_bytes(0xff, 0xd0);
2394 emit_restore_stack();
2399 emit_restore_backtrace_basic();
2402 emit_bytes(0x34, 0x01);
2405 emit_bytes(0x48, 0x83, 0xc4, 0x08 + extra);
2407 emit_bytes(0x48, 0x89, 0x04, 0x24);
2412 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
2414 emit_bytes(0xf3, 0x0f, 0xc2, 0x44, 0x24, 0x08,
opcode);
2417 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
2419 emit_bytes(0xf3, 0x0f, 0xc2, 0x04, 0x24,
opcode);
2422 emit_bytes(0x66, 0x0f, 0x7e, 0xc0);
2425 emit_bytes(0x83, 0xe0, 0x01);
2428 emit_bytes(0xff, 0xc0);
2431 emit_bytes(0x48, 0x8d, 0x64, 0x24, 0x10);
2439 auto extra = emit_setup_backtrace();
2446 emit_bytes(0x48, 0x8b, 0x74, 0x24, 0x18 + extra);
2448 emit_bytes(0x48, 0x8b, 0x7c, 0x24, 0x10 + extra);
2451 emit_bytes(0x48, 0x8b, 0x74, 0x24, 0x10 + extra);
2453 emit_bytes(0x48, 0x8b, 0x7c, 0x24, 0x18 + extra);
2457 emit_bytes(0x48, 0xb8);
2458 emit_operand_ptr(softfloatfun);
2460 emit_bytes(0xff, 0xd0);
2461 emit_restore_stack();
2466 emit_restore_backtrace_basic();
2469 emit_bytes(0x34, 0x01);
2472 emit_bytes(0x48, 0x83, 0xc4, 0x08 + extra);
2474 emit_bytes(0x48, 0x89, 0x04, 0x24);
2479 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
2481 emit_bytes(0xf2, 0x0f, 0xc2, 0x44, 0x24, 0x08,
opcode);
2484 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
2486 emit_bytes(0xf2, 0x0f, 0xc2, 0x04, 0x24,
opcode);
2489 emit_bytes(0x66, 0x0f, 0x7e, 0xc0);
2492 emit_bytes(0x83, 0xe0, 0x01);
2495 emit_bytes(0xff, 0xc0);
2498 emit_bytes(0x48, 0x8d, 0x64, 0x24, 0x10);
2504 template<
class...
T>
2505 void emit_i32_binop(
T...
op) {
2511 emit_bytes(
static_cast<uint8_t>(
op)...);
2516 template<
class...
T>
2517 void emit_i64_binop(
T...
op) {
2523 emit_bytes(
static_cast<uint8_t>(
op)...);
2528 return emit_f32_binop_softfloat(softfloatfun);
2531 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
2533 emit_bytes(0xf3, 0x0f,
op, 0x04, 0x24);
2535 emit_bytes(0x48, 0x8d, 0x64, 0x24, 0x08);
2537 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
2542 return emit_f64_binop_softfloat(softfloatfun);
2545 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
2547 emit_bytes(0xf2, 0x0f,
op, 0x04, 0x24);
2549 emit_bytes(0x48, 0x8d, 0x64, 0x24, 0x08);
2551 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2556 template<
class...
T>
2557 void emit_f2i(
T...
op) {
2559 emit_bytes(0xb8, 0x80, 0x1f, 0x00, 0x00);
2563 emit_bytes(0x0f, 0xae, 0x14, 0x24);
2567 emit_bytes(0x0f, 0xae, 0x1c, 0x24);
2571 emit_bytes(0xf6, 0xc1, 0x01);
2573 emit_bytes(0x0f, 0x85);
2574 fix_branch(emit_branch_target32(), fpe_handler);
2577 void* emit_error_handler(
void (*handler)()) {
2578 void* result = code;
2580 emit_bytes(0x48, 0x83, 0xe4, 0xf0);
2582 emit_bytes(0x48, 0xb8);
2583 emit_operand_ptr(handler);
2585 emit_bytes(0xff, 0xd0);
2589 void emit_align_stack() {
2591 emit_bytes(0x48, 0x89, 0xe1);
2592 emit_bytes(0x48, 0x83, 0xe4, 0xf0);
2597 void emit_restore_stack() {
2599 emit_bytes(0x48, 0x8b, 0x24, 0x24);
2602 void emit_host_call(
uint32_t funcnum) {
2604 if constexpr (Context::async_backtrace()) {
2608 emit_bytes(0x48, 0x89, 0x27);
2613 emit_operand32(funcnum);
2619 emit_bytes(0x48, 0x8d, 0x74, 0x24, 0x18 + extra);
2622 emit_bytes(0x48, 0xb8);
2623 emit_operand_ptr(&call_host_function);
2625 emit_bytes(0xff, 0xd0);
2626 emit_restore_stack();
2631 if constexpr (Context::async_backtrace()) {
2632 emit_restore_backtrace_basic();
2642 if constexpr (Context::async_backtrace()) {
2650 emit_bytes(0x48, 0x89, 0x27);
2658 void emit_restore_backtrace_basic() {
2659 if constexpr (Context::async_backtrace()) {
2661 emit_bytes(0x31, 0xd2);
2663 emit_bytes(0x48, 0x89, 0x17);
2666 void emit_restore_backtrace() {
2667 if constexpr (Context::async_backtrace()) {
2668 emit_restore_backtrace_basic();
2670 emit_bytes(0x48, 0x83, 0xc4, 0x10);
2676 static native_value call_host_function(Context*
context , native_value*
stack ,
uint32_t idx ) {
2679 native_value result;
2687 return context->current_linear_memory();
2691 return context->grow_linear_memory(pages);