Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
sysio::vm::machine_code_writer< Context > Class Template Reference

#include <x86_64.hpp>

Classes

struct  br_table_generator
 

Public Types

using float32_t = float
 
using float64_t = double
 
using fn_type = native_value(*)(void* context, void* memory)
 

Public Member Functions

 machine_code_writer (growable_allocator &alloc, std::size_t source_bytes, module &mod)
 
 ~machine_code_writer ()
 
void emit_prologue (const func_type &, const guarded_vector< local_entry > &locals, uint32_t funcnum)
 
void emit_epilogue (const func_type &ft, const guarded_vector< local_entry > &locals, uint32_t)
 
void emit_unreachable ()
 
void emit_nop ()
 
void * emit_end ()
 
void * emit_return (uint32_t depth_change)
 
void emit_block ()
 
void * emit_loop ()
 
void * emit_if ()
 
void * emit_else (void *if_loc)
 
void * emit_br (uint32_t depth_change)
 
void * emit_br_if (uint32_t depth_change)
 
br_table_generator emit_br_table (uint32_t table_size)
 
void register_call (void *ptr, uint32_t funcnum)
 
void start_function (void *func_start, uint32_t funcnum)
 
void emit_call (const func_type &ft, uint32_t funcnum)
 
void emit_call_indirect (const func_type &ft, uint32_t functypeidx)
 
void emit_drop ()
 
void emit_select ()
 
void emit_get_local (uint32_t local_idx)
 
void emit_set_local (uint32_t local_idx)
 
void emit_tee_local (uint32_t local_idx)
 
void emit_get_global (uint32_t globalidx)
 
void emit_set_global (uint32_t globalidx)
 
void emit_i32_load (uint32_t, uint32_t offset)
 
void emit_i64_load (uint32_t, uint32_t offset)
 
void emit_f32_load (uint32_t, uint32_t offset)
 
void emit_f64_load (uint32_t, uint32_t offset)
 
void emit_i32_load8_s (uint32_t, uint32_t offset)
 
void emit_i32_load16_s (uint32_t, uint32_t offset)
 
void emit_i32_load8_u (uint32_t, uint32_t offset)
 
void emit_i32_load16_u (uint32_t, uint32_t offset)
 
void emit_i64_load8_s (uint32_t, uint32_t offset)
 
void emit_i64_load16_s (uint32_t, uint32_t offset)
 
void emit_i64_load32_s (uint32_t, uint32_t offset)
 
void emit_i64_load8_u (uint32_t, uint32_t offset)
 
void emit_i64_load16_u (uint32_t, uint32_t offset)
 
void emit_i64_load32_u (uint32_t, uint32_t offset)
 
void emit_i32_store (uint32_t, uint32_t offset)
 
void emit_i64_store (uint32_t, uint32_t offset)
 
void emit_f32_store (uint32_t, uint32_t offset)
 
void emit_f64_store (uint32_t, uint32_t offset)
 
void emit_i32_store8 (uint32_t, uint32_t offset)
 
void emit_i32_store16 (uint32_t, uint32_t offset)
 
void emit_i64_store8 (uint32_t, uint32_t offset)
 
void emit_i64_store16 (uint32_t, uint32_t offset)
 
void emit_i64_store32 (uint32_t, uint32_t offset)
 
void emit_current_memory ()
 
void emit_grow_memory ()
 
void emit_i32_const (uint32_t value)
 
void emit_i64_const (uint64_t value)
 
void emit_f32_const (float value)
 
void emit_f64_const (double value)
 
void emit_i32_eqz ()
 
void emit_i32_eq ()
 
void emit_i32_ne ()
 
void emit_i32_lt_s ()
 
void emit_i32_lt_u ()
 
void emit_i32_gt_s ()
 
void emit_i32_gt_u ()
 
void emit_i32_le_s ()
 
void emit_i32_le_u ()
 
void emit_i32_ge_s ()
 
void emit_i32_ge_u ()
 
void emit_i64_eqz ()
 
void emit_i64_eq ()
 
void emit_i64_ne ()
 
void emit_i64_lt_s ()
 
void emit_i64_lt_u ()
 
void emit_i64_gt_s ()
 
void emit_i64_gt_u ()
 
void emit_i64_le_s ()
 
void emit_i64_le_u ()
 
void emit_i64_ge_s ()
 
void emit_i64_ge_u ()
 
void emit_f32_eq ()
 
void emit_f32_ne ()
 
void emit_f32_lt ()
 
void emit_f32_gt ()
 
void emit_f32_le ()
 
void emit_f32_ge ()
 
void emit_f64_eq ()
 
void emit_f64_ne ()
 
void emit_f64_lt ()
 
void emit_f64_gt ()
 
void emit_f64_le ()
 
void emit_f64_ge ()
 
bool has_tzcnt_impl ()
 
bool has_tzcnt ()
 
void emit_i32_clz ()
 
void emit_i32_ctz ()
 
void emit_i32_popcnt ()
 
void emit_i32_add ()
 
void emit_i32_sub ()
 
void emit_i32_mul ()
 
void emit_i32_div_s ()
 
void emit_i32_div_u ()
 
void emit_i32_rem_s ()
 
void emit_i32_rem_u ()
 
void emit_i32_and ()
 
void emit_i32_or ()
 
void emit_i32_xor ()
 
void emit_i32_shl ()
 
void emit_i32_shr_s ()
 
void emit_i32_shr_u ()
 
void emit_i32_rotl ()
 
void emit_i32_rotr ()
 
void emit_i64_clz ()
 
void emit_i64_ctz ()
 
void emit_i64_popcnt ()
 
void emit_i64_add ()
 
void emit_i64_sub ()
 
void emit_i64_mul ()
 
void emit_i64_div_s ()
 
void emit_i64_div_u ()
 
void emit_i64_rem_s ()
 
void emit_i64_rem_u ()
 
void emit_i64_and ()
 
void emit_i64_or ()
 
void emit_i64_xor ()
 
void emit_i64_shl ()
 
void emit_i64_shr_s ()
 
void emit_i64_shr_u ()
 
void emit_i64_rotl ()
 
void emit_i64_rotr ()
 
void emit_f32_abs ()
 
void emit_f32_neg ()
 
void emit_f32_ceil ()
 
void emit_f32_floor ()
 
void emit_f32_trunc ()
 
void emit_f32_nearest ()
 
void emit_f32_sqrt ()
 
void emit_f32_add ()
 
void emit_f32_sub ()
 
void emit_f32_mul ()
 
void emit_f32_div ()
 
void emit_f32_min ()
 
void emit_f32_max ()
 
void emit_f32_copysign ()
 
void emit_f64_abs ()
 
void emit_f64_neg ()
 
void emit_f64_ceil ()
 
void emit_f64_floor ()
 
void emit_f64_trunc ()
 
void emit_f64_nearest ()
 
void emit_f64_sqrt ()
 
void emit_f64_add ()
 
void emit_f64_sub ()
 
void emit_f64_mul ()
 
void emit_f64_div ()
 
void emit_f64_min ()
 
void emit_f64_max ()
 
void emit_f64_copysign ()
 
void emit_i32_wrap_i64 ()
 
void emit_i32_trunc_s_f32 ()
 
void emit_i32_trunc_u_f32 ()
 
void emit_i32_trunc_s_f64 ()
 
void emit_i32_trunc_u_f64 ()
 
void emit_i64_extend_s_i32 ()
 
void emit_i64_extend_u_i32 ()
 
void emit_i64_trunc_s_f32 ()
 
void emit_i64_trunc_u_f32 ()
 
void emit_i64_trunc_s_f64 ()
 
void emit_i64_trunc_u_f64 ()
 
void emit_f32_convert_s_i32 ()
 
void emit_f32_convert_u_i32 ()
 
void emit_f32_convert_s_i64 ()
 
void emit_f32_convert_u_i64 ()
 
void emit_f32_demote_f64 ()
 
void emit_f64_convert_s_i32 ()
 
void emit_f64_convert_u_i32 ()
 
void emit_f64_convert_s_i64 ()
 
void emit_f64_convert_u_i64 ()
 
void emit_f64_promote_f32 ()
 
void emit_i32_reinterpret_f32 ()
 
void emit_i64_reinterpret_f64 ()
 
void emit_f32_reinterpret_i32 ()
 
void emit_f64_reinterpret_i64 ()
 
void emit_error ()
 
void finalize (function_body &body)
 
const void * get_addr () const
 
const void * get_base_addr () const
 
 machine_code_writer (growable_allocator &alloc, std::size_t source_bytes, module &mod)
 
 ~machine_code_writer ()
 
void emit_prologue (const func_type &, const guarded_vector< local_entry > &locals, uint32_t funcnum)
 
void emit_epilogue (const func_type &ft, const guarded_vector< local_entry > &locals, uint32_t)
 
void emit_unreachable ()
 
void emit_nop ()
 
void * emit_end ()
 
void * emit_return (uint32_t depth_change)
 
void emit_block ()
 
void * emit_loop ()
 
void * emit_if ()
 
void * emit_else (void *if_loc)
 
void * emit_br (uint32_t depth_change)
 
void * emit_br_if (uint32_t depth_change)
 
br_table_generator emit_br_table (uint32_t table_size)
 
void register_call (void *ptr, uint32_t funcnum)
 
void start_function (void *func_start, uint32_t funcnum)
 
void emit_call (const func_type &ft, uint32_t funcnum)
 
void emit_call_indirect (const func_type &ft, uint32_t functypeidx)
 
void emit_drop ()
 
void emit_select ()
 
void emit_get_local (uint32_t local_idx)
 
void emit_set_local (uint32_t local_idx)
 
void emit_tee_local (uint32_t local_idx)
 
void emit_get_global (uint32_t globalidx)
 
void emit_set_global (uint32_t globalidx)
 
void emit_i32_load (uint32_t, uint32_t offset)
 
void emit_i64_load (uint32_t, uint32_t offset)
 
void emit_f32_load (uint32_t, uint32_t offset)
 
void emit_f64_load (uint32_t, uint32_t offset)
 
void emit_i32_load8_s (uint32_t, uint32_t offset)
 
void emit_i32_load16_s (uint32_t, uint32_t offset)
 
void emit_i32_load8_u (uint32_t, uint32_t offset)
 
void emit_i32_load16_u (uint32_t, uint32_t offset)
 
void emit_i64_load8_s (uint32_t, uint32_t offset)
 
void emit_i64_load16_s (uint32_t, uint32_t offset)
 
void emit_i64_load32_s (uint32_t, uint32_t offset)
 
void emit_i64_load8_u (uint32_t, uint32_t offset)
 
void emit_i64_load16_u (uint32_t, uint32_t offset)
 
void emit_i64_load32_u (uint32_t, uint32_t offset)
 
void emit_i32_store (uint32_t, uint32_t offset)
 
void emit_i64_store (uint32_t, uint32_t offset)
 
void emit_f32_store (uint32_t, uint32_t offset)
 
void emit_f64_store (uint32_t, uint32_t offset)
 
void emit_i32_store8 (uint32_t, uint32_t offset)
 
void emit_i32_store16 (uint32_t, uint32_t offset)
 
void emit_i64_store8 (uint32_t, uint32_t offset)
 
void emit_i64_store16 (uint32_t, uint32_t offset)
 
void emit_i64_store32 (uint32_t, uint32_t offset)
 
void emit_current_memory ()
 
void emit_grow_memory ()
 
void emit_i32_const (uint32_t value)
 
void emit_i64_const (uint64_t value)
 
void emit_f32_const (float value)
 
void emit_f64_const (double value)
 
void emit_i32_eqz ()
 
void emit_i32_eq ()
 
void emit_i32_ne ()
 
void emit_i32_lt_s ()
 
void emit_i32_lt_u ()
 
void emit_i32_gt_s ()
 
void emit_i32_gt_u ()
 
void emit_i32_le_s ()
 
void emit_i32_le_u ()
 
void emit_i32_ge_s ()
 
void emit_i32_ge_u ()
 
void emit_i64_eqz ()
 
void emit_i64_eq ()
 
void emit_i64_ne ()
 
void emit_i64_lt_s ()
 
void emit_i64_lt_u ()
 
void emit_i64_gt_s ()
 
void emit_i64_gt_u ()
 
void emit_i64_le_s ()
 
void emit_i64_le_u ()
 
void emit_i64_ge_s ()
 
void emit_i64_ge_u ()
 
void emit_f32_eq ()
 
void emit_f32_ne ()
 
void emit_f32_lt ()
 
void emit_f32_gt ()
 
void emit_f32_le ()
 
void emit_f32_ge ()
 
void emit_f64_eq ()
 
void emit_f64_ne ()
 
void emit_f64_lt ()
 
void emit_f64_gt ()
 
void emit_f64_le ()
 
void emit_f64_ge ()
 
bool has_tzcnt_impl ()
 
bool has_tzcnt ()
 
void emit_i32_clz ()
 
void emit_i32_ctz ()
 
void emit_i32_popcnt ()
 
void emit_i32_add ()
 
void emit_i32_sub ()
 
void emit_i32_mul ()
 
void emit_i32_div_s ()
 
void emit_i32_div_u ()
 
void emit_i32_rem_s ()
 
void emit_i32_rem_u ()
 
void emit_i32_and ()
 
void emit_i32_or ()
 
void emit_i32_xor ()
 
void emit_i32_shl ()
 
void emit_i32_shr_s ()
 
void emit_i32_shr_u ()
 
void emit_i32_rotl ()
 
void emit_i32_rotr ()
 
void emit_i64_clz ()
 
void emit_i64_ctz ()
 
void emit_i64_popcnt ()
 
void emit_i64_add ()
 
void emit_i64_sub ()
 
void emit_i64_mul ()
 
void emit_i64_div_s ()
 
void emit_i64_div_u ()
 
void emit_i64_rem_s ()
 
void emit_i64_rem_u ()
 
void emit_i64_and ()
 
void emit_i64_or ()
 
void emit_i64_xor ()
 
void emit_i64_shl ()
 
void emit_i64_shr_s ()
 
void emit_i64_shr_u ()
 
void emit_i64_rotl ()
 
void emit_i64_rotr ()
 
void emit_f32_abs ()
 
void emit_f32_neg ()
 
void emit_f32_ceil ()
 
void emit_f32_floor ()
 
void emit_f32_trunc ()
 
void emit_f32_nearest ()
 
void emit_f32_sqrt ()
 
void emit_f32_add ()
 
void emit_f32_sub ()
 
void emit_f32_mul ()
 
void emit_f32_div ()
 
void emit_f32_min ()
 
void emit_f32_max ()
 
void emit_f32_copysign ()
 
void emit_f64_abs ()
 
void emit_f64_neg ()
 
void emit_f64_ceil ()
 
void emit_f64_floor ()
 
void emit_f64_trunc ()
 
void emit_f64_nearest ()
 
void emit_f64_sqrt ()
 
void emit_f64_add ()
 
void emit_f64_sub ()
 
void emit_f64_mul ()
 
void emit_f64_div ()
 
void emit_f64_min ()
 
void emit_f64_max ()
 
void emit_f64_copysign ()
 
void emit_i32_wrap_i64 ()
 
void emit_i32_trunc_s_f32 ()
 
void emit_i32_trunc_u_f32 ()
 
void emit_i32_trunc_s_f64 ()
 
void emit_i32_trunc_u_f64 ()
 
void emit_i64_extend_s_i32 ()
 
void emit_i64_extend_u_i32 ()
 
void emit_i64_trunc_s_f32 ()
 
void emit_i64_trunc_u_f32 ()
 
void emit_i64_trunc_s_f64 ()
 
void emit_i64_trunc_u_f64 ()
 
void emit_f32_convert_s_i32 ()
 
void emit_f32_convert_u_i32 ()
 
void emit_f32_convert_s_i64 ()
 
void emit_f32_convert_u_i64 ()
 
void emit_f32_demote_f64 ()
 
void emit_f64_convert_s_i32 ()
 
void emit_f64_convert_u_i32 ()
 
void emit_f64_convert_s_i64 ()
 
void emit_f64_convert_u_i64 ()
 
void emit_f64_promote_f32 ()
 
void emit_i32_reinterpret_f32 ()
 
void emit_i64_reinterpret_f64 ()
 
void emit_f32_reinterpret_i32 ()
 
void emit_f64_reinterpret_i64 ()
 
void emit_error ()
 
void finalize (function_body &body)
 
const void * get_addr () const
 
const void * get_base_addr () const
 

Static Public Member Functions

static void fix_branch (void *branch, void *target)
 
static void fix_branch64 (void *branch, void *target)
 
static void fix_branch (void *branch, void *target)
 
static void fix_branch64 (void *branch, void *target)
 

Static Public Attributes

static constexpr std::size_t max_prologue_size = 21
 
static constexpr std::size_t max_epilogue_size = 10
 

Detailed Description

template<typename Context>
class sysio::vm::machine_code_writer< Context >

Definition at line 34 of file x86_64.hpp.

Member Typedef Documentation

◆ float32_t

template<typename Context >
typedef float sysio::vm::machine_code_writer< Context >::float32_t = float

Definition at line 974 of file x86_64.hpp.

◆ float64_t

template<typename Context >
typedef double sysio::vm::machine_code_writer< Context >::float64_t = double

Definition at line 975 of file x86_64.hpp.

◆ fn_type

template<typename Context >
typedef native_value(* sysio::vm::machine_code_writer< Context >::fn_type)(void *context, void *memory) = native_value(*)(void* context, void* memory)

Definition at line 2095 of file x86_64.hpp.

Constructor & Destructor Documentation

◆ machine_code_writer() [1/2]

template<typename Context >
sysio::vm::machine_code_writer< Context >::machine_code_writer ( growable_allocator & alloc,
std::size_t source_bytes,
module & mod )
inline

Definition at line 36 of file x86_64.hpp.

36 :
37 _mod(mod), _code_segment_base(alloc.start_code()) {
38 const std::size_t code_size = 4 * 16; // 4 error handlers, each is 16 bytes.
39 _code_start = _mod.allocator.alloc<unsigned char>(code_size);
40 _code_end = _code_start + code_size;
41 code = _code_start;
42
43 // always emit these functions
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);
48
49 assert(code == _code_end); // verify that the manual instruction count is correct
50
51 // emit host functions
52 const uint32_t num_imported = mod.get_imported_functions_size();
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;
56 // code already set
57 for(uint32_t i = 0; i < num_imported; ++i) {
58 start_function(code, i);
59 emit_host_call(i);
60 }
61 assert(code == _code_end);
62
63 jmp_table = code;
64 if (_mod.tables.size() > 0) {
65 // Each function table entry consumes exactly 17 bytes (counted
66 // manually). The size must be constant, so that call_indirect
67 // can use random access
68 _table_element_size = 17;
69 const std::size_t table_size = _table_element_size*_mod.tables[0].table.size();
70 _code_start = _mod.allocator.alloc<unsigned char>(table_size);
71 _code_end = _code_start + table_size;
72 // code already set
73 for(uint32_t i = 0; i < _mod.tables[0].table.size(); ++i) {
74 uint32_t fn_idx = _mod.tables[0].table[i];
75 if (fn_idx < _mod.fast_functions.size()) {
76 // cmp _mod.fast_functions[fn_idx], %edx
77 emit_bytes(0x81, 0xfa);
78 emit_operand32(_mod.fast_functions[fn_idx]);
79 // je fn
80 emit_bytes(0x0f, 0x84);
81 register_call(emit_branch_target32(), fn_idx);
82 // jmp ERROR
83 emit_bytes(0xe9);
84 fix_branch(emit_branch_target32(), type_error_handler);
85 } else {
86 // jmp ERROR
87 emit_bytes(0xe9);
88 // default for out-of-range functions
89 fix_branch(emit_branch_target32(), call_indirect_handler);
90 // padding
91 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
92 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
93 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
94 }
95 }
96 assert(code == _code_end);
97 }
98 }
void start_function(void *func_start, uint32_t funcnum)
Definition x86_64.hpp:305
void register_call(void *ptr, uint32_t funcnum)
Definition x86_64.hpp:296
static void fix_branch(void *branch, void *target)
Definition x86_64.hpp:2080
unsigned int uint32_t
Definition stdint.h:126
guarded_vector< uint32_t > fast_functions
Definition types.hpp:186
guarded_vector< table_type > tables
Definition types.hpp:172
growable_allocator allocator
Definition types.hpp:167
Here is the call graph for this function:

◆ ~machine_code_writer() [1/2]

template<typename Context >
sysio::vm::machine_code_writer< Context >::~machine_code_writer ( )
inline

Definition at line 99 of file x86_64.hpp.

99{ _mod.allocator.end_code<true>(_code_segment_base); }
void end_code(void *code_base)
Here is the call graph for this function:

◆ machine_code_writer() [2/2]

template<typename Context >
sysio::vm::machine_code_writer< Context >::machine_code_writer ( growable_allocator & alloc,
std::size_t source_bytes,
module & mod )
inline

Definition at line 36 of file x86_64.hpp.

36 :
37 _mod(mod), _code_segment_base(alloc.start_code()) {
38 const std::size_t code_size = 4 * 16; // 4 error handlers, each is 16 bytes.
39 _code_start = _mod.allocator.alloc<unsigned char>(code_size);
40 _code_end = _code_start + code_size;
41 code = _code_start;
42
43 // always emit these functions
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);
48
49 assert(code == _code_end); // verify that the manual instruction count is correct
50
51 // emit host functions
52 const uint32_t num_imported = mod.get_imported_functions_size();
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;
56 // code already set
57 for(uint32_t i = 0; i < num_imported; ++i) {
58 start_function(code, i);
59 emit_host_call(i);
60 }
61 assert(code == _code_end);
62
63 jmp_table = code;
64 if (_mod.tables.size() > 0) {
65 // Each function table entry consumes exactly 17 bytes (counted
66 // manually). The size must be constant, so that call_indirect
67 // can use random access
68 _table_element_size = 17;
69 const std::size_t table_size = _table_element_size*_mod.tables[0].table.size();
70 _code_start = _mod.allocator.alloc<unsigned char>(table_size);
71 _code_end = _code_start + table_size;
72 // code already set
73 for(uint32_t i = 0; i < _mod.tables[0].table.size(); ++i) {
74 uint32_t fn_idx = _mod.tables[0].table[i];
75 if (fn_idx < _mod.fast_functions.size()) {
76 // cmp _mod.fast_functions[fn_idx], %edx
77 emit_bytes(0x81, 0xfa);
78 emit_operand32(_mod.fast_functions[fn_idx]);
79 // je fn
80 emit_bytes(0x0f, 0x84);
81 register_call(emit_branch_target32(), fn_idx);
82 // jmp ERROR
83 emit_bytes(0xe9);
84 fix_branch(emit_branch_target32(), type_error_handler);
85 } else {
86 // jmp ERROR
87 emit_bytes(0xe9);
88 // default for out-of-range functions
89 fix_branch(emit_branch_target32(), call_indirect_handler);
90 // padding
91 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
92 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
93 emit_bytes(0xcc, 0xcc, 0xcc, 0xcc);
94 }
95 }
96 assert(code == _code_end);
97 }
98 }
Here is the call graph for this function:

◆ ~machine_code_writer() [2/2]

template<typename Context >
sysio::vm::machine_code_writer< Context >::~machine_code_writer ( )
inline

Definition at line 99 of file x86_64.hpp.

99{ _mod.allocator.end_code<true>(_code_segment_base); }
Here is the call graph for this function:

Member Function Documentation

◆ emit_block() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_block ( )
inline

Definition at line 175 of file x86_64.hpp.

175{}

◆ emit_block() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_block ( )
inline

Definition at line 175 of file x86_64.hpp.

175{}

◆ emit_br() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_br ( uint32_t depth_change)
inline

Definition at line 193 of file x86_64.hpp.

193 {
194 auto icount = variable_size_instr(5, 17);
195 // add RSP, depth_change * 8
196 emit_multipop(depth_change);
197 // jmp DEST
198 emit_bytes(0xe9);
199 return emit_branch_target32();
200 }
Here is the caller graph for this function:

◆ emit_br() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_br ( uint32_t depth_change)
inline

Definition at line 193 of file x86_64.hpp.

193 {
194 auto icount = variable_size_instr(5, 17);
195 // add RSP, depth_change * 8
196 emit_multipop(depth_change);
197 // jmp DEST
198 emit_bytes(0xe9);
199 return emit_branch_target32();
200 }

◆ emit_br_if() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_br_if ( uint32_t depth_change)
inline

Definition at line 201 of file x86_64.hpp.

201 {
202 auto icount = variable_size_instr(9, 26);
203 // pop RAX
204 emit_bytes(0x58);
205 // test EAX, EAX
206 emit_bytes(0x85, 0xC0);
207
208 if(depth_change == 0u || depth_change == 0x80000001u) {
209 // jnz DEST
210 emit_bytes(0x0F, 0x85);
211 return emit_branch_target32();
212 } else {
213 // jz SKIP
214 emit_bytes(0x0f, 0x84);
215 void* skip = emit_branch_target32();
216 // add depth_change*8, %rsp
217 emit_multipop(depth_change);
218 // jmp DEST
219 emit_bytes(0xe9);
220 void* result = emit_branch_target32();
221 // SKIP:
222 fix_branch(skip, code);
223 return result;
224 }
225 }
Here is the call graph for this function:

◆ emit_br_if() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_br_if ( uint32_t depth_change)
inline

Definition at line 201 of file x86_64.hpp.

201 {
202 auto icount = variable_size_instr(9, 26);
203 // pop RAX
204 emit_bytes(0x58);
205 // test EAX, EAX
206 emit_bytes(0x85, 0xC0);
207
208 if(depth_change == 0u || depth_change == 0x80000001u) {
209 // jnz DEST
210 emit_bytes(0x0F, 0x85);
211 return emit_branch_target32();
212 } else {
213 // jz SKIP
214 emit_bytes(0x0f, 0x84);
215 void* skip = emit_branch_target32();
216 // add depth_change*8, %rsp
217 emit_multipop(depth_change);
218 // jmp DEST
219 emit_bytes(0xe9);
220 void* result = emit_branch_target32();
221 // SKIP:
222 fix_branch(skip, code);
223 return result;
224 }
225 }
Here is the call graph for this function:

◆ emit_br_table() [1/2]

template<typename Context >
br_table_generator sysio::vm::machine_code_writer< Context >::emit_br_table ( uint32_t table_size)
inline

Definition at line 287 of file x86_64.hpp.

287 {
288 // pop %rax
289 emit_bytes(0x58);
290 // Increase the size by one to account for the default.
291 // The current algorithm handles this correctly, without
292 // any special cases.
293 return { this, 0, { {0, table_size+1, nullptr} } };
294 }

◆ emit_br_table() [2/2]

template<typename Context >
br_table_generator sysio::vm::machine_code_writer< Context >::emit_br_table ( uint32_t table_size)
inline

Definition at line 287 of file x86_64.hpp.

287 {
288 // pop %rax
289 emit_bytes(0x58);
290 // Increase the size by one to account for the default.
291 // The current algorithm handles this correctly, without
292 // any special cases.
293 return { this, 0, { {0, table_size+1, nullptr} } };
294 }

◆ emit_call() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_call ( const func_type & ft,
uint32_t funcnum )
inline

Definition at line 314 of file x86_64.hpp.

314 {
315 auto icount = variable_size_instr(15, 23);
316 emit_check_call_depth();
317 // callq TARGET
318 emit_bytes(0xe8);
319 void * branch = emit_branch_target32();
320 emit_multipop(ft.param_types.size());
321 register_call(branch, funcnum);
322 if(ft.return_count != 0)
323 // pushq %rax
324 emit_bytes(0x50);
325 emit_check_call_depth_end();
326 }
Here is the call graph for this function:

◆ emit_call() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_call ( const func_type & ft,
uint32_t funcnum )
inline

Definition at line 314 of file x86_64.hpp.

314 {
315 auto icount = variable_size_instr(15, 23);
316 emit_check_call_depth();
317 // callq TARGET
318 emit_bytes(0xe8);
319 void * branch = emit_branch_target32();
320 emit_multipop(ft.param_types.size());
321 register_call(branch, funcnum);
322 if(ft.return_count != 0)
323 // pushq %rax
324 emit_bytes(0x50);
325 emit_check_call_depth_end();
326 }
Here is the call graph for this function:

◆ emit_call_indirect() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_call_indirect ( const func_type & ft,
uint32_t functypeidx )
inline

Definition at line 328 of file x86_64.hpp.

328 {
329 auto icount = variable_size_instr(43, 51);
330 emit_check_call_depth();
331 auto& table = _mod.tables[0].table;
332 functypeidx = _mod.type_aliases[functypeidx];
333 // pop %rax
334 emit_bytes(0x58);
335 // cmp $size, %rax
336 emit_bytes(0x48, 0x3d);
337 emit_operand32(table.size());
338 // jae ERROR
339 emit_bytes(0x0f, 0x83);
340 fix_branch(emit_branch_target32(), call_indirect_handler);
341 // leaq table(%rip), %rdx
342 emit_bytes(0x48, 0x8d, 0x15);
343 fix_branch(emit_branch_target32(), jmp_table);
344 // imul $17, %eax, %eax
345 assert(_table_element_size <= 127); // must fit in 8-bit signed value for imul
346 emit_bytes(0x6b, 0xc0, _table_element_size);
347 // addq %rdx, %rax
348 emit_bytes(0x48, 0x01, 0xd0);
349 // mov $funtypeidx, %edx
350 emit_bytes(0xba);
351 emit_operand32(functypeidx);
352 // callq *%rax
353 emit_bytes(0xff, 0xd0);
354 emit_multipop(ft.param_types.size());
355 if(ft.return_count != 0)
356 // pushq %rax
357 emit_bytes(0x50);
358 emit_check_call_depth_end();
359 }
guarded_vector< uint32_t > type_aliases
Definition types.hpp:185
Here is the call graph for this function:

◆ emit_call_indirect() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_call_indirect ( const func_type & ft,
uint32_t functypeidx )
inline

Definition at line 328 of file x86_64.hpp.

328 {
329 auto icount = variable_size_instr(43, 51);
330 emit_check_call_depth();
331 auto& table = _mod.tables[0].table;
332 functypeidx = _mod.type_aliases[functypeidx];
333 // pop %rax
334 emit_bytes(0x58);
335 // cmp $size, %rax
336 emit_bytes(0x48, 0x3d);
337 emit_operand32(table.size());
338 // jae ERROR
339 emit_bytes(0x0f, 0x83);
340 fix_branch(emit_branch_target32(), call_indirect_handler);
341 // leaq table(%rip), %rdx
342 emit_bytes(0x48, 0x8d, 0x15);
343 fix_branch(emit_branch_target32(), jmp_table);
344 // imul $17, %eax, %eax
345 assert(_table_element_size <= 127); // must fit in 8-bit signed value for imul
346 emit_bytes(0x6b, 0xc0, _table_element_size);
347 // addq %rdx, %rax
348 emit_bytes(0x48, 0x01, 0xd0);
349 // mov $funtypeidx, %edx
350 emit_bytes(0xba);
351 emit_operand32(functypeidx);
352 // callq *%rax
353 emit_bytes(0xff, 0xd0);
354 emit_multipop(ft.param_types.size());
355 if(ft.return_count != 0)
356 // pushq %rax
357 emit_bytes(0x50);
358 emit_check_call_depth_end();
359 }
Here is the call graph for this function:

◆ emit_current_memory() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_current_memory ( )
inline

Definition at line 625 of file x86_64.hpp.

625 {
626 auto icount = variable_size_instr(17, 35);
627 emit_setup_backtrace();
628 // pushq %rdi
629 emit_bytes(0x57);
630 // pushq %rsi
631 emit_bytes(0x56);
632 // movabsq $current_memory, %rax
633 emit_bytes(0x48, 0xb8);
634 emit_operand_ptr(&current_memory);
635 // call *%rax
636 emit_bytes(0xff, 0xd0);
637 // pop %rsi
638 emit_bytes(0x5e);
639 // pop %rdi
640 emit_bytes(0x5f);
641 emit_restore_backtrace();
642 // push %rax
643 emit_bytes(0x50);
644 }

◆ emit_current_memory() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_current_memory ( )
inline

Definition at line 625 of file x86_64.hpp.

625 {
626 auto icount = variable_size_instr(17, 35);
627 emit_setup_backtrace();
628 // pushq %rdi
629 emit_bytes(0x57);
630 // pushq %rsi
631 emit_bytes(0x56);
632 // movabsq $current_memory, %rax
633 emit_bytes(0x48, 0xb8);
634 emit_operand_ptr(&current_memory);
635 // call *%rax
636 emit_bytes(0xff, 0xd0);
637 // pop %rsi
638 emit_bytes(0x5e);
639 // pop %rdi
640 emit_bytes(0x5f);
641 emit_restore_backtrace();
642 // push %rax
643 emit_bytes(0x50);
644 }

◆ emit_drop() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_drop ( )
inline

Definition at line 361 of file x86_64.hpp.

361 {
362 // pop RAX
363 emit_bytes(0x58);
364 }

◆ emit_drop() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_drop ( )
inline

Definition at line 361 of file x86_64.hpp.

361 {
362 // pop RAX
363 emit_bytes(0x58);
364 }

◆ emit_else() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_else ( void * if_loc)
inline

Definition at line 187 of file x86_64.hpp.

187 {
188 auto icount = fixed_size_instr(5);
189 void* result = emit_br(0);
190 fix_branch(if_loc, code);
191 return result;
192 }
void * emit_br(uint32_t depth_change)
Definition x86_64.hpp:193
Here is the call graph for this function:

◆ emit_else() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_else ( void * if_loc)
inline

Definition at line 187 of file x86_64.hpp.

187 {
188 auto icount = fixed_size_instr(5);
189 void* result = emit_br(0);
190 fix_branch(if_loc, code);
191 return result;
192 }
Here is the call graph for this function:

◆ emit_end() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_end ( )
inline

Definition at line 170 of file x86_64.hpp.

170{ return code; }

◆ emit_end() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_end ( )
inline

Definition at line 170 of file x86_64.hpp.

170{ return code; }

◆ emit_epilogue() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_epilogue ( const func_type & ft,
const guarded_vector< local_entry > & locals,
uint32_t  )
inline

Definition at line 148 of file x86_64.hpp.

148 {
149#ifndef NDEBUG
150 void * epilogue_start = code;
151#endif
152 if(ft.return_count != 0) {
153 // pop RAX
154 emit_bytes(0x58);
155 }
156 if (_local_count & 0xF0000000u) unimplemented();
157 emit_multipop(_local_count);
158 // popq RBP
159 emit_bytes(0x5d);
160 // retq
161 emit_bytes(0xc3);
162 assert((char*)code <= (char*)epilogue_start + max_epilogue_size);
163 }
static constexpr std::size_t max_epilogue_size
Definition x86_64.hpp:102

◆ emit_epilogue() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_epilogue ( const func_type & ft,
const guarded_vector< local_entry > & locals,
uint32_t  )
inline

Definition at line 148 of file x86_64.hpp.

148 {
149#ifndef NDEBUG
150 void * epilogue_start = code;
151#endif
152 if(ft.return_count != 0) {
153 // pop RAX
154 emit_bytes(0x58);
155 }
156 if (_local_count & 0xF0000000u) unimplemented();
157 emit_multipop(_local_count);
158 // popq RBP
159 emit_bytes(0x5d);
160 // retq
161 emit_bytes(0xc3);
162 assert((char*)code <= (char*)epilogue_start + max_epilogue_size);
163 }

◆ emit_error() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_error ( )
inline

Definition at line 2077 of file x86_64.hpp.

2077{ unimplemented(); }

◆ emit_error() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_error ( )
inline

Definition at line 2077 of file x86_64.hpp.

2077{ unimplemented(); }

◆ emit_f32_abs() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_abs ( )
inline

Definition at line 1352 of file x86_64.hpp.

1352 {
1353 auto icount = fixed_size_instr(7);
1354 // popq %rax;
1355 emit_bytes(0x58);
1356 // andl 0x7fffffff, %eax
1357 emit_bytes(0x25);
1358 emit_operand32(0x7fffffff);
1359 // pushq %rax
1360 emit_bytes(0x50);
1361 }

◆ emit_f32_abs() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_abs ( )
inline

Definition at line 1352 of file x86_64.hpp.

1352 {
1353 auto icount = fixed_size_instr(7);
1354 // popq %rax;
1355 emit_bytes(0x58);
1356 // andl 0x7fffffff, %eax
1357 emit_bytes(0x25);
1358 emit_operand32(0x7fffffff);
1359 // pushq %rax
1360 emit_bytes(0x50);
1361 }

◆ emit_f32_add() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_add ( )
inline

Definition at line 1431 of file x86_64.hpp.

1431 {
1432 auto icount = softfloat_instr(21, 44, 58);
1433 emit_f32_binop(0x58, CHOOSE_FN(_sysio_f32_add));
1434 }
#define CHOOSE_FN(name)
Definition x86_64.hpp:976

◆ emit_f32_add() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_add ( )
inline

Definition at line 1431 of file x86_64.hpp.

1431 {
1432 auto icount = softfloat_instr(21, 44, 58);
1433 emit_f32_binop(0x58, CHOOSE_FN(_sysio_f32_add));
1434 }

◆ emit_f32_ceil() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ceil ( )
inline

Definition at line 1374 of file x86_64.hpp.

1374 {
1375 auto icount = softfloat_instr(12, 36, 54);
1376 if constexpr (use_softfloat) {
1377 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_ceil));
1378 }
1379 // roundss 0b1010, (%rsp), %xmm0
1380 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0a);
1381 // movss %xmm0, (%rsp)
1382 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1383 }
constexpr bool use_softfloat
Definition config.hpp:16

◆ emit_f32_ceil() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ceil ( )
inline

Definition at line 1374 of file x86_64.hpp.

1374 {
1375 auto icount = softfloat_instr(12, 36, 54);
1376 if constexpr (use_softfloat) {
1377 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_ceil));
1378 }
1379 // roundss 0b1010, (%rsp), %xmm0
1380 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0a);
1381 // movss %xmm0, (%rsp)
1382 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1383 }

◆ emit_f32_const() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_const ( float value)
inline

Definition at line 688 of file x86_64.hpp.

688 {
689 auto icount = fixed_size_instr(6);
690 // mov $value, %eax
691 emit_bytes(0xb8);
692 emit_operandf32(value);
693 // push %rax
694 emit_bytes(0x50);
695 }
#define value
Definition pkcs11.h:157

◆ emit_f32_const() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_const ( float value)
inline

Definition at line 688 of file x86_64.hpp.

688 {
689 auto icount = fixed_size_instr(6);
690 // mov $value, %eax
691 emit_bytes(0xb8);
692 emit_operandf32(value);
693 // push %rax
694 emit_bytes(0x50);
695 }

◆ emit_f32_convert_s_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_s_i32 ( )
inline

Definition at line 1907 of file x86_64.hpp.

1907 {
1908 auto icount = softfloat_instr(10, 36, 54);
1909 if constexpr (use_softfloat) {
1910 return emit_softfloat_unop(CHOOSE_FN(_sysio_i32_to_f32));
1911 }
1912 // cvtsi2ssl (%rsp), %xmm0
1913 emit_bytes(0xf3, 0x0f, 0x2a, 0x04, 0x24);
1914 // movss %xmm0, (%rsp)
1915 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1916 }

◆ emit_f32_convert_s_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_s_i32 ( )
inline

Definition at line 1907 of file x86_64.hpp.

1907 {
1908 auto icount = softfloat_instr(10, 36, 54);
1909 if constexpr (use_softfloat) {
1910 return emit_softfloat_unop(CHOOSE_FN(_sysio_i32_to_f32));
1911 }
1912 // cvtsi2ssl (%rsp), %xmm0
1913 emit_bytes(0xf3, 0x0f, 0x2a, 0x04, 0x24);
1914 // movss %xmm0, (%rsp)
1915 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1916 }

◆ emit_f32_convert_s_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_s_i64 ( )
inline

Definition at line 1928 of file x86_64.hpp.

1928 {
1929 auto icount = softfloat_instr(11, 38, 56);
1930 if constexpr (use_softfloat) {
1931 return emit_softfloat_unop(CHOOSE_FN(_sysio_i64_to_f32));
1932 }
1933 // cvtsi2sslq (%rsp), %xmm0
1934 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1935 // movss %xmm0, (%rsp)
1936 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1937 }

◆ emit_f32_convert_s_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_s_i64 ( )
inline

Definition at line 1928 of file x86_64.hpp.

1928 {
1929 auto icount = softfloat_instr(11, 38, 56);
1930 if constexpr (use_softfloat) {
1931 return emit_softfloat_unop(CHOOSE_FN(_sysio_i64_to_f32));
1932 }
1933 // cvtsi2sslq (%rsp), %xmm0
1934 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1935 // movss %xmm0, (%rsp)
1936 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1937 }

◆ emit_f32_convert_u_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_u_i32 ( )
inline

Definition at line 1917 of file x86_64.hpp.

1917 {
1918 auto icount = softfloat_instr(11, 36, 54);
1919 if constexpr (use_softfloat) {
1920 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui32_to_f32));
1921 }
1922 // zero-extend to 64-bits
1923 // cvtsi2sslq (%rsp), %xmm0
1924 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1925 // movss %xmm0, (%rsp)
1926 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1927 }

◆ emit_f32_convert_u_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_u_i32 ( )
inline

Definition at line 1917 of file x86_64.hpp.

1917 {
1918 auto icount = softfloat_instr(11, 36, 54);
1919 if constexpr (use_softfloat) {
1920 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui32_to_f32));
1921 }
1922 // zero-extend to 64-bits
1923 // cvtsi2sslq (%rsp), %xmm0
1924 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0x04, 0x24);
1925 // movss %xmm0, (%rsp)
1926 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1927 }

◆ emit_f32_convert_u_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_u_i64 ( )
inline

Definition at line 1938 of file x86_64.hpp.

1938 {
1939 auto icount = softfloat_instr(55, 38, 56);
1940 if constexpr (use_softfloat) {
1941 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui64_to_f32));
1942 }
1943 // movq (%rsp), %rax
1944 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1945 // testq %rax, %rax
1946 emit_bytes(0x48, 0x85, 0xc0);
1947 // js LARGE
1948 emit_bytes(0x0f, 0x88);
1949 void * large = emit_branch_target32();
1950 // cvtsi2ssq %rax, %xmm0
1951 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1952 // jmp done
1953 emit_bytes(0xe9);
1954 void* done = emit_branch_target32();
1955 // LARGE:
1956 fix_branch(large, code);
1957 // movq %rax, %rcx
1958 emit_bytes(0x48, 0x89, 0xc1);
1959 // shrq %rax
1960 emit_bytes(0x48, 0xd1, 0xe8);
1961 // andl $1, %ecx
1962 emit_bytes(0x83, 0xe1, 0x01);
1963 // orq %rcx, %rax
1964 emit_bytes(0x48, 0x09, 0xc8);
1965 // cvtsi2ssq %rax, %xmm0
1966 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1967 // addss %xmm0, %xmm0
1968 emit_bytes(0xf3, 0x0f, 0x58, 0xc0);
1969 // DONE:
1970 fix_branch(done, code);
1971 // xorl %eax, %eax
1972 emit_bytes(0x31, 0xc0);
1973 // movl %eax, 4(%rsp)
1974 emit_bytes(0x89, 0x44, 0x24, 0x04);
1975 // movss %xmm0, (%rsp)
1976 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1977 }
Here is the call graph for this function:

◆ emit_f32_convert_u_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_convert_u_i64 ( )
inline

Definition at line 1938 of file x86_64.hpp.

1938 {
1939 auto icount = softfloat_instr(55, 38, 56);
1940 if constexpr (use_softfloat) {
1941 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui64_to_f32));
1942 }
1943 // movq (%rsp), %rax
1944 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1945 // testq %rax, %rax
1946 emit_bytes(0x48, 0x85, 0xc0);
1947 // js LARGE
1948 emit_bytes(0x0f, 0x88);
1949 void * large = emit_branch_target32();
1950 // cvtsi2ssq %rax, %xmm0
1951 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1952 // jmp done
1953 emit_bytes(0xe9);
1954 void* done = emit_branch_target32();
1955 // LARGE:
1956 fix_branch(large, code);
1957 // movq %rax, %rcx
1958 emit_bytes(0x48, 0x89, 0xc1);
1959 // shrq %rax
1960 emit_bytes(0x48, 0xd1, 0xe8);
1961 // andl $1, %ecx
1962 emit_bytes(0x83, 0xe1, 0x01);
1963 // orq %rcx, %rax
1964 emit_bytes(0x48, 0x09, 0xc8);
1965 // cvtsi2ssq %rax, %xmm0
1966 emit_bytes(0xf3, 0x48, 0x0f, 0x2a, 0xc0);
1967 // addss %xmm0, %xmm0
1968 emit_bytes(0xf3, 0x0f, 0x58, 0xc0);
1969 // DONE:
1970 fix_branch(done, code);
1971 // xorl %eax, %eax
1972 emit_bytes(0x31, 0xc0);
1973 // movl %eax, 4(%rsp)
1974 emit_bytes(0x89, 0x44, 0x24, 0x04);
1975 // movss %xmm0, (%rsp)
1976 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1977 }
Here is the call graph for this function:

◆ emit_f32_copysign() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_copysign ( )
inline

Definition at line 1514 of file x86_64.hpp.

1514 {
1515 auto icount = fixed_size_instr(16);
1516 // popq %rax;
1517 emit_bytes(0x58);
1518 // andl 0x80000000, %eax
1519 emit_bytes(0x25);
1520 emit_operand32(0x80000000);
1521 // popq %rcx
1522 emit_bytes(0x59);
1523 // andl 0x7fffffff, %ecx
1524 emit_bytes(0x81, 0xe1);
1525 emit_operand32(0x7fffffff);
1526 // orl %ecx, %eax
1527 emit_bytes(0x09, 0xc8);
1528 // pushq %rax
1529 emit_bytes(0x50);
1530 }

◆ emit_f32_copysign() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_copysign ( )
inline

Definition at line 1514 of file x86_64.hpp.

1514 {
1515 auto icount = fixed_size_instr(16);
1516 // popq %rax;
1517 emit_bytes(0x58);
1518 // andl 0x80000000, %eax
1519 emit_bytes(0x25);
1520 emit_operand32(0x80000000);
1521 // popq %rcx
1522 emit_bytes(0x59);
1523 // andl 0x7fffffff, %ecx
1524 emit_bytes(0x81, 0xe1);
1525 emit_operand32(0x7fffffff);
1526 // orl %ecx, %eax
1527 emit_bytes(0x09, 0xc8);
1528 // pushq %rax
1529 emit_bytes(0x50);
1530 }

◆ emit_f32_demote_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_demote_f64 ( )
inline

Definition at line 1978 of file x86_64.hpp.

1978 {
1979 auto icount = softfloat_instr(16, 38, 56);
1980 if constexpr (use_softfloat) {
1981 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_demote));
1982 }
1983 // cvtsd2ss (%rsp), %xmm0
1984 emit_bytes(0xf2, 0x0f, 0x5a, 0x04, 0x24);
1985 // movss %xmm0, (%rsp)
1986 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1987 // Zero out the high 4 bytes
1988 // xor %eax, %eax
1989 emit_bytes(0x31, 0xc0);
1990 // mov %eax, 4(%rsp)
1991 emit_bytes(0x89, 0x44, 0x24, 0x04);
1992 }

◆ emit_f32_demote_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_demote_f64 ( )
inline

Definition at line 1978 of file x86_64.hpp.

1978 {
1979 auto icount = softfloat_instr(16, 38, 56);
1980 if constexpr (use_softfloat) {
1981 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_demote));
1982 }
1983 // cvtsd2ss (%rsp), %xmm0
1984 emit_bytes(0xf2, 0x0f, 0x5a, 0x04, 0x24);
1985 // movss %xmm0, (%rsp)
1986 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1987 // Zero out the high 4 bytes
1988 // xor %eax, %eax
1989 emit_bytes(0x31, 0xc0);
1990 // mov %eax, 4(%rsp)
1991 emit_bytes(0x89, 0x44, 0x24, 0x04);
1992 }

◆ emit_f32_div() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_div ( )
inline

Definition at line 1443 of file x86_64.hpp.

1443 {
1444 auto icount = softfloat_instr(21, 44, 58);
1445 emit_f32_binop(0x5e, CHOOSE_FN(_sysio_f32_div));
1446 }

◆ emit_f32_div() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_div ( )
inline

Definition at line 1443 of file x86_64.hpp.

1443 {
1444 auto icount = softfloat_instr(21, 44, 58);
1445 emit_f32_binop(0x5e, CHOOSE_FN(_sysio_f32_div));
1446 }

◆ emit_f32_eq() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_eq ( )
inline

Definition at line 980 of file x86_64.hpp.

980 {
981 auto icount = softfloat_instr(25,45,59);
982 emit_f32_relop(0x00, CHOOSE_FN(_sysio_f32_eq), false, false);
983 }

◆ emit_f32_eq() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_eq ( )
inline

Definition at line 980 of file x86_64.hpp.

980 {
981 auto icount = softfloat_instr(25,45,59);
982 emit_f32_relop(0x00, CHOOSE_FN(_sysio_f32_eq), false, false);
983 }

◆ emit_f32_floor() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_floor ( )
inline

Definition at line 1385 of file x86_64.hpp.

1385 {
1386 auto icount = softfloat_instr(12, 36, 54);
1387 if constexpr (use_softfloat) {
1388 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_floor));
1389 }
1390 // roundss 0b1001, (%rsp), %xmm0
1391 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x09);
1392 // movss %xmm0, (%rsp)
1393 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1394 }

◆ emit_f32_floor() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_floor ( )
inline

Definition at line 1385 of file x86_64.hpp.

1385 {
1386 auto icount = softfloat_instr(12, 36, 54);
1387 if constexpr (use_softfloat) {
1388 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_floor));
1389 }
1390 // roundss 0b1001, (%rsp), %xmm0
1391 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x09);
1392 // movss %xmm0, (%rsp)
1393 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1394 }

◆ emit_f32_ge() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ge ( )
inline

Definition at line 1005 of file x86_64.hpp.

1005 {
1006 auto icount = softfloat_instr(25,45,59);
1007 emit_f32_relop(0x02, CHOOSE_FN(_sysio_f32_le), true, false);
1008 }

◆ emit_f32_ge() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ge ( )
inline

Definition at line 1005 of file x86_64.hpp.

1005 {
1006 auto icount = softfloat_instr(25,45,59);
1007 emit_f32_relop(0x02, CHOOSE_FN(_sysio_f32_le), true, false);
1008 }

◆ emit_f32_gt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_gt ( )
inline

Definition at line 995 of file x86_64.hpp.

995 {
996 auto icount = softfloat_instr(25,45,59);
997 emit_f32_relop(0x01, CHOOSE_FN(_sysio_f32_lt), true, false);
998 }

◆ emit_f32_gt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_gt ( )
inline

Definition at line 995 of file x86_64.hpp.

995 {
996 auto icount = softfloat_instr(25,45,59);
997 emit_f32_relop(0x01, CHOOSE_FN(_sysio_f32_lt), true, false);
998 }

◆ emit_f32_le() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_le ( )
inline

Definition at line 1000 of file x86_64.hpp.

1000 {
1001 auto icount = softfloat_instr(25,45,59);
1002 emit_f32_relop(0x02, CHOOSE_FN(_sysio_f32_le), false, false);
1003 }

◆ emit_f32_le() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_le ( )
inline

Definition at line 1000 of file x86_64.hpp.

1000 {
1001 auto icount = softfloat_instr(25,45,59);
1002 emit_f32_relop(0x02, CHOOSE_FN(_sysio_f32_le), false, false);
1003 }

◆ emit_f32_load() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 499 of file x86_64.hpp.

499 {
500 auto icount = variable_size_instr(7, 15);
501 // movl (RAX), EAX
502 emit_load_impl(offset, 0x8b, 0x00);
503 }

◆ emit_f32_load() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 499 of file x86_64.hpp.

499 {
500 auto icount = variable_size_instr(7, 15);
501 // movl (RAX), EAX
502 emit_load_impl(offset, 0x8b, 0x00);
503 }

◆ emit_f32_lt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_lt ( )
inline

Definition at line 990 of file x86_64.hpp.

990 {
991 auto icount = softfloat_instr(25,45,59);
992 emit_f32_relop(0x01, CHOOSE_FN(_sysio_f32_lt), false, false);
993 }

◆ emit_f32_lt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_lt ( )
inline

Definition at line 990 of file x86_64.hpp.

990 {
991 auto icount = softfloat_instr(25,45,59);
992 emit_f32_relop(0x01, CHOOSE_FN(_sysio_f32_lt), false, false);
993 }

◆ emit_f32_max() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_max ( )
inline

Definition at line 1480 of file x86_64.hpp.

1480 {
1481 auto icount = softfloat_instr(47, 44, 58);
1482 if(use_softfloat) {
1483 emit_f32_binop_softfloat(CHOOSE_FN(_sysio_f32_max));
1484 return;
1485 }
1486 // mov (%rsp), %eax
1487 emit_bytes(0x8b, 0x04, 0x24);
1488 // test %eax, %eax
1489 emit_bytes(0x85, 0xc0);
1490 // je ZERO
1491 emit_bytes(0x0f, 0x84);
1492 void* zero = emit_branch_target32();
1493 // movss (%rsp), %xmm0
1494 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1495 // maxss 8(%rsp), %xmm0
1496 emit_bytes(0xf3, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1497 // jmp DONE
1498 emit_bytes(0xe9);
1499 void* done = emit_branch_target32();
1500 // ZERO:
1501 fix_branch(zero, code);
1502 // movss 8(%rsp), %xmm0
1503 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1504 // maxss (%rsp), %xmm0
1505 emit_bytes(0xf3, 0x0f, 0x5f, 0x04, 0x24);
1506 // DONE:
1507 fix_branch(done, code);
1508 // add $8, %rsp
1509 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1510 // movss %xmm0, (%rsp)
1511 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1512 }
Here is the call graph for this function:

◆ emit_f32_max() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_max ( )
inline

Definition at line 1480 of file x86_64.hpp.

1480 {
1481 auto icount = softfloat_instr(47, 44, 58);
1482 if(use_softfloat) {
1483 emit_f32_binop_softfloat(CHOOSE_FN(_sysio_f32_max));
1484 return;
1485 }
1486 // mov (%rsp), %eax
1487 emit_bytes(0x8b, 0x04, 0x24);
1488 // test %eax, %eax
1489 emit_bytes(0x85, 0xc0);
1490 // je ZERO
1491 emit_bytes(0x0f, 0x84);
1492 void* zero = emit_branch_target32();
1493 // movss (%rsp), %xmm0
1494 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1495 // maxss 8(%rsp), %xmm0
1496 emit_bytes(0xf3, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1497 // jmp DONE
1498 emit_bytes(0xe9);
1499 void* done = emit_branch_target32();
1500 // ZERO:
1501 fix_branch(zero, code);
1502 // movss 8(%rsp), %xmm0
1503 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1504 // maxss (%rsp), %xmm0
1505 emit_bytes(0xf3, 0x0f, 0x5f, 0x04, 0x24);
1506 // DONE:
1507 fix_branch(done, code);
1508 // add $8, %rsp
1509 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1510 // movss %xmm0, (%rsp)
1511 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1512 }
Here is the call graph for this function:

◆ emit_f32_min() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_min ( )
inline

Definition at line 1447 of file x86_64.hpp.

1447 {
1448 auto icount = softfloat_instr(47, 44, 58);
1449 if constexpr(use_softfloat) {
1450 emit_f32_binop_softfloat(CHOOSE_FN(_sysio_f32_min));
1451 return;
1452 }
1453 // mov (%rsp), %eax
1454 emit_bytes(0x8b, 0x04, 0x24);
1455 // test %eax, %eax
1456 emit_bytes(0x85, 0xc0);
1457 // je ZERO
1458 emit_bytes(0x0f, 0x84);
1459 void* zero = emit_branch_target32();
1460 // movss 8(%rsp), %xmm0
1461 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1462 // minss (%rsp), %xmm0
1463 emit_bytes(0xf3, 0x0f, 0x5d, 0x04, 0x24);
1464 // jmp DONE
1465 emit_bytes(0xe9);
1466 void* done = emit_branch_target32();
1467 // ZERO:
1468 fix_branch(zero, code);
1469 // movss (%rsp), %xmm0
1470 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1471 // minss 8(%rsp), %xmm0
1472 emit_bytes(0xf3, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1473 // DONE:
1474 fix_branch(done, code);
1475 // add $8, %rsp
1476 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1477 // movss %xmm0, (%rsp)
1478 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1479 }
Here is the call graph for this function:

◆ emit_f32_min() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_min ( )
inline

Definition at line 1447 of file x86_64.hpp.

1447 {
1448 auto icount = softfloat_instr(47, 44, 58);
1449 if constexpr(use_softfloat) {
1450 emit_f32_binop_softfloat(CHOOSE_FN(_sysio_f32_min));
1451 return;
1452 }
1453 // mov (%rsp), %eax
1454 emit_bytes(0x8b, 0x04, 0x24);
1455 // test %eax, %eax
1456 emit_bytes(0x85, 0xc0);
1457 // je ZERO
1458 emit_bytes(0x0f, 0x84);
1459 void* zero = emit_branch_target32();
1460 // movss 8(%rsp), %xmm0
1461 emit_bytes(0xf3, 0x0f, 0x10, 0x44, 0x24, 0x08);
1462 // minss (%rsp), %xmm0
1463 emit_bytes(0xf3, 0x0f, 0x5d, 0x04, 0x24);
1464 // jmp DONE
1465 emit_bytes(0xe9);
1466 void* done = emit_branch_target32();
1467 // ZERO:
1468 fix_branch(zero, code);
1469 // movss (%rsp), %xmm0
1470 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1471 // minss 8(%rsp), %xmm0
1472 emit_bytes(0xf3, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1473 // DONE:
1474 fix_branch(done, code);
1475 // add $8, %rsp
1476 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1477 // movss %xmm0, (%rsp)
1478 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1479 }
Here is the call graph for this function:

◆ emit_f32_mul() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_mul ( )
inline

Definition at line 1439 of file x86_64.hpp.

1439 {
1440 auto icount = softfloat_instr(21, 44, 58);
1441 emit_f32_binop(0x59, CHOOSE_FN(_sysio_f32_mul));
1442 }

◆ emit_f32_mul() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_mul ( )
inline

Definition at line 1439 of file x86_64.hpp.

1439 {
1440 auto icount = softfloat_instr(21, 44, 58);
1441 emit_f32_binop(0x59, CHOOSE_FN(_sysio_f32_mul));
1442 }

◆ emit_f32_ne() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ne ( )
inline

Definition at line 985 of file x86_64.hpp.

985 {
986 auto icount = softfloat_instr(24,47,61);
987 emit_f32_relop(0x00, CHOOSE_FN(_sysio_f32_eq), false, true);
988 }

◆ emit_f32_ne() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_ne ( )
inline

Definition at line 985 of file x86_64.hpp.

985 {
986 auto icount = softfloat_instr(24,47,61);
987 emit_f32_relop(0x00, CHOOSE_FN(_sysio_f32_eq), false, true);
988 }

◆ emit_f32_nearest() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_nearest ( )
inline

Definition at line 1407 of file x86_64.hpp.

1407 {
1408 auto icount = softfloat_instr(12, 36, 54);
1409 if constexpr (use_softfloat) {
1410 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_nearest));
1411 }
1412 // roundss 0b1000, (%rsp), %xmm0
1413 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x08);
1414 // movss %xmm0, (%rsp)
1415 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1416 }

◆ emit_f32_nearest() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_nearest ( )
inline

Definition at line 1407 of file x86_64.hpp.

1407 {
1408 auto icount = softfloat_instr(12, 36, 54);
1409 if constexpr (use_softfloat) {
1410 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_nearest));
1411 }
1412 // roundss 0b1000, (%rsp), %xmm0
1413 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x08);
1414 // movss %xmm0, (%rsp)
1415 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1416 }

◆ emit_f32_neg() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_neg ( )
inline

Definition at line 1363 of file x86_64.hpp.

1363 {
1364 auto icount = fixed_size_instr(7);
1365 // popq %rax
1366 emit_bytes(0x58);
1367 // xorl 0x80000000, %eax
1368 emit_bytes(0x35);
1369 emit_operand32(0x80000000);
1370 // pushq %rax
1371 emit_bytes(0x50);
1372 }

◆ emit_f32_neg() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_neg ( )
inline

Definition at line 1363 of file x86_64.hpp.

1363 {
1364 auto icount = fixed_size_instr(7);
1365 // popq %rax
1366 emit_bytes(0x58);
1367 // xorl 0x80000000, %eax
1368 emit_bytes(0x35);
1369 emit_operand32(0x80000000);
1370 // pushq %rax
1371 emit_bytes(0x50);
1372 }

◆ emit_f32_reinterpret_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_reinterpret_i32 ( )
inline

Definition at line 2072 of file x86_64.hpp.

2072{ /* Nothing to do */ }

◆ emit_f32_reinterpret_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_reinterpret_i32 ( )
inline

Definition at line 2072 of file x86_64.hpp.

2072{ /* Nothing to do */ }

◆ emit_f32_sqrt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_sqrt ( )
inline

Definition at line 1418 of file x86_64.hpp.

1418 {
1419 auto icount = softfloat_instr(10, 36, 54);
1420 if constexpr (use_softfloat) {
1421 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_sqrt));
1422 }
1423 // sqrtss (%rsp), %xmm0
1424 emit_bytes(0xf3, 0x0f, 0x51, 0x04, 0x24);
1425 // movss %xmm0, (%rsp)
1426 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1427 }

◆ emit_f32_sqrt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_sqrt ( )
inline

Definition at line 1418 of file x86_64.hpp.

1418 {
1419 auto icount = softfloat_instr(10, 36, 54);
1420 if constexpr (use_softfloat) {
1421 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_sqrt));
1422 }
1423 // sqrtss (%rsp), %xmm0
1424 emit_bytes(0xf3, 0x0f, 0x51, 0x04, 0x24);
1425 // movss %xmm0, (%rsp)
1426 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1427 }

◆ emit_f32_store() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 583 of file x86_64.hpp.

583 {
584 auto icount = variable_size_instr(7, 15);
585 // movl ECX, (RAX)
586 emit_store_impl(offset, 0x89, 0x08);
587 }

◆ emit_f32_store() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 583 of file x86_64.hpp.

583 {
584 auto icount = variable_size_instr(7, 15);
585 // movl ECX, (RAX)
586 emit_store_impl(offset, 0x89, 0x08);
587 }

◆ emit_f32_sub() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_sub ( )
inline

Definition at line 1435 of file x86_64.hpp.

1435 {
1436 auto icount = softfloat_instr(21, 44, 58);
1437 emit_f32_binop(0x5c, CHOOSE_FN(_sysio_f32_sub));
1438 }

◆ emit_f32_sub() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_sub ( )
inline

Definition at line 1435 of file x86_64.hpp.

1435 {
1436 auto icount = softfloat_instr(21, 44, 58);
1437 emit_f32_binop(0x5c, CHOOSE_FN(_sysio_f32_sub));
1438 }

◆ emit_f32_trunc() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_trunc ( )
inline

Definition at line 1396 of file x86_64.hpp.

1396 {
1397 auto icount = softfloat_instr(12, 36, 54);
1398 if constexpr (use_softfloat) {
1399 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_trunc));
1400 }
1401 // roundss 0b1011, (%rsp), %xmm0
1402 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0b);
1403 // movss %xmm0, (%rsp)
1404 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1405 }

◆ emit_f32_trunc() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f32_trunc ( )
inline

Definition at line 1396 of file x86_64.hpp.

1396 {
1397 auto icount = softfloat_instr(12, 36, 54);
1398 if constexpr (use_softfloat) {
1399 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_trunc));
1400 }
1401 // roundss 0b1011, (%rsp), %xmm0
1402 emit_bytes(0x66, 0x0f, 0x3a, 0x0a, 0x04, 0x24, 0x0b);
1403 // movss %xmm0, (%rsp)
1404 emit_bytes(0xf3, 0x0f, 0x11, 0x04, 0x24);
1405 }

◆ emit_f64_abs() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_abs ( )
inline

Definition at line 1534 of file x86_64.hpp.

1534 {
1535 auto icount = fixed_size_instr(15);
1536 // popq %rcx;
1537 emit_bytes(0x59);
1538 // movabsq $0x7fffffffffffffff, %rax
1539 emit_bytes(0x48, 0xb8);
1540 emit_operand64(0x7fffffffffffffffull);
1541 // andq %rcx, %rax
1542 emit_bytes(0x48, 0x21, 0xc8);
1543 // pushq %rax
1544 emit_bytes(0x50);
1545 }

◆ emit_f64_abs() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_abs ( )
inline

Definition at line 1534 of file x86_64.hpp.

1534 {
1535 auto icount = fixed_size_instr(15);
1536 // popq %rcx;
1537 emit_bytes(0x59);
1538 // movabsq $0x7fffffffffffffff, %rax
1539 emit_bytes(0x48, 0xb8);
1540 emit_operand64(0x7fffffffffffffffull);
1541 // andq %rcx, %rax
1542 emit_bytes(0x48, 0x21, 0xc8);
1543 // pushq %rax
1544 emit_bytes(0x50);
1545 }

◆ emit_f64_add() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_add ( )
inline

Definition at line 1617 of file x86_64.hpp.

1617 {
1618 auto icount = softfloat_instr(21, 47, 61);
1619 emit_f64_binop(0x58, CHOOSE_FN(_sysio_f64_add));
1620 }

◆ emit_f64_add() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_add ( )
inline

Definition at line 1617 of file x86_64.hpp.

1617 {
1618 auto icount = softfloat_instr(21, 47, 61);
1619 emit_f64_binop(0x58, CHOOSE_FN(_sysio_f64_add));
1620 }

◆ emit_f64_ceil() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ceil ( )
inline

Definition at line 1560 of file x86_64.hpp.

1560 {
1561 auto icount = softfloat_instr(12, 38, 56);
1562 if constexpr (use_softfloat) {
1563 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_ceil));
1564 }
1565 // roundsd 0b1010, (%rsp), %xmm0
1566 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0a);
1567 // movsd %xmm0, (%rsp)
1568 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1569 }

◆ emit_f64_ceil() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ceil ( )
inline

Definition at line 1560 of file x86_64.hpp.

1560 {
1561 auto icount = softfloat_instr(12, 38, 56);
1562 if constexpr (use_softfloat) {
1563 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_ceil));
1564 }
1565 // roundsd 0b1010, (%rsp), %xmm0
1566 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0a);
1567 // movsd %xmm0, (%rsp)
1568 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1569 }

◆ emit_f64_const() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_const ( double value)
inline

Definition at line 696 of file x86_64.hpp.

696 {
697 auto icount = fixed_size_instr(11);
698 // movabsq $value, %rax
699 emit_bytes(0x48, 0xb8);
700 emit_operandf64(value);
701 // push %rax
702 emit_bytes(0x50);
703 }

◆ emit_f64_const() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_const ( double value)
inline

Definition at line 696 of file x86_64.hpp.

696 {
697 auto icount = fixed_size_instr(11);
698 // movabsq $value, %rax
699 emit_bytes(0x48, 0xb8);
700 emit_operandf64(value);
701 // push %rax
702 emit_bytes(0x50);
703 }

◆ emit_f64_convert_s_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_s_i32 ( )
inline

Definition at line 1993 of file x86_64.hpp.

1993 {
1994 auto icount = softfloat_instr(10, 37, 55);
1995 if constexpr (use_softfloat) {
1996 return emit_softfloat_unop(CHOOSE_FN(_sysio_i32_to_f64));
1997 }
1998 // cvtsi2sdl (%rsp), %xmm0
1999 emit_bytes(0xf2, 0x0f, 0x2a, 0x04, 0x24);
2000 // movsd %xmm0, (%rsp)
2001 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2002 }

◆ emit_f64_convert_s_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_s_i32 ( )
inline

Definition at line 1993 of file x86_64.hpp.

1993 {
1994 auto icount = softfloat_instr(10, 37, 55);
1995 if constexpr (use_softfloat) {
1996 return emit_softfloat_unop(CHOOSE_FN(_sysio_i32_to_f64));
1997 }
1998 // cvtsi2sdl (%rsp), %xmm0
1999 emit_bytes(0xf2, 0x0f, 0x2a, 0x04, 0x24);
2000 // movsd %xmm0, (%rsp)
2001 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2002 }

◆ emit_f64_convert_s_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_s_i64 ( )
inline

Definition at line 2013 of file x86_64.hpp.

2013 {
2014 auto icount = softfloat_instr(11, 38, 56);
2015 if constexpr (use_softfloat) {
2016 return emit_softfloat_unop(CHOOSE_FN(_sysio_i64_to_f64));
2017 }
2018 // cvtsi2sdq (%rsp), %xmm0
2019 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2020 // movsd %xmm0, (%rsp)
2021 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2022 }

◆ emit_f64_convert_s_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_s_i64 ( )
inline

Definition at line 2013 of file x86_64.hpp.

2013 {
2014 auto icount = softfloat_instr(11, 38, 56);
2015 if constexpr (use_softfloat) {
2016 return emit_softfloat_unop(CHOOSE_FN(_sysio_i64_to_f64));
2017 }
2018 // cvtsi2sdq (%rsp), %xmm0
2019 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2020 // movsd %xmm0, (%rsp)
2021 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2022 }

◆ emit_f64_convert_u_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_u_i32 ( )
inline

Definition at line 2003 of file x86_64.hpp.

2003 {
2004 auto icount = softfloat_instr(11, 37, 55);
2005 if constexpr (use_softfloat) {
2006 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui32_to_f64));
2007 }
2008 // cvtsi2sdq (%rsp), %xmm0
2009 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2010 // movsd %xmm0, (%rsp)
2011 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2012 }

◆ emit_f64_convert_u_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_u_i32 ( )
inline

Definition at line 2003 of file x86_64.hpp.

2003 {
2004 auto icount = softfloat_instr(11, 37, 55);
2005 if constexpr (use_softfloat) {
2006 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui32_to_f64));
2007 }
2008 // cvtsi2sdq (%rsp), %xmm0
2009 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0x04, 0x24);
2010 // movsd %xmm0, (%rsp)
2011 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2012 }

◆ emit_f64_convert_u_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_u_i64 ( )
inline

Definition at line 2023 of file x86_64.hpp.

2023 {
2024 auto icount = softfloat_instr(49, 38, 56);
2025 if constexpr (use_softfloat) {
2026 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui64_to_f64));
2027 }
2028 // movq (%rsp), %rax
2029 emit_bytes(0x48, 0x8b, 0x04, 0x24);
2030 // testq %rax, %rax
2031 emit_bytes(0x48, 0x85, 0xc0);
2032 // js LARGE
2033 emit_bytes(0x0f, 0x88);
2034 void * large = emit_branch_target32();
2035 // cvtsi2sdq %rax, %xmm0
2036 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2037 // jmp done
2038 emit_bytes(0xe9);
2039 void* done = emit_branch_target32();
2040 // LARGE:
2041 fix_branch(large, code);
2042 // movq %rax, %rcx
2043 emit_bytes(0x48, 0x89, 0xc1);
2044 // shrq %rax
2045 emit_bytes(0x48, 0xd1, 0xe8);
2046 // andl $1, %ecx
2047 emit_bytes(0x83, 0xe1, 0x01);
2048 // orq %rcx, %rax
2049 emit_bytes(0x48, 0x09, 0xc8);
2050 // cvtsi2sdq %rax, %xmm0
2051 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2052 // addsd %xmm0, %xmm0
2053 emit_bytes(0xf2, 0x0f, 0x58, 0xc0);
2054 // DONE:
2055 fix_branch(done, code);
2056 // movsd %xmm0, (%rsp)
2057 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2058 }
Here is the call graph for this function:

◆ emit_f64_convert_u_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_convert_u_i64 ( )
inline

Definition at line 2023 of file x86_64.hpp.

2023 {
2024 auto icount = softfloat_instr(49, 38, 56);
2025 if constexpr (use_softfloat) {
2026 return emit_softfloat_unop(CHOOSE_FN(_sysio_ui64_to_f64));
2027 }
2028 // movq (%rsp), %rax
2029 emit_bytes(0x48, 0x8b, 0x04, 0x24);
2030 // testq %rax, %rax
2031 emit_bytes(0x48, 0x85, 0xc0);
2032 // js LARGE
2033 emit_bytes(0x0f, 0x88);
2034 void * large = emit_branch_target32();
2035 // cvtsi2sdq %rax, %xmm0
2036 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2037 // jmp done
2038 emit_bytes(0xe9);
2039 void* done = emit_branch_target32();
2040 // LARGE:
2041 fix_branch(large, code);
2042 // movq %rax, %rcx
2043 emit_bytes(0x48, 0x89, 0xc1);
2044 // shrq %rax
2045 emit_bytes(0x48, 0xd1, 0xe8);
2046 // andl $1, %ecx
2047 emit_bytes(0x83, 0xe1, 0x01);
2048 // orq %rcx, %rax
2049 emit_bytes(0x48, 0x09, 0xc8);
2050 // cvtsi2sdq %rax, %xmm0
2051 emit_bytes(0xf2, 0x48, 0x0f, 0x2a, 0xc0);
2052 // addsd %xmm0, %xmm0
2053 emit_bytes(0xf2, 0x0f, 0x58, 0xc0);
2054 // DONE:
2055 fix_branch(done, code);
2056 // movsd %xmm0, (%rsp)
2057 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2058 }
Here is the call graph for this function:

◆ emit_f64_copysign() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_copysign ( )
inline

Definition at line 1700 of file x86_64.hpp.

1700 {
1701 auto icount = fixed_size_instr(25);
1702 // popq %rcx;
1703 emit_bytes(0x59);
1704 // movabsq 0x8000000000000000, %rax
1705 emit_bytes(0x48, 0xb8);
1706 emit_operand64(0x8000000000000000ull);
1707 // andq %rax, %rcx
1708 emit_bytes(0x48, 0x21, 0xc1);
1709 // popq %rdx
1710 emit_bytes(0x5a);
1711 // notq %rax
1712 emit_bytes(0x48, 0xf7, 0xd0);
1713 // andq %rdx, %rax
1714 emit_bytes(0x48, 0x21, 0xd0);
1715 // orq %rcx, %rax
1716 emit_bytes(0x48, 0x09, 0xc8);
1717 // pushq %rax
1718 emit_bytes(0x50);
1719 }

◆ emit_f64_copysign() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_copysign ( )
inline

Definition at line 1700 of file x86_64.hpp.

1700 {
1701 auto icount = fixed_size_instr(25);
1702 // popq %rcx;
1703 emit_bytes(0x59);
1704 // movabsq 0x8000000000000000, %rax
1705 emit_bytes(0x48, 0xb8);
1706 emit_operand64(0x8000000000000000ull);
1707 // andq %rax, %rcx
1708 emit_bytes(0x48, 0x21, 0xc1);
1709 // popq %rdx
1710 emit_bytes(0x5a);
1711 // notq %rax
1712 emit_bytes(0x48, 0xf7, 0xd0);
1713 // andq %rdx, %rax
1714 emit_bytes(0x48, 0x21, 0xd0);
1715 // orq %rcx, %rax
1716 emit_bytes(0x48, 0x09, 0xc8);
1717 // pushq %rax
1718 emit_bytes(0x50);
1719 }

◆ emit_f64_div() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_div ( )
inline

Definition at line 1629 of file x86_64.hpp.

1629 {
1630 auto icount = softfloat_instr(21, 47, 61);
1631 emit_f64_binop(0x5e, CHOOSE_FN(_sysio_f64_div));
1632 }

◆ emit_f64_div() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_div ( )
inline

Definition at line 1629 of file x86_64.hpp.

1629 {
1630 auto icount = softfloat_instr(21, 47, 61);
1631 emit_f64_binop(0x5e, CHOOSE_FN(_sysio_f64_div));
1632 }

◆ emit_f64_eq() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_eq ( )
inline

Definition at line 1011 of file x86_64.hpp.

1011 {
1012 auto icount = softfloat_instr(25,47,61);
1013 emit_f64_relop(0x00, CHOOSE_FN(_sysio_f64_eq), false, false);
1014 }

◆ emit_f64_eq() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_eq ( )
inline

Definition at line 1011 of file x86_64.hpp.

1011 {
1012 auto icount = softfloat_instr(25,47,61);
1013 emit_f64_relop(0x00, CHOOSE_FN(_sysio_f64_eq), false, false);
1014 }

◆ emit_f64_floor() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_floor ( )
inline

Definition at line 1571 of file x86_64.hpp.

1571 {
1572 auto icount = softfloat_instr(12, 38, 56);
1573 if constexpr (use_softfloat) {
1574 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_floor));
1575 }
1576 // roundsd 0b1001, (%rsp), %xmm0
1577 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x09);
1578 // movss %xmm0, (%rsp)
1579 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1580 }

◆ emit_f64_floor() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_floor ( )
inline

Definition at line 1571 of file x86_64.hpp.

1571 {
1572 auto icount = softfloat_instr(12, 38, 56);
1573 if constexpr (use_softfloat) {
1574 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_floor));
1575 }
1576 // roundsd 0b1001, (%rsp), %xmm0
1577 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x09);
1578 // movss %xmm0, (%rsp)
1579 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1580 }

◆ emit_f64_ge() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ge ( )
inline

Definition at line 1036 of file x86_64.hpp.

1036 {
1037 auto icount = softfloat_instr(25,47,61);
1038 emit_f64_relop(0x02, CHOOSE_FN(_sysio_f64_le), true, false);
1039 }

◆ emit_f64_ge() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ge ( )
inline

Definition at line 1036 of file x86_64.hpp.

1036 {
1037 auto icount = softfloat_instr(25,47,61);
1038 emit_f64_relop(0x02, CHOOSE_FN(_sysio_f64_le), true, false);
1039 }

◆ emit_f64_gt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_gt ( )
inline

Definition at line 1026 of file x86_64.hpp.

1026 {
1027 auto icount = softfloat_instr(25,47,61);
1028 emit_f64_relop(0x01, CHOOSE_FN(_sysio_f64_lt), true, false);
1029 }

◆ emit_f64_gt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_gt ( )
inline

Definition at line 1026 of file x86_64.hpp.

1026 {
1027 auto icount = softfloat_instr(25,47,61);
1028 emit_f64_relop(0x01, CHOOSE_FN(_sysio_f64_lt), true, false);
1029 }

◆ emit_f64_le() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_le ( )
inline

Definition at line 1031 of file x86_64.hpp.

1031 {
1032 auto icount = softfloat_instr(25,47,61);
1033 emit_f64_relop(0x02, CHOOSE_FN(_sysio_f64_le), false, false);
1034 }

◆ emit_f64_le() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_le ( )
inline

Definition at line 1031 of file x86_64.hpp.

1031 {
1032 auto icount = softfloat_instr(25,47,61);
1033 emit_f64_relop(0x02, CHOOSE_FN(_sysio_f64_le), false, false);
1034 }

◆ emit_f64_load() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 505 of file x86_64.hpp.

505 {
506 auto icount = variable_size_instr(8, 16);
507 // movq (RAX), RAX
508 emit_load_impl(offset, 0x48, 0x8b, 0x00);
509 }

◆ emit_f64_load() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 505 of file x86_64.hpp.

505 {
506 auto icount = variable_size_instr(8, 16);
507 // movq (RAX), RAX
508 emit_load_impl(offset, 0x48, 0x8b, 0x00);
509 }

◆ emit_f64_lt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_lt ( )
inline

Definition at line 1021 of file x86_64.hpp.

1021 {
1022 auto icount = softfloat_instr(25,47,61);
1023 emit_f64_relop(0x01, CHOOSE_FN(_sysio_f64_lt), false, false);
1024 }

◆ emit_f64_lt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_lt ( )
inline

Definition at line 1021 of file x86_64.hpp.

1021 {
1022 auto icount = softfloat_instr(25,47,61);
1023 emit_f64_relop(0x01, CHOOSE_FN(_sysio_f64_lt), false, false);
1024 }

◆ emit_f64_max() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_max ( )
inline

Definition at line 1666 of file x86_64.hpp.

1666 {
1667 auto icount = softfloat_instr(49, 47, 61);
1668 if(use_softfloat) {
1669 emit_f64_binop_softfloat(CHOOSE_FN(_sysio_f64_max));
1670 return;
1671 }
1672 // mov (%rsp), %rax
1673 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1674 // test %rax, %rax
1675 emit_bytes(0x48, 0x85, 0xc0);
1676 // je ZERO
1677 emit_bytes(0x0f, 0x84);
1678 void* zero = emit_branch_target32();
1679 // maxsd (%rsp), %xmm0
1680 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1681 // maxsd 8(%rsp), %xmm0
1682 emit_bytes(0xf2, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1683 // jmp DONE
1684 emit_bytes(0xe9);
1685 void* done = emit_branch_target32();
1686 // ZERO:
1687 fix_branch(zero, code);
1688 // movsd 8(%rsp), %xmm0
1689 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1690 // maxsd (%rsp), %xmm0
1691 emit_bytes(0xf2, 0x0f, 0x5f, 0x04, 0x24);
1692 // DONE:
1693 fix_branch(done, code);
1694 // add $8, %rsp
1695 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1696 // movsd %xmm0, (%rsp)
1697 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1698 }
Here is the call graph for this function:

◆ emit_f64_max() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_max ( )
inline

Definition at line 1666 of file x86_64.hpp.

1666 {
1667 auto icount = softfloat_instr(49, 47, 61);
1668 if(use_softfloat) {
1669 emit_f64_binop_softfloat(CHOOSE_FN(_sysio_f64_max));
1670 return;
1671 }
1672 // mov (%rsp), %rax
1673 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1674 // test %rax, %rax
1675 emit_bytes(0x48, 0x85, 0xc0);
1676 // je ZERO
1677 emit_bytes(0x0f, 0x84);
1678 void* zero = emit_branch_target32();
1679 // maxsd (%rsp), %xmm0
1680 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1681 // maxsd 8(%rsp), %xmm0
1682 emit_bytes(0xf2, 0x0f, 0x5f, 0x44, 0x24, 0x08);
1683 // jmp DONE
1684 emit_bytes(0xe9);
1685 void* done = emit_branch_target32();
1686 // ZERO:
1687 fix_branch(zero, code);
1688 // movsd 8(%rsp), %xmm0
1689 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1690 // maxsd (%rsp), %xmm0
1691 emit_bytes(0xf2, 0x0f, 0x5f, 0x04, 0x24);
1692 // DONE:
1693 fix_branch(done, code);
1694 // add $8, %rsp
1695 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1696 // movsd %xmm0, (%rsp)
1697 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1698 }
Here is the call graph for this function:

◆ emit_f64_min() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_min ( )
inline

Definition at line 1633 of file x86_64.hpp.

1633 {
1634 auto icount = softfloat_instr(49, 47, 61);
1635 if(use_softfloat) {
1636 emit_f64_binop_softfloat(CHOOSE_FN(_sysio_f64_min));
1637 return;
1638 }
1639 // mov (%rsp), %rax
1640 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1641 // test %rax, %rax
1642 emit_bytes(0x48, 0x85, 0xc0);
1643 // je ZERO
1644 emit_bytes(0x0f, 0x84);
1645 void* zero = emit_branch_target32();
1646 // movsd 8(%rsp), %xmm0
1647 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1648 // minsd (%rsp), %xmm0
1649 emit_bytes(0xf2, 0x0f, 0x5d, 0x04, 0x24);
1650 // jmp DONE
1651 emit_bytes(0xe9);
1652 void* done = emit_branch_target32();
1653 // ZERO:
1654 fix_branch(zero, code);
1655 // movsd (%rsp), %xmm0
1656 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1657 // minsd 8(%rsp), %xmm0
1658 emit_bytes(0xf2, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1659 // DONE:
1660 fix_branch(done, code);
1661 // add $8, %rsp
1662 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1663 // movsd %xmm0, (%rsp)
1664 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1665 }
Here is the call graph for this function:

◆ emit_f64_min() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_min ( )
inline

Definition at line 1633 of file x86_64.hpp.

1633 {
1634 auto icount = softfloat_instr(49, 47, 61);
1635 if(use_softfloat) {
1636 emit_f64_binop_softfloat(CHOOSE_FN(_sysio_f64_min));
1637 return;
1638 }
1639 // mov (%rsp), %rax
1640 emit_bytes(0x48, 0x8b, 0x04, 0x24);
1641 // test %rax, %rax
1642 emit_bytes(0x48, 0x85, 0xc0);
1643 // je ZERO
1644 emit_bytes(0x0f, 0x84);
1645 void* zero = emit_branch_target32();
1646 // movsd 8(%rsp), %xmm0
1647 emit_bytes(0xf2, 0x0f, 0x10, 0x44, 0x24, 0x08);
1648 // minsd (%rsp), %xmm0
1649 emit_bytes(0xf2, 0x0f, 0x5d, 0x04, 0x24);
1650 // jmp DONE
1651 emit_bytes(0xe9);
1652 void* done = emit_branch_target32();
1653 // ZERO:
1654 fix_branch(zero, code);
1655 // movsd (%rsp), %xmm0
1656 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1657 // minsd 8(%rsp), %xmm0
1658 emit_bytes(0xf2, 0x0f, 0x5d, 0x44, 0x24, 0x08);
1659 // DONE:
1660 fix_branch(done, code);
1661 // add $8, %rsp
1662 emit_bytes(0x48, 0x83, 0xc4, 0x08);
1663 // movsd %xmm0, (%rsp)
1664 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1665 }
Here is the call graph for this function:

◆ emit_f64_mul() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_mul ( )
inline

Definition at line 1625 of file x86_64.hpp.

1625 {
1626 auto icount = softfloat_instr(21, 47, 61);
1627 emit_f64_binop(0x59, CHOOSE_FN(_sysio_f64_mul));
1628 }

◆ emit_f64_mul() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_mul ( )
inline

Definition at line 1625 of file x86_64.hpp.

1625 {
1626 auto icount = softfloat_instr(21, 47, 61);
1627 emit_f64_binop(0x59, CHOOSE_FN(_sysio_f64_mul));
1628 }

◆ emit_f64_ne() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ne ( )
inline

Definition at line 1016 of file x86_64.hpp.

1016 {
1017 auto icount = softfloat_instr(24,49,63);
1018 emit_f64_relop(0x00, CHOOSE_FN(_sysio_f64_eq), false, true);
1019 }

◆ emit_f64_ne() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_ne ( )
inline

Definition at line 1016 of file x86_64.hpp.

1016 {
1017 auto icount = softfloat_instr(24,49,63);
1018 emit_f64_relop(0x00, CHOOSE_FN(_sysio_f64_eq), false, true);
1019 }

◆ emit_f64_nearest() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_nearest ( )
inline

Definition at line 1593 of file x86_64.hpp.

1593 {
1594 auto icount = softfloat_instr(12, 38, 56);
1595 if constexpr (use_softfloat) {
1596 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_nearest));
1597 }
1598 // roundsd 0b1000, (%rsp), %xmm0
1599 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x08);
1600 // movss %xmm0, (%rsp)
1601 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1602 }

◆ emit_f64_nearest() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_nearest ( )
inline

Definition at line 1593 of file x86_64.hpp.

1593 {
1594 auto icount = softfloat_instr(12, 38, 56);
1595 if constexpr (use_softfloat) {
1596 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_nearest));
1597 }
1598 // roundsd 0b1000, (%rsp), %xmm0
1599 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x08);
1600 // movss %xmm0, (%rsp)
1601 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1602 }

◆ emit_f64_neg() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_neg ( )
inline

Definition at line 1547 of file x86_64.hpp.

1547 {
1548 auto icount = fixed_size_instr(15);
1549 // popq %rcx;
1550 emit_bytes(0x59);
1551 // movabsq $0x8000000000000000, %rax
1552 emit_bytes(0x48, 0xb8);
1553 emit_operand64(0x8000000000000000ull);
1554 // xorq %rcx, %rax
1555 emit_bytes(0x48, 0x31, 0xc8);
1556 // pushq %rax
1557 emit_bytes(0x50);
1558 }

◆ emit_f64_neg() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_neg ( )
inline

Definition at line 1547 of file x86_64.hpp.

1547 {
1548 auto icount = fixed_size_instr(15);
1549 // popq %rcx;
1550 emit_bytes(0x59);
1551 // movabsq $0x8000000000000000, %rax
1552 emit_bytes(0x48, 0xb8);
1553 emit_operand64(0x8000000000000000ull);
1554 // xorq %rcx, %rax
1555 emit_bytes(0x48, 0x31, 0xc8);
1556 // pushq %rax
1557 emit_bytes(0x50);
1558 }

◆ emit_f64_promote_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_promote_f32 ( )
inline

Definition at line 2059 of file x86_64.hpp.

2059 {
2060 auto icount = softfloat_instr(10, 37, 55);
2061 if constexpr (use_softfloat) {
2062 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_promote));
2063 }
2064 // cvtss2sd (%rsp), %xmm0
2065 emit_bytes(0xf3, 0x0f, 0x5a, 0x04, 0x24);
2066 // movsd %xmm0, (%rsp)
2067 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2068 }

◆ emit_f64_promote_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_promote_f32 ( )
inline

Definition at line 2059 of file x86_64.hpp.

2059 {
2060 auto icount = softfloat_instr(10, 37, 55);
2061 if constexpr (use_softfloat) {
2062 return emit_softfloat_unop(CHOOSE_FN(_sysio_f32_promote));
2063 }
2064 // cvtss2sd (%rsp), %xmm0
2065 emit_bytes(0xf3, 0x0f, 0x5a, 0x04, 0x24);
2066 // movsd %xmm0, (%rsp)
2067 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
2068 }

◆ emit_f64_reinterpret_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_reinterpret_i64 ( )
inline

Definition at line 2073 of file x86_64.hpp.

2073{ /* Nothing to do */ }

◆ emit_f64_reinterpret_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_reinterpret_i64 ( )
inline

Definition at line 2073 of file x86_64.hpp.

2073{ /* Nothing to do */ }

◆ emit_f64_sqrt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_sqrt ( )
inline

Definition at line 1604 of file x86_64.hpp.

1604 {
1605 auto icount = softfloat_instr(10, 38, 56);
1606 if constexpr (use_softfloat) {
1607 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_sqrt));
1608 }
1609 // sqrtss (%rsp), %xmm0
1610 emit_bytes(0xf2, 0x0f, 0x51, 0x04, 0x24);
1611 // movss %xmm0, (%rsp)
1612 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1613 }

◆ emit_f64_sqrt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_sqrt ( )
inline

Definition at line 1604 of file x86_64.hpp.

1604 {
1605 auto icount = softfloat_instr(10, 38, 56);
1606 if constexpr (use_softfloat) {
1607 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_sqrt));
1608 }
1609 // sqrtss (%rsp), %xmm0
1610 emit_bytes(0xf2, 0x0f, 0x51, 0x04, 0x24);
1611 // movss %xmm0, (%rsp)
1612 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1613 }

◆ emit_f64_store() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 589 of file x86_64.hpp.

589 {
590 auto icount = variable_size_instr(8, 16);
591 // movl ECX, (RAX)
592 emit_store_impl(offset, 0x48, 0x89, 0x08);
593 }

◆ emit_f64_store() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 589 of file x86_64.hpp.

589 {
590 auto icount = variable_size_instr(8, 16);
591 // movl ECX, (RAX)
592 emit_store_impl(offset, 0x48, 0x89, 0x08);
593 }

◆ emit_f64_sub() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_sub ( )
inline

Definition at line 1621 of file x86_64.hpp.

1621 {
1622 auto icount = softfloat_instr(21, 47, 61);
1623 emit_f64_binop(0x5c, CHOOSE_FN(_sysio_f64_sub));
1624 }

◆ emit_f64_sub() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_sub ( )
inline

Definition at line 1621 of file x86_64.hpp.

1621 {
1622 auto icount = softfloat_instr(21, 47, 61);
1623 emit_f64_binop(0x5c, CHOOSE_FN(_sysio_f64_sub));
1624 }

◆ emit_f64_trunc() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_trunc ( )
inline

Definition at line 1582 of file x86_64.hpp.

1582 {
1583 auto icount = softfloat_instr(12, 38, 56);
1584 if constexpr (use_softfloat) {
1585 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_trunc));
1586 }
1587 // roundsd 0b1011, (%rsp), %xmm0
1588 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0b);
1589 // movss %xmm0, (%rsp)
1590 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1591 }

◆ emit_f64_trunc() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_f64_trunc ( )
inline

Definition at line 1582 of file x86_64.hpp.

1582 {
1583 auto icount = softfloat_instr(12, 38, 56);
1584 if constexpr (use_softfloat) {
1585 return emit_softfloat_unop(CHOOSE_FN(_sysio_f64_trunc));
1586 }
1587 // roundsd 0b1011, (%rsp), %xmm0
1588 emit_bytes(0x66, 0x0f, 0x3a, 0x0b, 0x04, 0x24, 0x0b);
1589 // movss %xmm0, (%rsp)
1590 emit_bytes(0xf2, 0x0f, 0x11, 0x04, 0x24);
1591 }

◆ emit_get_global() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_get_global ( uint32_t globalidx)
inline

Definition at line 447 of file x86_64.hpp.

447 {
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) {
452 case types::i32:
453 case types::f32:
454 // movabsq $ptr, %rax
455 emit_bytes(0x48, 0xb8);
456 emit_operand_ptr(ptr);
457 // movl (%rax), eax
458 emit_bytes(0x8b, 0x00);
459 // push %rax
460 emit_bytes(0x50);
461 break;
462 case types::i64:
463 case types::f64:
464 // movabsq $ptr, %rax
465 emit_bytes(0x48, 0xb8);
466 emit_operand_ptr(ptr);
467 // movl (%rax), %rax
468 emit_bytes(0x48, 0x8b, 0x00);
469 // push %rax
470 emit_bytes(0x50);
471 break;
472 }
473 }
guarded_vector< global_variable > globals
Definition types.hpp:174

◆ emit_get_global() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_get_global ( uint32_t globalidx)
inline

Definition at line 447 of file x86_64.hpp.

447 {
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) {
452 case types::i32:
453 case types::f32:
454 // movabsq $ptr, %rax
455 emit_bytes(0x48, 0xb8);
456 emit_operand_ptr(ptr);
457 // movl (%rax), eax
458 emit_bytes(0x8b, 0x00);
459 // push %rax
460 emit_bytes(0x50);
461 break;
462 case types::i64:
463 case types::f64:
464 // movabsq $ptr, %rax
465 emit_bytes(0x48, 0xb8);
466 emit_operand_ptr(ptr);
467 // movl (%rax), %rax
468 emit_bytes(0x48, 0x8b, 0x00);
469 // push %rax
470 emit_bytes(0x50);
471 break;
472 }
473 }

◆ emit_get_local() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_get_local ( uint32_t local_idx)
inline

Definition at line 380 of file x86_64.hpp.

380 {
381 auto icount = fixed_size_instr(8);
382 // stack layout:
383 // param0 <----- %rbp + 8*(nparams + 1)
384 // param1
385 // param2
386 // ...
387 // paramN
388 // return address
389 // old %rbp <------ %rbp
390 // local0 <------ %rbp - 8
391 // local1
392 // ...
393 // localN
394 if (local_idx < _ft->param_types.size()) {
395 // mov 8*(local_idx)(%RBP), RAX
396 emit_bytes(0x48, 0x8b, 0x85);
397 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
398 // push RAX
399 emit_bytes(0x50);
400 } else {
401 // mov -8*(local_idx+1)(%RBP), RAX
402 emit_bytes(0x48, 0x8b, 0x85);
403 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
404 // push RAX
405 emit_bytes(0x50);
406 }
407 }
guarded_vector< value_type > param_types
Definition types.hpp:44

◆ emit_get_local() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_get_local ( uint32_t local_idx)
inline

Definition at line 380 of file x86_64.hpp.

380 {
381 auto icount = fixed_size_instr(8);
382 // stack layout:
383 // param0 <----- %rbp + 8*(nparams + 1)
384 // param1
385 // param2
386 // ...
387 // paramN
388 // return address
389 // old %rbp <------ %rbp
390 // local0 <------ %rbp - 8
391 // local1
392 // ...
393 // localN
394 if (local_idx < _ft->param_types.size()) {
395 // mov 8*(local_idx)(%RBP), RAX
396 emit_bytes(0x48, 0x8b, 0x85);
397 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
398 // push RAX
399 emit_bytes(0x50);
400 } else {
401 // mov -8*(local_idx+1)(%RBP), RAX
402 emit_bytes(0x48, 0x8b, 0x85);
403 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
404 // push RAX
405 emit_bytes(0x50);
406 }
407 }

◆ emit_grow_memory() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_grow_memory ( )
inline

Definition at line 645 of file x86_64.hpp.

645 {
646 auto icount = variable_size_instr(21, 39);
647 // popq %rax
648 emit_bytes(0x58);
649 emit_setup_backtrace();
650 // pushq %rdi
651 emit_bytes(0x57);
652 // pushq %rsi
653 emit_bytes(0x56);
654 // movq %rax, %rsi
655 emit_bytes(0x48, 0x89, 0xc6);
656 // movabsq $grow_memory, %rax
657 emit_bytes(0x48, 0xb8);
658 emit_operand_ptr(&grow_memory);
659 // call *%rax
660 emit_bytes(0xff, 0xd0);
661 // pop %rsi
662 emit_bytes(0x5e);
663 // pop %rdi
664 emit_bytes(0x5f);
665 emit_restore_backtrace();
666 // push %rax
667 emit_bytes(0x50);
668 }

◆ emit_grow_memory() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_grow_memory ( )
inline

Definition at line 645 of file x86_64.hpp.

645 {
646 auto icount = variable_size_instr(21, 39);
647 // popq %rax
648 emit_bytes(0x58);
649 emit_setup_backtrace();
650 // pushq %rdi
651 emit_bytes(0x57);
652 // pushq %rsi
653 emit_bytes(0x56);
654 // movq %rax, %rsi
655 emit_bytes(0x48, 0x89, 0xc6);
656 // movabsq $grow_memory, %rax
657 emit_bytes(0x48, 0xb8);
658 emit_operand_ptr(&grow_memory);
659 // call *%rax
660 emit_bytes(0xff, 0xd0);
661 // pop %rsi
662 emit_bytes(0x5e);
663 // pop %rdi
664 emit_bytes(0x5f);
665 emit_restore_backtrace();
666 // push %rax
667 emit_bytes(0x50);
668 }

◆ emit_i32_add() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_add ( )
inline

Definition at line 1116 of file x86_64.hpp.

1116 {
1117 auto icount = fixed_size_instr(5);
1118 emit_i32_binop(0x01, 0xc8, 0x50);
1119 }

◆ emit_i32_add() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_add ( )
inline

Definition at line 1116 of file x86_64.hpp.

1116 {
1117 auto icount = fixed_size_instr(5);
1118 emit_i32_binop(0x01, 0xc8, 0x50);
1119 }

◆ emit_i32_and() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_and ( )
inline

Definition at line 1168 of file x86_64.hpp.

1168 {
1169 auto icount = fixed_size_instr(5);
1170 emit_i32_binop(0x21, 0xc8, 0x50);
1171 }

◆ emit_i32_and() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_and ( )
inline

Definition at line 1168 of file x86_64.hpp.

1168 {
1169 auto icount = fixed_size_instr(5);
1170 emit_i32_binop(0x21, 0xc8, 0x50);
1171 }

◆ emit_i32_clz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_clz ( )
inline

Definition at line 1054 of file x86_64.hpp.

1054 {
1055 auto icount = fixed_size_instr(has_tzcnt()?6:18);
1056 if(!has_tzcnt()) {
1057 // pop %rax
1058 emit_bytes(0x58);
1059 // mov $-1, %ecx
1060 emit_bytes(0xb9, 0xff, 0xff, 0xff, 0xff);
1061 // bsr %eax, %eax
1062 emit_bytes(0x0f, 0xbd, 0xc0);
1063 // cmovz %ecx, %eax
1064 emit_bytes(0x0f, 0x44, 0xc1);
1065 // sub $31, %eax
1066 emit_bytes(0x83, 0xe8, 0x1f);
1067 // neg %eax
1068 emit_bytes(0xf7, 0xd8);
1069 // push %rax
1070 emit_bytes(0x50);
1071 } else {
1072 // popq %rax
1073 emit_bytes(0x58);
1074 // lzcntl %eax, %eax
1075 emit_bytes(0xf3, 0x0f, 0xbd, 0xc0);
1076 // pushq %rax
1077 emit_bytes(0x50);
1078 }
1079 }
Here is the call graph for this function:

◆ emit_i32_clz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_clz ( )
inline

Definition at line 1054 of file x86_64.hpp.

1054 {
1055 auto icount = fixed_size_instr(has_tzcnt()?6:18);
1056 if(!has_tzcnt()) {
1057 // pop %rax
1058 emit_bytes(0x58);
1059 // mov $-1, %ecx
1060 emit_bytes(0xb9, 0xff, 0xff, 0xff, 0xff);
1061 // bsr %eax, %eax
1062 emit_bytes(0x0f, 0xbd, 0xc0);
1063 // cmovz %ecx, %eax
1064 emit_bytes(0x0f, 0x44, 0xc1);
1065 // sub $31, %eax
1066 emit_bytes(0x83, 0xe8, 0x1f);
1067 // neg %eax
1068 emit_bytes(0xf7, 0xd8);
1069 // push %rax
1070 emit_bytes(0x50);
1071 } else {
1072 // popq %rax
1073 emit_bytes(0x58);
1074 // lzcntl %eax, %eax
1075 emit_bytes(0xf3, 0x0f, 0xbd, 0xc0);
1076 // pushq %rax
1077 emit_bytes(0x50);
1078 }
1079 }
Here is the call graph for this function:

◆ emit_i32_const() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_const ( uint32_t value)
inline

Definition at line 670 of file x86_64.hpp.

670 {
671 auto icount = fixed_size_instr(6);
672 // mov $value, %eax
673 emit_bytes(0xb8);
674 emit_operand32(value);
675 // push %rax
676 emit_bytes(0x50);
677 }

◆ emit_i32_const() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_const ( uint32_t value)
inline

Definition at line 670 of file x86_64.hpp.

670 {
671 auto icount = fixed_size_instr(6);
672 // mov $value, %eax
673 emit_bytes(0xb8);
674 emit_operand32(value);
675 // push %rax
676 emit_bytes(0x50);
677 }

◆ emit_i32_ctz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ctz ( )
inline

Definition at line 1081 of file x86_64.hpp.

1081 {
1082 auto icount = fixed_size_instr(has_tzcnt()?6:13);
1083 if(!has_tzcnt()) {
1084 // pop %rax
1085 emit_bytes(0x58);
1086 // mov $32, %ecx
1087 emit_bytes(0xb9, 0x20, 0x00, 0x00, 0x00);
1088 // bsf %eax, %eax
1089 emit_bytes(0x0f, 0xbc, 0xc0);
1090 // cmovz %ecx, %eax
1091 emit_bytes(0x0f, 0x44, 0xc1);
1092 // push %rax
1093 emit_bytes(0x50);
1094 } else {
1095 // popq %rax
1096 emit_bytes(0x58);
1097 // tzcntl %eax, %eax
1098 emit_bytes(0xf3, 0x0f, 0xbc, 0xc0);
1099 // pushq %rax
1100 emit_bytes(0x50);
1101 }
1102 }
Here is the call graph for this function:

◆ emit_i32_ctz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ctz ( )
inline

Definition at line 1081 of file x86_64.hpp.

1081 {
1082 auto icount = fixed_size_instr(has_tzcnt()?6:13);
1083 if(!has_tzcnt()) {
1084 // pop %rax
1085 emit_bytes(0x58);
1086 // mov $32, %ecx
1087 emit_bytes(0xb9, 0x20, 0x00, 0x00, 0x00);
1088 // bsf %eax, %eax
1089 emit_bytes(0x0f, 0xbc, 0xc0);
1090 // cmovz %ecx, %eax
1091 emit_bytes(0x0f, 0x44, 0xc1);
1092 // push %rax
1093 emit_bytes(0x50);
1094 } else {
1095 // popq %rax
1096 emit_bytes(0x58);
1097 // tzcntl %eax, %eax
1098 emit_bytes(0xf3, 0x0f, 0xbc, 0xc0);
1099 // pushq %rax
1100 emit_bytes(0x50);
1101 }
1102 }
Here is the call graph for this function:

◆ emit_i32_div_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_div_s ( )
inline

Definition at line 1129 of file x86_64.hpp.

1129 {
1130 auto icount = fixed_size_instr(6);
1131 emit_i32_binop(0x99, 0xf7, 0xf9, 0x50);
1132 }

◆ emit_i32_div_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_div_s ( )
inline

Definition at line 1129 of file x86_64.hpp.

1129 {
1130 auto icount = fixed_size_instr(6);
1131 emit_i32_binop(0x99, 0xf7, 0xf9, 0x50);
1132 }

◆ emit_i32_div_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_div_u ( )
inline

Definition at line 1133 of file x86_64.hpp.

1133 {
1134 auto icount = fixed_size_instr(7);
1135 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x50);
1136 }

◆ emit_i32_div_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_div_u ( )
inline

Definition at line 1133 of file x86_64.hpp.

1133 {
1134 auto icount = fixed_size_instr(7);
1135 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x50);
1136 }

◆ emit_i32_eq() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_eq ( )
inline

Definition at line 720 of file x86_64.hpp.

720 {
721 auto icount = fixed_size_instr(11);
722 // sete %dl
723 emit_i32_relop(0x94);
724 }

◆ emit_i32_eq() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_eq ( )
inline

Definition at line 720 of file x86_64.hpp.

720 {
721 auto icount = fixed_size_instr(11);
722 // sete %dl
723 emit_i32_relop(0x94);
724 }

◆ emit_i32_eqz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_eqz ( )
inline

Definition at line 705 of file x86_64.hpp.

705 {
706 auto icount = fixed_size_instr(10);
707 // pop %rax
708 emit_bytes(0x58);
709 // xor %rcx, %rcx
710 emit_bytes(0x48, 0x31, 0xc9);
711 // test %eax, %eax
712 emit_bytes(0x85, 0xc0);
713 // setz %cl
714 emit_bytes(0x0f, 0x94, 0xc1);
715 // push %rcx
716 emit_bytes(0x51);
717 }

◆ emit_i32_eqz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_eqz ( )
inline

Definition at line 705 of file x86_64.hpp.

705 {
706 auto icount = fixed_size_instr(10);
707 // pop %rax
708 emit_bytes(0x58);
709 // xor %rcx, %rcx
710 emit_bytes(0x48, 0x31, 0xc9);
711 // test %eax, %eax
712 emit_bytes(0x85, 0xc0);
713 // setz %cl
714 emit_bytes(0x0f, 0x94, 0xc1);
715 // push %rcx
716 emit_bytes(0x51);
717 }

◆ emit_i32_ge_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ge_s ( )
inline

Definition at line 768 of file x86_64.hpp.

768 {
769 auto icount = fixed_size_instr(11);
770 // setge %dl
771 emit_i32_relop(0x9d);
772 }

◆ emit_i32_ge_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ge_s ( )
inline

Definition at line 768 of file x86_64.hpp.

768 {
769 auto icount = fixed_size_instr(11);
770 // setge %dl
771 emit_i32_relop(0x9d);
772 }

◆ emit_i32_ge_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ge_u ( )
inline

Definition at line 774 of file x86_64.hpp.

774 {
775 auto icount = fixed_size_instr(11);
776 // setae %dl
777 emit_i32_relop(0x93);
778 }

◆ emit_i32_ge_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ge_u ( )
inline

Definition at line 774 of file x86_64.hpp.

774 {
775 auto icount = fixed_size_instr(11);
776 // setae %dl
777 emit_i32_relop(0x93);
778 }

◆ emit_i32_gt_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_gt_s ( )
inline

Definition at line 744 of file x86_64.hpp.

744 {
745 auto icount = fixed_size_instr(11);
746 // setg %dl
747 emit_i32_relop(0x9f);
748 }

◆ emit_i32_gt_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_gt_s ( )
inline

Definition at line 744 of file x86_64.hpp.

744 {
745 auto icount = fixed_size_instr(11);
746 // setg %dl
747 emit_i32_relop(0x9f);
748 }

◆ emit_i32_gt_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_gt_u ( )
inline

Definition at line 750 of file x86_64.hpp.

750 {
751 auto icount = fixed_size_instr(11);
752 // seta %dl
753 emit_i32_relop(0x97);
754 }

◆ emit_i32_gt_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_gt_u ( )
inline

Definition at line 750 of file x86_64.hpp.

750 {
751 auto icount = fixed_size_instr(11);
752 // seta %dl
753 emit_i32_relop(0x97);
754 }

◆ emit_i32_le_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_le_s ( )
inline

Definition at line 756 of file x86_64.hpp.

756 {
757 auto icount = fixed_size_instr(11);
758 // setle %dl
759 emit_i32_relop(0x9e);
760 }

◆ emit_i32_le_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_le_s ( )
inline

Definition at line 756 of file x86_64.hpp.

756 {
757 auto icount = fixed_size_instr(11);
758 // setle %dl
759 emit_i32_relop(0x9e);
760 }

◆ emit_i32_le_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_le_u ( )
inline

Definition at line 762 of file x86_64.hpp.

762 {
763 auto icount = fixed_size_instr(11);
764 // setbe %dl
765 emit_i32_relop(0x96);
766 }

◆ emit_i32_le_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_le_u ( )
inline

Definition at line 762 of file x86_64.hpp.

762 {
763 auto icount = fixed_size_instr(11);
764 // setbe %dl
765 emit_i32_relop(0x96);
766 }

◆ emit_i32_load() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 487 of file x86_64.hpp.

487 {
488 auto icount = variable_size_instr(7, 15);
489 // movl (RAX), EAX
490 emit_load_impl(offset, 0x8b, 0x00);
491 }

◆ emit_i32_load() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 487 of file x86_64.hpp.

487 {
488 auto icount = variable_size_instr(7, 15);
489 // movl (RAX), EAX
490 emit_load_impl(offset, 0x8b, 0x00);
491 }

◆ emit_i32_load16_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load16_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 517 of file x86_64.hpp.

517 {
518 auto icount = variable_size_instr(8, 16);
519 // movswl (RAX), EAX;
520 emit_load_impl(offset, 0x0F, 0xbf, 0x00);
521 }

◆ emit_i32_load16_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load16_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 517 of file x86_64.hpp.

517 {
518 auto icount = variable_size_instr(8, 16);
519 // movswl (RAX), EAX;
520 emit_load_impl(offset, 0x0F, 0xbf, 0x00);
521 }

◆ emit_i32_load16_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load16_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 529 of file x86_64.hpp.

529 {
530 auto icount = variable_size_instr(8, 16);
531 // movzwl (RAX), EAX;
532 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
533 }

◆ emit_i32_load16_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load16_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 529 of file x86_64.hpp.

529 {
530 auto icount = variable_size_instr(8, 16);
531 // movzwl (RAX), EAX;
532 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
533 }

◆ emit_i32_load8_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load8_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 511 of file x86_64.hpp.

511 {
512 auto icount = variable_size_instr(8, 16);
513 // movsbl (RAX), EAX;
514 emit_load_impl(offset, 0x0F, 0xbe, 0x00);
515 }

◆ emit_i32_load8_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load8_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 511 of file x86_64.hpp.

511 {
512 auto icount = variable_size_instr(8, 16);
513 // movsbl (RAX), EAX;
514 emit_load_impl(offset, 0x0F, 0xbe, 0x00);
515 }

◆ emit_i32_load8_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load8_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 523 of file x86_64.hpp.

523 {
524 auto icount = variable_size_instr(8, 16);
525 // movzbl (RAX), EAX;
526 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
527 }

◆ emit_i32_load8_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_load8_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 523 of file x86_64.hpp.

523 {
524 auto icount = variable_size_instr(8, 16);
525 // movzbl (RAX), EAX;
526 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
527 }

◆ emit_i32_lt_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_lt_s ( )
inline

Definition at line 732 of file x86_64.hpp.

732 {
733 auto icount = fixed_size_instr(11);
734 // setl %dl
735 emit_i32_relop(0x9c);
736 }

◆ emit_i32_lt_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_lt_s ( )
inline

Definition at line 732 of file x86_64.hpp.

732 {
733 auto icount = fixed_size_instr(11);
734 // setl %dl
735 emit_i32_relop(0x9c);
736 }

◆ emit_i32_lt_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_lt_u ( )
inline

Definition at line 738 of file x86_64.hpp.

738 {
739 auto icount = fixed_size_instr(11);
740 // setl %dl
741 emit_i32_relop(0x92);
742 }

◆ emit_i32_lt_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_lt_u ( )
inline

Definition at line 738 of file x86_64.hpp.

738 {
739 auto icount = fixed_size_instr(11);
740 // setl %dl
741 emit_i32_relop(0x92);
742 }

◆ emit_i32_mul() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_mul ( )
inline

Definition at line 1124 of file x86_64.hpp.

1124 {
1125 auto icount = fixed_size_instr(6);
1126 emit_i32_binop(0x0f, 0xaf, 0xc1, 0x50);
1127 }

◆ emit_i32_mul() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_mul ( )
inline

Definition at line 1124 of file x86_64.hpp.

1124 {
1125 auto icount = fixed_size_instr(6);
1126 emit_i32_binop(0x0f, 0xaf, 0xc1, 0x50);
1127 }

◆ emit_i32_ne() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ne ( )
inline

Definition at line 726 of file x86_64.hpp.

726 {
727 auto icount = fixed_size_instr(11);
728 // sete %dl
729 emit_i32_relop(0x95);
730 }

◆ emit_i32_ne() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_ne ( )
inline

Definition at line 726 of file x86_64.hpp.

726 {
727 auto icount = fixed_size_instr(11);
728 // sete %dl
729 emit_i32_relop(0x95);
730 }

◆ emit_i32_or() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_or ( )
inline

Definition at line 1172 of file x86_64.hpp.

1172 {
1173 auto icount = fixed_size_instr(5);
1174 emit_i32_binop(0x09, 0xc8, 0x50);
1175 }

◆ emit_i32_or() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_or ( )
inline

Definition at line 1172 of file x86_64.hpp.

1172 {
1173 auto icount = fixed_size_instr(5);
1174 emit_i32_binop(0x09, 0xc8, 0x50);
1175 }

◆ emit_i32_popcnt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_popcnt ( )
inline

Definition at line 1104 of file x86_64.hpp.

1104 {
1105 auto icount = fixed_size_instr(6);
1106 // popq %rax
1107 emit_bytes(0x58);
1108 // popcntl %eax, %eax
1109 emit_bytes(0xf3, 0x0f, 0xb8, 0xc0);
1110 // pushq %rax
1111 emit_bytes(0x50);
1112 }

◆ emit_i32_popcnt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_popcnt ( )
inline

Definition at line 1104 of file x86_64.hpp.

1104 {
1105 auto icount = fixed_size_instr(6);
1106 // popq %rax
1107 emit_bytes(0x58);
1108 // popcntl %eax, %eax
1109 emit_bytes(0xf3, 0x0f, 0xb8, 0xc0);
1110 // pushq %rax
1111 emit_bytes(0x50);
1112 }

◆ emit_i32_reinterpret_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_reinterpret_f32 ( )
inline

Definition at line 2070 of file x86_64.hpp.

2070{ /* Nothing to do */ }

◆ emit_i32_reinterpret_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_reinterpret_f32 ( )
inline

Definition at line 2070 of file x86_64.hpp.

2070{ /* Nothing to do */ }

◆ emit_i32_rem_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rem_s ( )
inline

Definition at line 1137 of file x86_64.hpp.

1137 {
1138 auto icount = fixed_size_instr(22);
1139 // pop %rcx
1140 emit_bytes(0x59);
1141 // pop %rax
1142 emit_bytes(0x58);
1143 // cmp $-1, %edx
1144 emit_bytes(0x83, 0xf9, 0xff);
1145 // je MINUS1
1146 emit_bytes(0x0f, 0x84);
1147 void* minus1 = emit_branch_target32();
1148 // cdq
1149 emit_bytes(0x99);
1150 // idiv %ecx
1151 emit_bytes(0xf7, 0xf9);
1152 // jmp END
1153 emit_bytes(0xe9);
1154 void* end = emit_branch_target32();
1155 // MINUS1:
1156 fix_branch(minus1, code);
1157 // xor %edx, %edx
1158 emit_bytes(0x31, 0xd2);
1159 // END:
1160 fix_branch(end, code);
1161 // push %rdx
1162 emit_bytes(0x52);
1163 }
Here is the call graph for this function:

◆ emit_i32_rem_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rem_s ( )
inline

Definition at line 1137 of file x86_64.hpp.

1137 {
1138 auto icount = fixed_size_instr(22);
1139 // pop %rcx
1140 emit_bytes(0x59);
1141 // pop %rax
1142 emit_bytes(0x58);
1143 // cmp $-1, %edx
1144 emit_bytes(0x83, 0xf9, 0xff);
1145 // je MINUS1
1146 emit_bytes(0x0f, 0x84);
1147 void* minus1 = emit_branch_target32();
1148 // cdq
1149 emit_bytes(0x99);
1150 // idiv %ecx
1151 emit_bytes(0xf7, 0xf9);
1152 // jmp END
1153 emit_bytes(0xe9);
1154 void* end = emit_branch_target32();
1155 // MINUS1:
1156 fix_branch(minus1, code);
1157 // xor %edx, %edx
1158 emit_bytes(0x31, 0xd2);
1159 // END:
1160 fix_branch(end, code);
1161 // push %rdx
1162 emit_bytes(0x52);
1163 }
Here is the call graph for this function:

◆ emit_i32_rem_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rem_u ( )
inline

Definition at line 1164 of file x86_64.hpp.

1164 {
1165 auto icount = fixed_size_instr(7);
1166 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x52);
1167 }

◆ emit_i32_rem_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rem_u ( )
inline

Definition at line 1164 of file x86_64.hpp.

1164 {
1165 auto icount = fixed_size_instr(7);
1166 emit_i32_binop(0x31, 0xd2, 0xf7, 0xf1, 0x52);
1167 }

◆ emit_i32_rotl() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rotl ( )
inline

Definition at line 1192 of file x86_64.hpp.

1192 {
1193 auto icount = fixed_size_instr(5);
1194 emit_i32_binop(0xd3, 0xc0, 0x50);
1195 }

◆ emit_i32_rotl() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rotl ( )
inline

Definition at line 1192 of file x86_64.hpp.

1192 {
1193 auto icount = fixed_size_instr(5);
1194 emit_i32_binop(0xd3, 0xc0, 0x50);
1195 }

◆ emit_i32_rotr() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rotr ( )
inline

Definition at line 1196 of file x86_64.hpp.

1196 {
1197 auto icount = fixed_size_instr(5);
1198 emit_i32_binop(0xd3, 0xc8, 0x50);
1199 }

◆ emit_i32_rotr() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_rotr ( )
inline

Definition at line 1196 of file x86_64.hpp.

1196 {
1197 auto icount = fixed_size_instr(5);
1198 emit_i32_binop(0xd3, 0xc8, 0x50);
1199 }

◆ emit_i32_shl() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shl ( )
inline

Definition at line 1180 of file x86_64.hpp.

1180 {
1181 auto icount = fixed_size_instr(5);
1182 emit_i32_binop(0xd3, 0xe0, 0x50);
1183 }

◆ emit_i32_shl() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shl ( )
inline

Definition at line 1180 of file x86_64.hpp.

1180 {
1181 auto icount = fixed_size_instr(5);
1182 emit_i32_binop(0xd3, 0xe0, 0x50);
1183 }

◆ emit_i32_shr_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shr_s ( )
inline

Definition at line 1184 of file x86_64.hpp.

1184 {
1185 auto icount = fixed_size_instr(5);
1186 emit_i32_binop(0xd3, 0xf8, 0x50);
1187 }

◆ emit_i32_shr_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shr_s ( )
inline

Definition at line 1184 of file x86_64.hpp.

1184 {
1185 auto icount = fixed_size_instr(5);
1186 emit_i32_binop(0xd3, 0xf8, 0x50);
1187 }

◆ emit_i32_shr_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shr_u ( )
inline

Definition at line 1188 of file x86_64.hpp.

1188 {
1189 auto icount = fixed_size_instr(5);
1190 emit_i32_binop(0xd3, 0xe8, 0x50);
1191 }

◆ emit_i32_shr_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_shr_u ( )
inline

Definition at line 1188 of file x86_64.hpp.

1188 {
1189 auto icount = fixed_size_instr(5);
1190 emit_i32_binop(0xd3, 0xe8, 0x50);
1191 }

◆ emit_i32_store() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 571 of file x86_64.hpp.

571 {
572 auto icount = variable_size_instr(7, 15);
573 // movl ECX, (RAX)
574 emit_store_impl(offset, 0x89, 0x08);
575 }

◆ emit_i32_store() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 571 of file x86_64.hpp.

571 {
572 auto icount = variable_size_instr(7, 15);
573 // movl ECX, (RAX)
574 emit_store_impl(offset, 0x89, 0x08);
575 }

◆ emit_i32_store16() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store16 ( uint32_t ,
uint32_t offset )
inline

Definition at line 601 of file x86_64.hpp.

601 {
602 auto icount = variable_size_instr(8, 16);
603 // movb CX, (RAX)
604 emit_store_impl(offset, 0x66, 0x89, 0x08);
605 }

◆ emit_i32_store16() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store16 ( uint32_t ,
uint32_t offset )
inline

Definition at line 601 of file x86_64.hpp.

601 {
602 auto icount = variable_size_instr(8, 16);
603 // movb CX, (RAX)
604 emit_store_impl(offset, 0x66, 0x89, 0x08);
605 }

◆ emit_i32_store8() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store8 ( uint32_t ,
uint32_t offset )
inline

Definition at line 595 of file x86_64.hpp.

595 {
596 auto icount = variable_size_instr(7, 15);
597 // movb CL, (RAX)
598 emit_store_impl(offset, 0x88, 0x08);
599 }

◆ emit_i32_store8() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_store8 ( uint32_t ,
uint32_t offset )
inline

Definition at line 595 of file x86_64.hpp.

595 {
596 auto icount = variable_size_instr(7, 15);
597 // movb CL, (RAX)
598 emit_store_impl(offset, 0x88, 0x08);
599 }

◆ emit_i32_sub() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_sub ( )
inline

Definition at line 1120 of file x86_64.hpp.

1120 {
1121 auto icount = fixed_size_instr(5);
1122 emit_i32_binop(0x29, 0xc8, 0x50);
1123 }

◆ emit_i32_sub() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_sub ( )
inline

Definition at line 1120 of file x86_64.hpp.

1120 {
1121 auto icount = fixed_size_instr(5);
1122 emit_i32_binop(0x29, 0xc8, 0x50);
1123 }

◆ emit_i32_trunc_s_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_s_f32 ( )
inline

Definition at line 1733 of file x86_64.hpp.

1733 {
1734 auto icount = softfloat_instr(33, 36, 54);
1735 if constexpr (use_softfloat) {
1736 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32s>()));
1737 }
1738 // cvttss2si 8(%rsp), %eax
1739 emit_f2i(0xf3, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1740 // mov %eax, (%rsp)
1741 emit_bytes(0x89, 0x04 ,0x24);
1742 }

◆ emit_i32_trunc_s_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_s_f32 ( )
inline

Definition at line 1733 of file x86_64.hpp.

1733 {
1734 auto icount = softfloat_instr(33, 36, 54);
1735 if constexpr (use_softfloat) {
1736 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32s>()));
1737 }
1738 // cvttss2si 8(%rsp), %eax
1739 emit_f2i(0xf3, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1740 // mov %eax, (%rsp)
1741 emit_bytes(0x89, 0x04 ,0x24);
1742 }

◆ emit_i32_trunc_s_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_s_f64 ( )
inline

Definition at line 1761 of file x86_64.hpp.

1761 {
1762 auto icount = softfloat_instr(34, 38, 56);
1763 if constexpr (use_softfloat) {
1764 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32s>()));
1765 }
1766 // cvttsd2si 8(%rsp), %eax
1767 emit_f2i(0xf2, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1768 // movq %rax, (%rsp)
1769 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1770 }

◆ emit_i32_trunc_s_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_s_f64 ( )
inline

Definition at line 1761 of file x86_64.hpp.

1761 {
1762 auto icount = softfloat_instr(34, 38, 56);
1763 if constexpr (use_softfloat) {
1764 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32s>()));
1765 }
1766 // cvttsd2si 8(%rsp), %eax
1767 emit_f2i(0xf2, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1768 // movq %rax, (%rsp)
1769 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1770 }

◆ emit_i32_trunc_u_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_u_f32 ( )
inline

Definition at line 1744 of file x86_64.hpp.

1744 {
1745 auto icount = softfloat_instr(46, 36, 54);
1746 if constexpr (use_softfloat) {
1747 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32u>()));
1748 }
1749 // cvttss2si 8(%rsp), %rax
1750 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1751 // mov %eax, (%rsp)
1752 emit_bytes(0x89, 0x04 ,0x24);
1753 // shr $32, %rax
1754 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1755 // test %eax, %eax
1756 emit_bytes(0x85, 0xc0);
1757 // jnz FP_ERROR_HANDLER
1758 emit_bytes(0x0f, 0x85);
1759 fix_branch(emit_branch_target32(), fpe_handler);
1760 }
Here is the call graph for this function:

◆ emit_i32_trunc_u_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_u_f32 ( )
inline

Definition at line 1744 of file x86_64.hpp.

1744 {
1745 auto icount = softfloat_instr(46, 36, 54);
1746 if constexpr (use_softfloat) {
1747 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i32u>()));
1748 }
1749 // cvttss2si 8(%rsp), %rax
1750 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1751 // mov %eax, (%rsp)
1752 emit_bytes(0x89, 0x04 ,0x24);
1753 // shr $32, %rax
1754 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1755 // test %eax, %eax
1756 emit_bytes(0x85, 0xc0);
1757 // jnz FP_ERROR_HANDLER
1758 emit_bytes(0x0f, 0x85);
1759 fix_branch(emit_branch_target32(), fpe_handler);
1760 }
Here is the call graph for this function:

◆ emit_i32_trunc_u_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_u_f64 ( )
inline

Definition at line 1772 of file x86_64.hpp.

1772 {
1773 auto icount = softfloat_instr(47, 38, 56);
1774 if constexpr (use_softfloat) {
1775 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32u>()));
1776 }
1777 // cvttsd2si 8(%rsp), %rax
1778 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1779 // movq %rax, (%rsp)
1780 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1781 // shr $32, %rax
1782 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1783 // test %eax, %eax
1784 emit_bytes(0x85, 0xc0);
1785 // jnz FP_ERROR_HANDLER
1786 emit_bytes(0x0f, 0x85);
1787 fix_branch(emit_branch_target32(), fpe_handler);
1788 }
Here is the call graph for this function:

◆ emit_i32_trunc_u_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_trunc_u_f64 ( )
inline

Definition at line 1772 of file x86_64.hpp.

1772 {
1773 auto icount = softfloat_instr(47, 38, 56);
1774 if constexpr (use_softfloat) {
1775 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i32u>()));
1776 }
1777 // cvttsd2si 8(%rsp), %rax
1778 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1779 // movq %rax, (%rsp)
1780 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1781 // shr $32, %rax
1782 emit_bytes(0x48, 0xc1, 0xe8, 0x20);
1783 // test %eax, %eax
1784 emit_bytes(0x85, 0xc0);
1785 // jnz FP_ERROR_HANDLER
1786 emit_bytes(0x0f, 0x85);
1787 fix_branch(emit_branch_target32(), fpe_handler);
1788 }
Here is the call graph for this function:

◆ emit_i32_wrap_i64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_wrap_i64 ( )
inline

Definition at line 1724 of file x86_64.hpp.

1724 {
1725 auto icount = fixed_size_instr(6);
1726 // Zero out the high 4 bytes
1727 // xor %eax, %eax
1728 emit_bytes(0x31, 0xc0);
1729 // mov %eax, 4(%rsp)
1730 emit_bytes(0x89, 0x44, 0x24, 0x04);
1731 }

◆ emit_i32_wrap_i64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_wrap_i64 ( )
inline

Definition at line 1724 of file x86_64.hpp.

1724 {
1725 auto icount = fixed_size_instr(6);
1726 // Zero out the high 4 bytes
1727 // xor %eax, %eax
1728 emit_bytes(0x31, 0xc0);
1729 // mov %eax, 4(%rsp)
1730 emit_bytes(0x89, 0x44, 0x24, 0x04);
1731 }

◆ emit_i32_xor() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_xor ( )
inline

Definition at line 1176 of file x86_64.hpp.

1176 {
1177 auto icount = fixed_size_instr(5);
1178 emit_i32_binop(0x31, 0xc8, 0x50);
1179 }

◆ emit_i32_xor() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i32_xor ( )
inline

Definition at line 1176 of file x86_64.hpp.

1176 {
1177 auto icount = fixed_size_instr(5);
1178 emit_i32_binop(0x31, 0xc8, 0x50);
1179 }

◆ emit_i64_add() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_add ( )
inline

Definition at line 1265 of file x86_64.hpp.

1265 {
1266 auto icount = fixed_size_instr(6);
1267 emit_i64_binop(0x48, 0x01, 0xc8, 0x50);
1268 }

◆ emit_i64_add() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_add ( )
inline

Definition at line 1265 of file x86_64.hpp.

1265 {
1266 auto icount = fixed_size_instr(6);
1267 emit_i64_binop(0x48, 0x01, 0xc8, 0x50);
1268 }

◆ emit_i64_and() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_and ( )
inline

Definition at line 1317 of file x86_64.hpp.

1317 {
1318 auto icount = fixed_size_instr(6);
1319 emit_i64_binop(0x48, 0x21, 0xc8, 0x50);
1320 }

◆ emit_i64_and() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_and ( )
inline

Definition at line 1317 of file x86_64.hpp.

1317 {
1318 auto icount = fixed_size_instr(6);
1319 emit_i64_binop(0x48, 0x21, 0xc8, 0x50);
1320 }

◆ emit_i64_clz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_clz ( )
inline

Definition at line 1203 of file x86_64.hpp.

1203 {
1204 auto icount = fixed_size_instr(has_tzcnt()?7:24);
1205 if(!has_tzcnt()) {
1206 // pop %rax
1207 emit_bytes(0x58);
1208 // mov $-1, %ecx
1209 emit_bytes(0x48, 0xc7, 0xc1, 0xff, 0xff, 0xff, 0xff);
1210 // bsr %eax, %eax
1211 emit_bytes(0x48, 0x0f, 0xbd, 0xc0);
1212 // cmovz %ecx, %eax
1213 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1214 // sub $63, %eax
1215 emit_bytes(0x48, 0x83, 0xe8, 0x3f);
1216 // neg %eax
1217 emit_bytes(0x48, 0xf7, 0xd8);
1218 // push %rax
1219 emit_bytes(0x50);
1220 } else {
1221 // popq %rax
1222 emit_bytes(0x58);
1223 // lzcntq %eax, %eax
1224 emit_bytes(0xf3, 0x48, 0x0f, 0xbd, 0xc0);
1225 // pushq %rax
1226 emit_bytes(0x50);
1227 }
1228 }
Here is the call graph for this function:

◆ emit_i64_clz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_clz ( )
inline

Definition at line 1203 of file x86_64.hpp.

1203 {
1204 auto icount = fixed_size_instr(has_tzcnt()?7:24);
1205 if(!has_tzcnt()) {
1206 // pop %rax
1207 emit_bytes(0x58);
1208 // mov $-1, %ecx
1209 emit_bytes(0x48, 0xc7, 0xc1, 0xff, 0xff, 0xff, 0xff);
1210 // bsr %eax, %eax
1211 emit_bytes(0x48, 0x0f, 0xbd, 0xc0);
1212 // cmovz %ecx, %eax
1213 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1214 // sub $63, %eax
1215 emit_bytes(0x48, 0x83, 0xe8, 0x3f);
1216 // neg %eax
1217 emit_bytes(0x48, 0xf7, 0xd8);
1218 // push %rax
1219 emit_bytes(0x50);
1220 } else {
1221 // popq %rax
1222 emit_bytes(0x58);
1223 // lzcntq %eax, %eax
1224 emit_bytes(0xf3, 0x48, 0x0f, 0xbd, 0xc0);
1225 // pushq %rax
1226 emit_bytes(0x50);
1227 }
1228 }
Here is the call graph for this function:

◆ emit_i64_const() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_const ( uint64_t value)
inline

Definition at line 679 of file x86_64.hpp.

679 {
680 auto icount = fixed_size_instr(11);
681 // movabsq $value, %rax
682 emit_bytes(0x48, 0xb8);
683 emit_operand64(value);
684 // push %rax
685 emit_bytes(0x50);
686 }

◆ emit_i64_const() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_const ( uint64_t value)
inline

Definition at line 679 of file x86_64.hpp.

679 {
680 auto icount = fixed_size_instr(11);
681 // movabsq $value, %rax
682 emit_bytes(0x48, 0xb8);
683 emit_operand64(value);
684 // push %rax
685 emit_bytes(0x50);
686 }

◆ emit_i64_ctz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ctz ( )
inline

Definition at line 1230 of file x86_64.hpp.

1230 {
1231 auto icount = fixed_size_instr(has_tzcnt()?7:17);
1232 if(!has_tzcnt()) {
1233 // pop %rax
1234 emit_bytes(0x58);
1235 // mov $64, %ecx
1236 emit_bytes(0x48, 0xc7, 0xc1, 0x40, 0x00, 0x00, 0x00);
1237 // bsf %eax, %eax
1238 emit_bytes(0x48, 0x0f, 0xbc, 0xc0);
1239 // cmovz %ecx, %eax
1240 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1241 // push %rax
1242 emit_bytes(0x50);
1243 } else {
1244 // popq %rax
1245 emit_bytes(0x58);
1246 // tzcntq %eax, %eax
1247 emit_bytes(0xf3, 0x48, 0x0f, 0xbc, 0xc0);
1248 // pushq %rax
1249 emit_bytes(0x50);
1250 }
1251 }
Here is the call graph for this function:

◆ emit_i64_ctz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ctz ( )
inline

Definition at line 1230 of file x86_64.hpp.

1230 {
1231 auto icount = fixed_size_instr(has_tzcnt()?7:17);
1232 if(!has_tzcnt()) {
1233 // pop %rax
1234 emit_bytes(0x58);
1235 // mov $64, %ecx
1236 emit_bytes(0x48, 0xc7, 0xc1, 0x40, 0x00, 0x00, 0x00);
1237 // bsf %eax, %eax
1238 emit_bytes(0x48, 0x0f, 0xbc, 0xc0);
1239 // cmovz %ecx, %eax
1240 emit_bytes(0x48, 0x0f, 0x44, 0xc1);
1241 // push %rax
1242 emit_bytes(0x50);
1243 } else {
1244 // popq %rax
1245 emit_bytes(0x58);
1246 // tzcntq %eax, %eax
1247 emit_bytes(0xf3, 0x48, 0x0f, 0xbc, 0xc0);
1248 // pushq %rax
1249 emit_bytes(0x50);
1250 }
1251 }
Here is the call graph for this function:

◆ emit_i64_div_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_div_s ( )
inline

Definition at line 1278 of file x86_64.hpp.

1278 {
1279 auto icount = fixed_size_instr(8);
1280 emit_i64_binop(0x48, 0x99, 0x48, 0xf7, 0xf9, 0x50);
1281 }

◆ emit_i64_div_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_div_s ( )
inline

Definition at line 1278 of file x86_64.hpp.

1278 {
1279 auto icount = fixed_size_instr(8);
1280 emit_i64_binop(0x48, 0x99, 0x48, 0xf7, 0xf9, 0x50);
1281 }

◆ emit_i64_div_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_div_u ( )
inline

Definition at line 1282 of file x86_64.hpp.

1282 {
1283 auto icount = fixed_size_instr(9);
1284 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x50);
1285 }

◆ emit_i64_div_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_div_u ( )
inline

Definition at line 1282 of file x86_64.hpp.

1282 {
1283 auto icount = fixed_size_instr(9);
1284 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x50);
1285 }

◆ emit_i64_eq() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_eq ( )
inline

Definition at line 794 of file x86_64.hpp.

794 {
795 auto icount = fixed_size_instr(12);
796 // sete %dl
797 emit_i64_relop(0x94);
798 }

◆ emit_i64_eq() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_eq ( )
inline

Definition at line 794 of file x86_64.hpp.

794 {
795 auto icount = fixed_size_instr(12);
796 // sete %dl
797 emit_i64_relop(0x94);
798 }

◆ emit_i64_eqz() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_eqz ( )
inline

Definition at line 780 of file x86_64.hpp.

780 {
781 auto icount = fixed_size_instr(11);
782 // pop %rax
783 emit_bytes(0x58);
784 // xor %rcx, %rcx
785 emit_bytes(0x48, 0x31, 0xc9);
786 // test %rax, %rax
787 emit_bytes(0x48, 0x85, 0xc0);
788 // setz %cl
789 emit_bytes(0x0f, 0x94, 0xc1);
790 // push %rcx
791 emit_bytes(0x51);
792 }

◆ emit_i64_eqz() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_eqz ( )
inline

Definition at line 780 of file x86_64.hpp.

780 {
781 auto icount = fixed_size_instr(11);
782 // pop %rax
783 emit_bytes(0x58);
784 // xor %rcx, %rcx
785 emit_bytes(0x48, 0x31, 0xc9);
786 // test %rax, %rax
787 emit_bytes(0x48, 0x85, 0xc0);
788 // setz %cl
789 emit_bytes(0x0f, 0x94, 0xc1);
790 // push %rcx
791 emit_bytes(0x51);
792 }

◆ emit_i64_extend_s_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_extend_s_i32 ( )
inline

Definition at line 1790 of file x86_64.hpp.

1790 {
1791 auto icount = fixed_size_instr(8);
1792 // movslq (%rsp), %rax
1793 emit_bytes(0x48, 0x63, 0x04, 0x24);
1794 // mov %rax, (%rsp)
1795 emit_bytes(0x48, 0x89, 0x04, 0x24);
1796 }

◆ emit_i64_extend_s_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_extend_s_i32 ( )
inline

Definition at line 1790 of file x86_64.hpp.

1790 {
1791 auto icount = fixed_size_instr(8);
1792 // movslq (%rsp), %rax
1793 emit_bytes(0x48, 0x63, 0x04, 0x24);
1794 // mov %rax, (%rsp)
1795 emit_bytes(0x48, 0x89, 0x04, 0x24);
1796 }

◆ emit_i64_extend_u_i32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_extend_u_i32 ( )
inline

Definition at line 1798 of file x86_64.hpp.

1798{ /* Nothing to do */ }

◆ emit_i64_extend_u_i32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_extend_u_i32 ( )
inline

Definition at line 1798 of file x86_64.hpp.

1798{ /* Nothing to do */ }

◆ emit_i64_ge_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ge_s ( )
inline

Definition at line 842 of file x86_64.hpp.

842 {
843 auto icount = fixed_size_instr(12);
844 // setge %dl
845 emit_i64_relop(0x9d);
846 }

◆ emit_i64_ge_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ge_s ( )
inline

Definition at line 842 of file x86_64.hpp.

842 {
843 auto icount = fixed_size_instr(12);
844 // setge %dl
845 emit_i64_relop(0x9d);
846 }

◆ emit_i64_ge_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ge_u ( )
inline

Definition at line 848 of file x86_64.hpp.

848 {
849 auto icount = fixed_size_instr(12);
850 // setae %dl
851 emit_i64_relop(0x93);
852 }

◆ emit_i64_ge_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ge_u ( )
inline

Definition at line 848 of file x86_64.hpp.

848 {
849 auto icount = fixed_size_instr(12);
850 // setae %dl
851 emit_i64_relop(0x93);
852 }

◆ emit_i64_gt_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_gt_s ( )
inline

Definition at line 818 of file x86_64.hpp.

818 {
819 auto icount = fixed_size_instr(12);
820 // setg %dl
821 emit_i64_relop(0x9f);
822 }

◆ emit_i64_gt_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_gt_s ( )
inline

Definition at line 818 of file x86_64.hpp.

818 {
819 auto icount = fixed_size_instr(12);
820 // setg %dl
821 emit_i64_relop(0x9f);
822 }

◆ emit_i64_gt_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_gt_u ( )
inline

Definition at line 824 of file x86_64.hpp.

824 {
825 auto icount = fixed_size_instr(12);
826 // seta %dl
827 emit_i64_relop(0x97);
828 }

◆ emit_i64_gt_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_gt_u ( )
inline

Definition at line 824 of file x86_64.hpp.

824 {
825 auto icount = fixed_size_instr(12);
826 // seta %dl
827 emit_i64_relop(0x97);
828 }

◆ emit_i64_le_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_le_s ( )
inline

Definition at line 830 of file x86_64.hpp.

830 {
831 auto icount = fixed_size_instr(12);
832 // setle %dl
833 emit_i64_relop(0x9e);
834 }

◆ emit_i64_le_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_le_s ( )
inline

Definition at line 830 of file x86_64.hpp.

830 {
831 auto icount = fixed_size_instr(12);
832 // setle %dl
833 emit_i64_relop(0x9e);
834 }

◆ emit_i64_le_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_le_u ( )
inline

Definition at line 836 of file x86_64.hpp.

836 {
837 auto icount = fixed_size_instr(12);
838 // setbe %dl
839 emit_i64_relop(0x96);
840 }

◆ emit_i64_le_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_le_u ( )
inline

Definition at line 836 of file x86_64.hpp.

836 {
837 auto icount = fixed_size_instr(12);
838 // setbe %dl
839 emit_i64_relop(0x96);
840 }

◆ emit_i64_load() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 493 of file x86_64.hpp.

493 {
494 auto icount = variable_size_instr(8, 16);
495 // movq (RAX), RAX
496 emit_load_impl(offset, 0x48, 0x8b, 0x00);
497 }

◆ emit_i64_load() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load ( uint32_t ,
uint32_t offset )
inline

Definition at line 493 of file x86_64.hpp.

493 {
494 auto icount = variable_size_instr(8, 16);
495 // movq (RAX), RAX
496 emit_load_impl(offset, 0x48, 0x8b, 0x00);
497 }

◆ emit_i64_load16_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load16_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 541 of file x86_64.hpp.

541 {
542 auto icount = variable_size_instr(9, 17);
543 // movswq (RAX), RAX;
544 emit_load_impl(offset, 0x48, 0x0F, 0xbf, 0x00);
545 }

◆ emit_i64_load16_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load16_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 541 of file x86_64.hpp.

541 {
542 auto icount = variable_size_instr(9, 17);
543 // movswq (RAX), RAX;
544 emit_load_impl(offset, 0x48, 0x0F, 0xbf, 0x00);
545 }

◆ emit_i64_load16_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load16_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 559 of file x86_64.hpp.

559 {
560 auto icount = variable_size_instr(8, 16);
561 // movzwl (RAX), EAX;
562 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
563 }

◆ emit_i64_load16_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load16_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 559 of file x86_64.hpp.

559 {
560 auto icount = variable_size_instr(8, 16);
561 // movzwl (RAX), EAX;
562 emit_load_impl(offset, 0x0f, 0xb7, 0x00);
563 }

◆ emit_i64_load32_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load32_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 547 of file x86_64.hpp.

547 {
548 auto icount = variable_size_instr(8, 16);
549 // movslq (RAX), RAX
550 emit_load_impl(offset, 0x48, 0x63, 0x00);
551 }

◆ emit_i64_load32_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load32_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 547 of file x86_64.hpp.

547 {
548 auto icount = variable_size_instr(8, 16);
549 // movslq (RAX), RAX
550 emit_load_impl(offset, 0x48, 0x63, 0x00);
551 }

◆ emit_i64_load32_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load32_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 565 of file x86_64.hpp.

565 {
566 auto icount = variable_size_instr(7, 15);
567 // movl (RAX), EAX
568 emit_load_impl(offset, 0x8b, 0x00);
569 }

◆ emit_i64_load32_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load32_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 565 of file x86_64.hpp.

565 {
566 auto icount = variable_size_instr(7, 15);
567 // movl (RAX), EAX
568 emit_load_impl(offset, 0x8b, 0x00);
569 }

◆ emit_i64_load8_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load8_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 535 of file x86_64.hpp.

535 {
536 auto icount = variable_size_instr(9, 17);
537 // movsbq (RAX), RAX;
538 emit_load_impl(offset, 0x48, 0x0F, 0xbe, 0x00);
539 }

◆ emit_i64_load8_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load8_s ( uint32_t ,
uint32_t offset )
inline

Definition at line 535 of file x86_64.hpp.

535 {
536 auto icount = variable_size_instr(9, 17);
537 // movsbq (RAX), RAX;
538 emit_load_impl(offset, 0x48, 0x0F, 0xbe, 0x00);
539 }

◆ emit_i64_load8_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load8_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 553 of file x86_64.hpp.

553 {
554 auto icount = variable_size_instr(8, 16);
555 // movzbl (RAX), EAX;
556 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
557 }

◆ emit_i64_load8_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_load8_u ( uint32_t ,
uint32_t offset )
inline

Definition at line 553 of file x86_64.hpp.

553 {
554 auto icount = variable_size_instr(8, 16);
555 // movzbl (RAX), EAX;
556 emit_load_impl(offset, 0x0f, 0xb6, 0x00);
557 }

◆ emit_i64_lt_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_lt_s ( )
inline

Definition at line 806 of file x86_64.hpp.

806 {
807 auto icount = fixed_size_instr(12);
808 // setl %dl
809 emit_i64_relop(0x9c);
810 }

◆ emit_i64_lt_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_lt_s ( )
inline

Definition at line 806 of file x86_64.hpp.

806 {
807 auto icount = fixed_size_instr(12);
808 // setl %dl
809 emit_i64_relop(0x9c);
810 }

◆ emit_i64_lt_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_lt_u ( )
inline

Definition at line 812 of file x86_64.hpp.

812 {
813 auto icount = fixed_size_instr(12);
814 // setl %dl
815 emit_i64_relop(0x92);
816 }

◆ emit_i64_lt_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_lt_u ( )
inline

Definition at line 812 of file x86_64.hpp.

812 {
813 auto icount = fixed_size_instr(12);
814 // setl %dl
815 emit_i64_relop(0x92);
816 }

◆ emit_i64_mul() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_mul ( )
inline

Definition at line 1273 of file x86_64.hpp.

1273 {
1274 auto icount = fixed_size_instr(7);
1275 emit_i64_binop(0x48, 0x0f, 0xaf, 0xc1, 0x50);
1276 }

◆ emit_i64_mul() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_mul ( )
inline

Definition at line 1273 of file x86_64.hpp.

1273 {
1274 auto icount = fixed_size_instr(7);
1275 emit_i64_binop(0x48, 0x0f, 0xaf, 0xc1, 0x50);
1276 }

◆ emit_i64_ne() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ne ( )
inline

Definition at line 800 of file x86_64.hpp.

800 {
801 auto icount = fixed_size_instr(12);
802 // sete %dl
803 emit_i64_relop(0x95);
804 }

◆ emit_i64_ne() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_ne ( )
inline

Definition at line 800 of file x86_64.hpp.

800 {
801 auto icount = fixed_size_instr(12);
802 // sete %dl
803 emit_i64_relop(0x95);
804 }

◆ emit_i64_or() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_or ( )
inline

Definition at line 1321 of file x86_64.hpp.

1321 {
1322 auto icount = fixed_size_instr(6);
1323 emit_i64_binop(0x48, 0x09, 0xc8, 0x50);
1324 }

◆ emit_i64_or() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_or ( )
inline

Definition at line 1321 of file x86_64.hpp.

1321 {
1322 auto icount = fixed_size_instr(6);
1323 emit_i64_binop(0x48, 0x09, 0xc8, 0x50);
1324 }

◆ emit_i64_popcnt() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_popcnt ( )
inline

Definition at line 1253 of file x86_64.hpp.

1253 {
1254 auto icount = fixed_size_instr(7);
1255 // popq %rax
1256 emit_bytes(0x58);
1257 // popcntq %rax, %rax
1258 emit_bytes(0xf3, 0x48, 0x0f, 0xb8, 0xc0);
1259 // pushq %rax
1260 emit_bytes(0x50);
1261 }

◆ emit_i64_popcnt() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_popcnt ( )
inline

Definition at line 1253 of file x86_64.hpp.

1253 {
1254 auto icount = fixed_size_instr(7);
1255 // popq %rax
1256 emit_bytes(0x58);
1257 // popcntq %rax, %rax
1258 emit_bytes(0xf3, 0x48, 0x0f, 0xb8, 0xc0);
1259 // pushq %rax
1260 emit_bytes(0x50);
1261 }

◆ emit_i64_reinterpret_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_reinterpret_f64 ( )
inline

Definition at line 2071 of file x86_64.hpp.

2071{ /* Nothing to do */ }

◆ emit_i64_reinterpret_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_reinterpret_f64 ( )
inline

Definition at line 2071 of file x86_64.hpp.

2071{ /* Nothing to do */ }

◆ emit_i64_rem_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rem_s ( )
inline

Definition at line 1286 of file x86_64.hpp.

1286 {
1287 auto icount = fixed_size_instr(25);
1288 // pop %rcx
1289 emit_bytes(0x59);
1290 // pop %rax
1291 emit_bytes(0x58);
1292 // cmp $-1, %rcx
1293 emit_bytes(0x48, 0x83, 0xf9, 0xff);
1294 // je MINUS1
1295 emit_bytes(0x0f, 0x84);
1296 void* minus1 = emit_branch_target32();
1297 // cqo
1298 emit_bytes(0x48, 0x99);
1299 // idiv %rcx
1300 emit_bytes(0x48, 0xf7, 0xf9);
1301 // jmp END
1302 emit_bytes(0xe9);
1303 void* end = emit_branch_target32();
1304 // MINUS1:
1305 fix_branch(minus1, code);
1306 // xor %edx, %edx
1307 emit_bytes(0x31, 0xd2);
1308 // END:
1309 fix_branch(end, code);
1310 // push %rdx
1311 emit_bytes(0x52);
1312 }
Here is the call graph for this function:

◆ emit_i64_rem_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rem_s ( )
inline

Definition at line 1286 of file x86_64.hpp.

1286 {
1287 auto icount = fixed_size_instr(25);
1288 // pop %rcx
1289 emit_bytes(0x59);
1290 // pop %rax
1291 emit_bytes(0x58);
1292 // cmp $-1, %rcx
1293 emit_bytes(0x48, 0x83, 0xf9, 0xff);
1294 // je MINUS1
1295 emit_bytes(0x0f, 0x84);
1296 void* minus1 = emit_branch_target32();
1297 // cqo
1298 emit_bytes(0x48, 0x99);
1299 // idiv %rcx
1300 emit_bytes(0x48, 0xf7, 0xf9);
1301 // jmp END
1302 emit_bytes(0xe9);
1303 void* end = emit_branch_target32();
1304 // MINUS1:
1305 fix_branch(minus1, code);
1306 // xor %edx, %edx
1307 emit_bytes(0x31, 0xd2);
1308 // END:
1309 fix_branch(end, code);
1310 // push %rdx
1311 emit_bytes(0x52);
1312 }
Here is the call graph for this function:

◆ emit_i64_rem_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rem_u ( )
inline

Definition at line 1313 of file x86_64.hpp.

1313 {
1314 auto icount = fixed_size_instr(9);
1315 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x52);
1316 }

◆ emit_i64_rem_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rem_u ( )
inline

Definition at line 1313 of file x86_64.hpp.

1313 {
1314 auto icount = fixed_size_instr(9);
1315 emit_i64_binop(0x48, 0x31, 0xd2, 0x48, 0xf7, 0xf1, 0x52);
1316 }

◆ emit_i64_rotl() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rotl ( )
inline

Definition at line 1341 of file x86_64.hpp.

1341 {
1342 auto icount = fixed_size_instr(6);
1343 emit_i64_binop(0x48, 0xd3, 0xc0, 0x50);
1344 }

◆ emit_i64_rotl() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rotl ( )
inline

Definition at line 1341 of file x86_64.hpp.

1341 {
1342 auto icount = fixed_size_instr(6);
1343 emit_i64_binop(0x48, 0xd3, 0xc0, 0x50);
1344 }

◆ emit_i64_rotr() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rotr ( )
inline

Definition at line 1345 of file x86_64.hpp.

1345 {
1346 auto icount = fixed_size_instr(6);
1347 emit_i64_binop(0x48, 0xd3, 0xc8, 0x50);
1348 }

◆ emit_i64_rotr() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_rotr ( )
inline

Definition at line 1345 of file x86_64.hpp.

1345 {
1346 auto icount = fixed_size_instr(6);
1347 emit_i64_binop(0x48, 0xd3, 0xc8, 0x50);
1348 }

◆ emit_i64_shl() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shl ( )
inline

Definition at line 1329 of file x86_64.hpp.

1329 {
1330 auto icount = fixed_size_instr(6);
1331 emit_i64_binop(0x48, 0xd3, 0xe0, 0x50);
1332 }

◆ emit_i64_shl() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shl ( )
inline

Definition at line 1329 of file x86_64.hpp.

1329 {
1330 auto icount = fixed_size_instr(6);
1331 emit_i64_binop(0x48, 0xd3, 0xe0, 0x50);
1332 }

◆ emit_i64_shr_s() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shr_s ( )
inline

Definition at line 1333 of file x86_64.hpp.

1333 {
1334 auto icount = fixed_size_instr(6);
1335 emit_i64_binop(0x48, 0xd3, 0xf8, 0x50);
1336 }

◆ emit_i64_shr_s() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shr_s ( )
inline

Definition at line 1333 of file x86_64.hpp.

1333 {
1334 auto icount = fixed_size_instr(6);
1335 emit_i64_binop(0x48, 0xd3, 0xf8, 0x50);
1336 }

◆ emit_i64_shr_u() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shr_u ( )
inline

Definition at line 1337 of file x86_64.hpp.

1337 {
1338 auto icount = fixed_size_instr(6);
1339 emit_i64_binop(0x48, 0xd3, 0xe8, 0x50);
1340 }

◆ emit_i64_shr_u() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_shr_u ( )
inline

Definition at line 1337 of file x86_64.hpp.

1337 {
1338 auto icount = fixed_size_instr(6);
1339 emit_i64_binop(0x48, 0xd3, 0xe8, 0x50);
1340 }

◆ emit_i64_store() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 577 of file x86_64.hpp.

577 {
578 auto icount = variable_size_instr(8, 16);
579 // movl ECX, (RAX)
580 emit_store_impl(offset, 0x48, 0x89, 0x08);
581 }

◆ emit_i64_store() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store ( uint32_t ,
uint32_t offset )
inline

Definition at line 577 of file x86_64.hpp.

577 {
578 auto icount = variable_size_instr(8, 16);
579 // movl ECX, (RAX)
580 emit_store_impl(offset, 0x48, 0x89, 0x08);
581 }

◆ emit_i64_store16() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store16 ( uint32_t ,
uint32_t offset )
inline

Definition at line 613 of file x86_64.hpp.

613 {
614 auto icount = variable_size_instr(8, 16);
615 // movb CX, (RAX)
616 emit_store_impl(offset, 0x66, 0x89, 0x08);
617 }

◆ emit_i64_store16() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store16 ( uint32_t ,
uint32_t offset )
inline

Definition at line 613 of file x86_64.hpp.

613 {
614 auto icount = variable_size_instr(8, 16);
615 // movb CX, (RAX)
616 emit_store_impl(offset, 0x66, 0x89, 0x08);
617 }

◆ emit_i64_store32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store32 ( uint32_t ,
uint32_t offset )
inline

Definition at line 619 of file x86_64.hpp.

619 {
620 auto icount = variable_size_instr(7, 15);
621 // movl ECX, (RAX)
622 emit_store_impl(offset, 0x89, 0x08);
623 }

◆ emit_i64_store32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store32 ( uint32_t ,
uint32_t offset )
inline

Definition at line 619 of file x86_64.hpp.

619 {
620 auto icount = variable_size_instr(7, 15);
621 // movl ECX, (RAX)
622 emit_store_impl(offset, 0x89, 0x08);
623 }

◆ emit_i64_store8() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store8 ( uint32_t ,
uint32_t offset )
inline

Definition at line 607 of file x86_64.hpp.

607 {
608 auto icount = variable_size_instr(7, 15);
609 // movb CL, (RAX)
610 emit_store_impl(offset, 0x88, 0x08);
611 }

◆ emit_i64_store8() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_store8 ( uint32_t ,
uint32_t offset )
inline

Definition at line 607 of file x86_64.hpp.

607 {
608 auto icount = variable_size_instr(7, 15);
609 // movb CL, (RAX)
610 emit_store_impl(offset, 0x88, 0x08);
611 }

◆ emit_i64_sub() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_sub ( )
inline

Definition at line 1269 of file x86_64.hpp.

1269 {
1270 auto icount = fixed_size_instr(6);
1271 emit_i64_binop(0x48, 0x29, 0xc8, 0x50);
1272 }

◆ emit_i64_sub() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_sub ( )
inline

Definition at line 1269 of file x86_64.hpp.

1269 {
1270 auto icount = fixed_size_instr(6);
1271 emit_i64_binop(0x48, 0x29, 0xc8, 0x50);
1272 }

◆ emit_i64_trunc_s_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_s_f32 ( )
inline

Definition at line 1800 of file x86_64.hpp.

1800 {
1801 auto icount = softfloat_instr(35, 37, 55);
1802 if constexpr (use_softfloat) {
1803 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64s>()));
1804 }
1805 // cvttss2si (%rsp), %rax
1806 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1807 // mov %rax, (%rsp)
1808 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1809 }

◆ emit_i64_trunc_s_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_s_f32 ( )
inline

Definition at line 1800 of file x86_64.hpp.

1800 {
1801 auto icount = softfloat_instr(35, 37, 55);
1802 if constexpr (use_softfloat) {
1803 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64s>()));
1804 }
1805 // cvttss2si (%rsp), %rax
1806 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1807 // mov %rax, (%rsp)
1808 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1809 }

◆ emit_i64_trunc_s_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_s_f64 ( )
inline

Definition at line 1853 of file x86_64.hpp.

1853 {
1854 auto icount = softfloat_instr(35, 38, 56);
1855 if constexpr (use_softfloat) {
1856 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64s>()));
1857 }
1858 // cvttsd2si (%rsp), %rax
1859 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1860 // mov %rax, (%rsp)
1861 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1862 }

◆ emit_i64_trunc_s_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_s_f64 ( )
inline

Definition at line 1853 of file x86_64.hpp.

1853 {
1854 auto icount = softfloat_instr(35, 38, 56);
1855 if constexpr (use_softfloat) {
1856 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64s>()));
1857 }
1858 // cvttsd2si (%rsp), %rax
1859 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0x44, 0x24, 0x08);
1860 // mov %rax, (%rsp)
1861 emit_bytes(0x48, 0x89, 0x04 ,0x24);
1862 }

◆ emit_i64_trunc_u_f32() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_u_f32 ( )
inline

Definition at line 1810 of file x86_64.hpp.

1810 {
1811 auto icount = softfloat_instr(101, 37, 55);
1812 if constexpr (use_softfloat) {
1813 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64u>()));
1814 }
1815 // mov $0x5f000000, %eax
1816 emit_bytes(0xb8);
1817 emit_operand32(0x5f000000);
1818 // movss (%rsp), %xmm0
1819 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1820 // mov %eax, (%rsp)
1821 emit_bytes(0x89, 0x04, 0x24);
1822 // movss (%rsp), %xmm1
1823 emit_bytes(0xf3, 0x0f, 0x10, 0x0c, 0x24);
1824 // movaps %xmm0, %xmm2
1825 emit_bytes(0x0f, 0x28, 0xd0);
1826 // subss %xmm1, %xmm2
1827 emit_bytes(0xf3, 0x0f, 0x5c, 0xd1);
1828 // cvttss2siq %xmm2, %rax
1829 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0xc2);
1830 // movabsq $0x8000000000000000, %rcx
1831 emit_bytes(0x48, 0xb9);
1832 emit_operand64(0x8000000000000000);
1833 // xorq %rax, %rcx
1834 emit_bytes(0x48, 0x31, 0xc1);
1835 // cvttss2siq %xmm0, %rax
1836 emit_bytes(0xf3, 0x48, 0x0f, 0x2c, 0xc0);
1837 // xor %rdx, %rdx
1838 emit_bytes(0x48, 0x31, 0xd2);
1839 // ucomiss %xmm0, %xmm1
1840 emit_bytes(0x0f, 0x2e, 0xc8);
1841 // cmovaq %rax, %rdx
1842 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1843 // cmovbeq %rcx, %rax
1844 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1845 // mov %rax, (%rsp)
1846 emit_bytes(0x48, 0x89, 0x04, 0x24);
1847 // bt $63, %rdx
1848 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1849 // jc FP_ERROR_HANDLER
1850 emit_bytes(0x0f, 0x82);
1851 fix_branch(emit_branch_target32(), fpe_handler);
1852 }
Here is the call graph for this function:

◆ emit_i64_trunc_u_f32() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_u_f32 ( )
inline

Definition at line 1810 of file x86_64.hpp.

1810 {
1811 auto icount = softfloat_instr(101, 37, 55);
1812 if constexpr (use_softfloat) {
1813 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f32_trunc_i64u>()));
1814 }
1815 // mov $0x5f000000, %eax
1816 emit_bytes(0xb8);
1817 emit_operand32(0x5f000000);
1818 // movss (%rsp), %xmm0
1819 emit_bytes(0xf3, 0x0f, 0x10, 0x04, 0x24);
1820 // mov %eax, (%rsp)
1821 emit_bytes(0x89, 0x04, 0x24);
1822 // movss (%rsp), %xmm1
1823 emit_bytes(0xf3, 0x0f, 0x10, 0x0c, 0x24);
1824 // movaps %xmm0, %xmm2
1825 emit_bytes(0x0f, 0x28, 0xd0);
1826 // subss %xmm1, %xmm2
1827 emit_bytes(0xf3, 0x0f, 0x5c, 0xd1);
1828 // cvttss2siq %xmm2, %rax
1829 emit_f2i(0xf3, 0x48, 0x0f, 0x2c, 0xc2);
1830 // movabsq $0x8000000000000000, %rcx
1831 emit_bytes(0x48, 0xb9);
1832 emit_operand64(0x8000000000000000);
1833 // xorq %rax, %rcx
1834 emit_bytes(0x48, 0x31, 0xc1);
1835 // cvttss2siq %xmm0, %rax
1836 emit_bytes(0xf3, 0x48, 0x0f, 0x2c, 0xc0);
1837 // xor %rdx, %rdx
1838 emit_bytes(0x48, 0x31, 0xd2);
1839 // ucomiss %xmm0, %xmm1
1840 emit_bytes(0x0f, 0x2e, 0xc8);
1841 // cmovaq %rax, %rdx
1842 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1843 // cmovbeq %rcx, %rax
1844 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1845 // mov %rax, (%rsp)
1846 emit_bytes(0x48, 0x89, 0x04, 0x24);
1847 // bt $63, %rdx
1848 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1849 // jc FP_ERROR_HANDLER
1850 emit_bytes(0x0f, 0x82);
1851 fix_branch(emit_branch_target32(), fpe_handler);
1852 }
Here is the call graph for this function:

◆ emit_i64_trunc_u_f64() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_u_f64 ( )
inline

Definition at line 1863 of file x86_64.hpp.

1863 {
1864 auto icount = softfloat_instr(109, 38, 56);
1865 if constexpr (use_softfloat) {
1866 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64u>()));
1867 }
1868 // movabsq $0x43e0000000000000, %rax
1869 emit_bytes(0x48, 0xb8);
1870 emit_operand64(0x43e0000000000000);
1871 // movsd (%rsp), %xmm0
1872 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1873 // movq %rax, (%rsp)
1874 emit_bytes(0x48, 0x89, 0x04, 0x24);
1875 // movsd (%rsp), %xmm1
1876 emit_bytes(0xf2, 0x0f, 0x10, 0x0c, 0x24);
1877 // movapd %xmm0, %xmm2
1878 emit_bytes(0x66, 0x0f, 0x28, 0xd0);
1879 // subsd %xmm1, %xmm2
1880 emit_bytes(0xf2, 0x0f, 0x5c, 0xd1);
1881 // cvttsd2siq %xmm2, %rax
1882 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0xc2);
1883 // movabsq $0x8000000000000000, %rcx
1884 emit_bytes(0x48, 0xb9);
1885 emit_operand64(0x8000000000000000);
1886 // xorq %rax, %rcx
1887 emit_bytes(0x48, 0x31, 0xc1);
1888 // cvttsd2siq %xmm0, %rax
1889 emit_bytes(0xf2, 0x48, 0x0f, 0x2c, 0xc0);
1890 // xor %rdx, %rdx
1891 emit_bytes(0x48, 0x31, 0xd2);
1892 // ucomisd %xmm0, %xmm1
1893 emit_bytes(0x66, 0x0f, 0x2e, 0xc8);
1894 // cmovaq %rax, %rdx
1895 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1896 // cmovbeq %rcx, %rax
1897 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1898 // mov %rax, (%rsp)
1899 emit_bytes(0x48, 0x89, 0x04, 0x24);
1900 // bt $63, %rdx
1901 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1902 // jc FP_ERROR_HANDLER
1903 emit_bytes(0x0f, 0x82);
1904 fix_branch(emit_branch_target32(), fpe_handler);
1905 }
Here is the call graph for this function:

◆ emit_i64_trunc_u_f64() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_trunc_u_f64 ( )
inline

Definition at line 1863 of file x86_64.hpp.

1863 {
1864 auto icount = softfloat_instr(109, 38, 56);
1865 if constexpr (use_softfloat) {
1866 return emit_softfloat_unop(CHOOSE_FN(softfloat_trap<&_sysio_f64_trunc_i64u>()));
1867 }
1868 // movabsq $0x43e0000000000000, %rax
1869 emit_bytes(0x48, 0xb8);
1870 emit_operand64(0x43e0000000000000);
1871 // movsd (%rsp), %xmm0
1872 emit_bytes(0xf2, 0x0f, 0x10, 0x04, 0x24);
1873 // movq %rax, (%rsp)
1874 emit_bytes(0x48, 0x89, 0x04, 0x24);
1875 // movsd (%rsp), %xmm1
1876 emit_bytes(0xf2, 0x0f, 0x10, 0x0c, 0x24);
1877 // movapd %xmm0, %xmm2
1878 emit_bytes(0x66, 0x0f, 0x28, 0xd0);
1879 // subsd %xmm1, %xmm2
1880 emit_bytes(0xf2, 0x0f, 0x5c, 0xd1);
1881 // cvttsd2siq %xmm2, %rax
1882 emit_f2i(0xf2, 0x48, 0x0f, 0x2c, 0xc2);
1883 // movabsq $0x8000000000000000, %rcx
1884 emit_bytes(0x48, 0xb9);
1885 emit_operand64(0x8000000000000000);
1886 // xorq %rax, %rcx
1887 emit_bytes(0x48, 0x31, 0xc1);
1888 // cvttsd2siq %xmm0, %rax
1889 emit_bytes(0xf2, 0x48, 0x0f, 0x2c, 0xc0);
1890 // xor %rdx, %rdx
1891 emit_bytes(0x48, 0x31, 0xd2);
1892 // ucomisd %xmm0, %xmm1
1893 emit_bytes(0x66, 0x0f, 0x2e, 0xc8);
1894 // cmovaq %rax, %rdx
1895 emit_bytes(0x48, 0x0f, 0x47, 0xd0);
1896 // cmovbeq %rcx, %rax
1897 emit_bytes(0x48, 0x0f, 0x46, 0xc1);
1898 // mov %rax, (%rsp)
1899 emit_bytes(0x48, 0x89, 0x04, 0x24);
1900 // bt $63, %rdx
1901 emit_bytes(0x48, 0x0f, 0xba, 0xe2, 0x3f);
1902 // jc FP_ERROR_HANDLER
1903 emit_bytes(0x0f, 0x82);
1904 fix_branch(emit_branch_target32(), fpe_handler);
1905 }
Here is the call graph for this function:

◆ emit_i64_xor() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_xor ( )
inline

Definition at line 1325 of file x86_64.hpp.

1325 {
1326 auto icount = fixed_size_instr(6);
1327 emit_i64_binop(0x48, 0x31, 0xc8, 0x50);
1328 }

◆ emit_i64_xor() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_i64_xor ( )
inline

Definition at line 1325 of file x86_64.hpp.

1325 {
1326 auto icount = fixed_size_instr(6);
1327 emit_i64_binop(0x48, 0x31, 0xc8, 0x50);
1328 }

◆ emit_if() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_if ( )
inline

Definition at line 177 of file x86_64.hpp.

177 {
178 auto icount = fixed_size_instr(9);
179 // pop RAX
180 emit_bytes(0x58);
181 // test EAX, EAX
182 emit_bytes(0x85, 0xC0);
183 // jz DEST
184 emit_bytes(0x0F, 0x84);
185 return emit_branch_target32();
186 }

◆ emit_if() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_if ( )
inline

Definition at line 177 of file x86_64.hpp.

177 {
178 auto icount = fixed_size_instr(9);
179 // pop RAX
180 emit_bytes(0x58);
181 // test EAX, EAX
182 emit_bytes(0x85, 0xC0);
183 // jz DEST
184 emit_bytes(0x0F, 0x84);
185 return emit_branch_target32();
186 }

◆ emit_loop() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_loop ( )
inline

Definition at line 176 of file x86_64.hpp.

176{ return code; }

◆ emit_loop() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_loop ( )
inline

Definition at line 176 of file x86_64.hpp.

176{ return code; }

◆ emit_nop() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_nop ( )
inline

Definition at line 169 of file x86_64.hpp.

169{}

◆ emit_nop() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_nop ( )
inline

Definition at line 169 of file x86_64.hpp.

169{}

◆ emit_prologue() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_prologue ( const func_type & ,
const guarded_vector< local_entry > & locals,
uint32_t funcnum )
inline

Definition at line 103 of file x86_64.hpp.

103 {
104 _ft = &_mod.types[_mod.functions[funcnum]];
105 // FIXME: This is not a tight upper bound
106 const std::size_t instruction_size_ratio_upper_bound = use_softfloat?(Context::async_backtrace()?63:49):79;
107 std::size_t code_size = max_prologue_size + _mod.code[funcnum].size * instruction_size_ratio_upper_bound + max_epilogue_size;
108 _code_start = _mod.allocator.alloc<unsigned char>(code_size);
109 _code_end = _code_start + code_size;
110 code = _code_start;
111 start_function(code, funcnum + _mod.get_imported_functions_size());
112 // pushq RBP
113 emit_bytes(0x55);
114 // movq RSP, RBP
115 emit_bytes(0x48, 0x89, 0xe5);
116 // No more than 2^32-1 locals. Already validated by the parser.
117 uint32_t count = 0;
118 for(uint32_t i = 0; i < locals.size(); ++i) {
119 assert(uint64_t(count) + locals[i].count <= 0xFFFFFFFFu);
120 count += locals[i].count;
121 }
122 _local_count = count;
123 if (_local_count > 0) {
124 // xor %rax, %rax
125 emit_bytes(0x48, 0x31, 0xc0);
126 if (_local_count > 14) { // only use a loop if it would save space
127 // mov $count, %ecx
128 emit_bytes(0xb9);
129 emit_operand32(_local_count);
130 // loop:
131 void* loop = code;
132 // pushq %rax
133 emit_bytes(0x50);
134 // dec %ecx
135 emit_bytes(0xff, 0xc9);
136 // jnz loop
137 emit_bytes(0x0f, 0x85);
138 fix_branch(emit_branch_target32(), loop);
139 } else {
140 for (uint32_t i = 0; i < _local_count; ++i) {
141 // pushq %rax
142 emit_bytes(0x50);
143 }
144 }
145 }
146 assert((char*)code <= (char*)_code_start + max_prologue_size);
147 }
static constexpr std::size_t max_prologue_size
Definition x86_64.hpp:101
int * count
unsigned __int64 uint64_t
Definition stdint.h:136
guarded_vector< uint32_t > functions
Definition types.hpp:171
uint32_t get_imported_functions_size() const
Definition types.hpp:197
guarded_vector< func_type > types
Definition types.hpp:169
guarded_vector< function_body > code
Definition types.hpp:177
Here is the call graph for this function:

◆ emit_prologue() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_prologue ( const func_type & ,
const guarded_vector< local_entry > & locals,
uint32_t funcnum )
inline

Definition at line 103 of file x86_64.hpp.

103 {
104 _ft = &_mod.types[_mod.functions[funcnum]];
105 // FIXME: This is not a tight upper bound
106 const std::size_t instruction_size_ratio_upper_bound = use_softfloat?(Context::async_backtrace()?63:49):79;
107 std::size_t code_size = max_prologue_size + _mod.code[funcnum].size * instruction_size_ratio_upper_bound + max_epilogue_size;
108 _code_start = _mod.allocator.alloc<unsigned char>(code_size);
109 _code_end = _code_start + code_size;
110 code = _code_start;
111 start_function(code, funcnum + _mod.get_imported_functions_size());
112 // pushq RBP
113 emit_bytes(0x55);
114 // movq RSP, RBP
115 emit_bytes(0x48, 0x89, 0xe5);
116 // No more than 2^32-1 locals. Already validated by the parser.
117 uint32_t count = 0;
118 for(uint32_t i = 0; i < locals.size(); ++i) {
119 assert(uint64_t(count) + locals[i].count <= 0xFFFFFFFFu);
120 count += locals[i].count;
121 }
122 _local_count = count;
123 if (_local_count > 0) {
124 // xor %rax, %rax
125 emit_bytes(0x48, 0x31, 0xc0);
126 if (_local_count > 14) { // only use a loop if it would save space
127 // mov $count, %ecx
128 emit_bytes(0xb9);
129 emit_operand32(_local_count);
130 // loop:
131 void* loop = code;
132 // pushq %rax
133 emit_bytes(0x50);
134 // dec %ecx
135 emit_bytes(0xff, 0xc9);
136 // jnz loop
137 emit_bytes(0x0f, 0x85);
138 fix_branch(emit_branch_target32(), loop);
139 } else {
140 for (uint32_t i = 0; i < _local_count; ++i) {
141 // pushq %rax
142 emit_bytes(0x50);
143 }
144 }
145 }
146 assert((char*)code <= (char*)_code_start + max_prologue_size);
147 }
Here is the call graph for this function:

◆ emit_return() [1/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_return ( uint32_t depth_change)
inline

Definition at line 171 of file x86_64.hpp.

171 {
172 // Return is defined as equivalent to branching to the outermost label
173 return emit_br(depth_change);
174 }
Here is the call graph for this function:

◆ emit_return() [2/2]

template<typename Context >
void * sysio::vm::machine_code_writer< Context >::emit_return ( uint32_t depth_change)
inline

Definition at line 171 of file x86_64.hpp.

171 {
172 // Return is defined as equivalent to branching to the outermost label
173 return emit_br(depth_change);
174 }
Here is the call graph for this function:

◆ emit_select() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_select ( )
inline

Definition at line 366 of file x86_64.hpp.

366 {
367 auto icount = fixed_size_instr(13);
368 // popq RAX
369 emit_bytes(0x58);
370 // popq RCX
371 emit_bytes(0x59);
372 // test EAX, EAX
373 emit_bytes(0x85, 0xc0);
374 // cmovnzq RCX, (RSP)
375 emit_bytes(0x48, 0x0f, 0x45, 0x0c, 0x24);
376 // movq (RSP), RCX
377 emit_bytes(0x48, 0x89, 0x0c, 0x24);
378 }

◆ emit_select() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_select ( )
inline

Definition at line 366 of file x86_64.hpp.

366 {
367 auto icount = fixed_size_instr(13);
368 // popq RAX
369 emit_bytes(0x58);
370 // popq RCX
371 emit_bytes(0x59);
372 // test EAX, EAX
373 emit_bytes(0x85, 0xc0);
374 // cmovnzq RCX, (RSP)
375 emit_bytes(0x48, 0x0f, 0x45, 0x0c, 0x24);
376 // movq (RSP), RCX
377 emit_bytes(0x48, 0x89, 0x0c, 0x24);
378 }

◆ emit_set_global() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_set_global ( uint32_t globalidx)
inline

Definition at line 474 of file x86_64.hpp.

474 {
475 auto icount = fixed_size_instr(14);
476 auto& gl = _mod.globals[globalidx];
477 void *ptr = &gl.current.value;
478 // popq %rcx
479 emit_bytes(0x59);
480 // movabsq $ptr, %rax
481 emit_bytes(0x48, 0xb8);
482 emit_operand_ptr(ptr);
483 // movq %rcx, (%rax)
484 emit_bytes(0x48, 0x89, 0x08);
485 }

◆ emit_set_global() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_set_global ( uint32_t globalidx)
inline

Definition at line 474 of file x86_64.hpp.

474 {
475 auto icount = fixed_size_instr(14);
476 auto& gl = _mod.globals[globalidx];
477 void *ptr = &gl.current.value;
478 // popq %rcx
479 emit_bytes(0x59);
480 // movabsq $ptr, %rax
481 emit_bytes(0x48, 0xb8);
482 emit_operand_ptr(ptr);
483 // movq %rcx, (%rax)
484 emit_bytes(0x48, 0x89, 0x08);
485 }

◆ emit_set_local() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_set_local ( uint32_t local_idx)
inline

Definition at line 409 of file x86_64.hpp.

409 {
410 auto icount = fixed_size_instr(8);
411 if (local_idx < _ft->param_types.size()) {
412 // pop RAX
413 emit_bytes(0x58);
414 // mov RAX, -8*local_idx(EBP)
415 emit_bytes(0x48, 0x89, 0x85);
416 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
417 } else {
418 // pop RAX
419 emit_bytes(0x58);
420 // mov RAX, -8*local_idx(EBP)
421 emit_bytes(0x48, 0x89, 0x85);
422 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
423 }
424 }

◆ emit_set_local() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_set_local ( uint32_t local_idx)
inline

Definition at line 409 of file x86_64.hpp.

409 {
410 auto icount = fixed_size_instr(8);
411 if (local_idx < _ft->param_types.size()) {
412 // pop RAX
413 emit_bytes(0x58);
414 // mov RAX, -8*local_idx(EBP)
415 emit_bytes(0x48, 0x89, 0x85);
416 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
417 } else {
418 // pop RAX
419 emit_bytes(0x58);
420 // mov RAX, -8*local_idx(EBP)
421 emit_bytes(0x48, 0x89, 0x85);
422 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
423 }
424 }

◆ emit_tee_local() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_tee_local ( uint32_t local_idx)
inline

Definition at line 426 of file x86_64.hpp.

426 {
427 auto icount = fixed_size_instr(9);
428 if (local_idx < _ft->param_types.size()) {
429 // pop RAX
430 emit_bytes(0x58);
431 // push RAX
432 emit_bytes(0x50);
433 // mov RAX, -8*local_idx(EBP)
434 emit_bytes(0x48, 0x89, 0x85);
435 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
436 } else {
437 // pop RAX
438 emit_bytes(0x58);
439 // push RAX
440 emit_bytes(0x50);
441 // mov RAX, -8*local_idx(EBP)
442 emit_bytes(0x48, 0x89, 0x85);
443 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
444 }
445 }

◆ emit_tee_local() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_tee_local ( uint32_t local_idx)
inline

Definition at line 426 of file x86_64.hpp.

426 {
427 auto icount = fixed_size_instr(9);
428 if (local_idx < _ft->param_types.size()) {
429 // pop RAX
430 emit_bytes(0x58);
431 // push RAX
432 emit_bytes(0x50);
433 // mov RAX, -8*local_idx(EBP)
434 emit_bytes(0x48, 0x89, 0x85);
435 emit_operand32(8 * (_ft->param_types.size() - local_idx + 1));
436 } else {
437 // pop RAX
438 emit_bytes(0x58);
439 // push RAX
440 emit_bytes(0x50);
441 // mov RAX, -8*local_idx(EBP)
442 emit_bytes(0x48, 0x89, 0x85);
443 emit_operand32(-8 * (local_idx - _ft->param_types.size() + 1));
444 }
445 }

◆ emit_unreachable() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_unreachable ( )
inline

Definition at line 165 of file x86_64.hpp.

165 {
166 auto icount = fixed_size_instr(16);
167 emit_error_handler(&on_unreachable);
168 }

◆ emit_unreachable() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::emit_unreachable ( )
inline

Definition at line 165 of file x86_64.hpp.

165 {
166 auto icount = fixed_size_instr(16);
167 emit_error_handler(&on_unreachable);
168 }

◆ finalize() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::finalize ( function_body & body)
inline

Definition at line 2096 of file x86_64.hpp.

2096 {
2097 _mod.allocator.reclaim(code, _code_end - code);
2098 body.jit_code_offset = _code_start - (unsigned char*)_code_segment_base;
2099 }
void reclaim(const T *ptr, size_t size=0)
Here is the call graph for this function:

◆ finalize() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::finalize ( function_body & body)
inline

Definition at line 2096 of file x86_64.hpp.

2096 {
2097 _mod.allocator.reclaim(code, _code_end - code);
2098 body.jit_code_offset = _code_start - (unsigned char*)_code_segment_base;
2099 }
Here is the call graph for this function:

◆ fix_branch() [1/2]

template<typename Context >
static void sysio::vm::machine_code_writer< Context >::fix_branch ( void * branch,
void * target )
inlinestatic

Definition at line 2080 of file x86_64.hpp.

2080 {
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);
2087 }
unsigned char uint8_t
Definition stdint.h:124
memcpy((char *) pInfo->slotDescription, s, l)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fix_branch() [2/2]

template<typename Context >
static void sysio::vm::machine_code_writer< Context >::fix_branch ( void * branch,
void * target )
inlinestatic

Definition at line 2080 of file x86_64.hpp.

2080 {
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);
2087 }
Here is the call graph for this function:

◆ fix_branch64() [1/2]

template<typename Context >
static void sysio::vm::machine_code_writer< Context >::fix_branch64 ( void * branch,
void * target )
inlinestatic

Definition at line 2091 of file x86_64.hpp.

2091 {
2092 memcpy(branch, &target, 8);
2093 }
Here is the call graph for this function:

◆ fix_branch64() [2/2]

template<typename Context >
static void sysio::vm::machine_code_writer< Context >::fix_branch64 ( void * branch,
void * target )
inlinestatic

Definition at line 2091 of file x86_64.hpp.

2091 {
2092 memcpy(branch, &target, 8);
2093 }
Here is the call graph for this function:

◆ get_addr() [1/2]

template<typename Context >
const void * sysio::vm::machine_code_writer< Context >::get_addr ( ) const
inline

Definition at line 2102 of file x86_64.hpp.

2102 {
2103 return code;
2104 }

◆ get_addr() [2/2]

template<typename Context >
const void * sysio::vm::machine_code_writer< Context >::get_addr ( ) const
inline

Definition at line 2102 of file x86_64.hpp.

2102 {
2103 return code;
2104 }

◆ get_base_addr() [1/2]

template<typename Context >
const void * sysio::vm::machine_code_writer< Context >::get_base_addr ( ) const
inline

Definition at line 2106 of file x86_64.hpp.

2106{ return _code_segment_base; }

◆ get_base_addr() [2/2]

template<typename Context >
const void * sysio::vm::machine_code_writer< Context >::get_base_addr ( ) const
inline

Definition at line 2106 of file x86_64.hpp.

2106{ return _code_segment_base; }

◆ has_tzcnt() [1/2]

template<typename Context >
bool sysio::vm::machine_code_writer< Context >::has_tzcnt ( )
inline

Definition at line 1049 of file x86_64.hpp.

1049 {
1050 static bool result = has_tzcnt_impl();
1051 return result;
1052 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ has_tzcnt() [2/2]

template<typename Context >
bool sysio::vm::machine_code_writer< Context >::has_tzcnt ( )
inline

Definition at line 1049 of file x86_64.hpp.

1049 {
1050 static bool result = has_tzcnt_impl();
1051 return result;
1052 }
Here is the call graph for this function:

◆ has_tzcnt_impl() [1/2]

template<typename Context >
bool sysio::vm::machine_code_writer< Context >::has_tzcnt_impl ( )
inline

Definition at line 1043 of file x86_64.hpp.

1043 {
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);
1047 }
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1181
CK_ULONG d
Here is the caller graph for this function:

◆ has_tzcnt_impl() [2/2]

template<typename Context >
bool sysio::vm::machine_code_writer< Context >::has_tzcnt_impl ( )
inline

Definition at line 1043 of file x86_64.hpp.

1043 {
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);
1047 }

◆ register_call() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::register_call ( void * ptr,
uint32_t funcnum )
inline

Definition at line 296 of file x86_64.hpp.

296 {
297 auto& vec = _function_relocations;
298 if(funcnum >= vec.size()) vec.resize(funcnum + 1);
299 if(void** addr = std::get_if<void*>(&vec[funcnum])) {
300 fix_branch(ptr, *addr);
301 } else {
302 std::get<std::vector<void*>>(vec[funcnum]).push_back(ptr);
303 }
304 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ register_call() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::register_call ( void * ptr,
uint32_t funcnum )
inline

Definition at line 296 of file x86_64.hpp.

296 {
297 auto& vec = _function_relocations;
298 if(funcnum >= vec.size()) vec.resize(funcnum + 1);
299 if(void** addr = std::get_if<void*>(&vec[funcnum])) {
300 fix_branch(ptr, *addr);
301 } else {
302 std::get<std::vector<void*>>(vec[funcnum]).push_back(ptr);
303 }
304 }
Here is the call graph for this function:

◆ start_function() [1/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::start_function ( void * func_start,
uint32_t funcnum )
inline

Definition at line 305 of file x86_64.hpp.

305 {
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])) {
309 fix_branch(branch, func_start);
310 }
311 vec[funcnum] = func_start;
312 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_function() [2/2]

template<typename Context >
void sysio::vm::machine_code_writer< Context >::start_function ( void * func_start,
uint32_t funcnum )
inline

Definition at line 305 of file x86_64.hpp.

305 {
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])) {
309 fix_branch(branch, func_start);
310 }
311 vec[funcnum] = func_start;
312 }
Here is the call graph for this function:

Member Data Documentation

◆ max_epilogue_size

template<typename Context >
static constexpr std::size_t sysio::vm::machine_code_writer< Context >::max_epilogue_size = 10
staticconstexpr

Definition at line 102 of file x86_64.hpp.

◆ max_prologue_size

template<typename Context >
static constexpr std::size_t sysio::vm::machine_code_writer< Context >::max_prologue_size = 21
staticconstexpr

Definition at line 101 of file x86_64.hpp.


The documentation for this class was generated from the following files: