Coverage Report

Created: 2023-06-07 06:30

/src/wasm3/source/m3_exec.h
Line
Count
Source (jump to first uncovered line)
1
//
2
//  m3_exec.h
3
//
4
//  Created by Steven Massey on 4/17/19.
5
//  Copyright © 2019 Steven Massey. All rights reserved.
6
7
8
#ifndef m3_exec_h
9
#define m3_exec_h
10
11
// TODO: all these functions could move over to the .c at some point. normally, I'd say screw it,
12
// but it might prove useful to be able to compile m3_exec alone w/ optimizations while the remaining
13
// code is at debug O0
14
15
16
// About the naming convention of these operations/macros (_rs, _sr_, _ss, _srs, etc.)
17
//------------------------------------------------------------------------------------------------------
18
//   - 'r' means register and 's' means slot
19
//   - the first letter is the top of the stack
20
//
21
//  so, for example, _rs means the first operand (the first thing pushed to the stack) is in a slot
22
//  and the second operand (the top of the stack) is in a register
23
//------------------------------------------------------------------------------------------------------
24
25
#ifndef M3_COMPILE_OPCODES
26
#  error "Opcodes should only be included in one compilation unit"
27
#endif
28
29
#include "m3_math_utils.h"
30
#include "m3_compile.h"
31
#include "m3_env.h"
32
#include "m3_info.h"
33
#include "m3_exec_defs.h"
34
35
#include <limits.h>
36
37
d_m3BeginExternC
38
39
0
# define rewrite_op(OP)             * ((void **) (_pc-1)) = (void*)(OP)
40
41
4.45k
# define immediate(TYPE)            * ((TYPE *) _pc++)
42
# define skip_immediate(TYPE)       (_pc++)
43
44
3.50k
# define slot(TYPE)                 * (TYPE *) (_sp + immediate (i32))
45
0
# define slot_ptr(TYPE)             (TYPE *) (_sp + immediate (i32))
46
47
48
# if d_m3EnableOpProfiling
49
                                    d_m3RetSig  profileOp   (d_m3OpSig, cstr_t i_operationName);
50
#   define nextOp()                 M3_MUSTTAIL return profileOp (d_m3OpAllArgs, __FUNCTION__)
51
# elif d_m3EnableOpTracing
52
                                    d_m3RetSig  debugOp     (d_m3OpSig, cstr_t i_operationName);
53
#   define nextOp()                 M3_MUSTTAIL return debugOp (d_m3OpAllArgs, __FUNCTION__)
54
# else
55
3.50k
#   define nextOp()                 nextOpDirect()
56
# endif
57
58
0
#define jumpOp(PC)                  jumpOpDirect(PC)
59
60
#if d_m3RecordBacktraces
61
    #define pushBacktraceFrame()            (PushBacktraceFrame (_mem->runtime, _pc - 1))
62
    #define fillBacktraceFrame(FUNCTION)    (FillBacktraceFunctionInfo (_mem->runtime, function))
63
64
    #define newTrap(err)                    return (pushBacktraceFrame (), err)
65
    #define forwardTrap(err)                return err
66
#else
67
0
    #define pushBacktraceFrame()            do {} while (0)
68
0
    #define fillBacktraceFrame(FUNCTION)    do {} while (0)
69
70
0
    #define newTrap(err)                    return err
71
0
    #define forwardTrap(err)                return err
72
#endif
73
74
75
#if d_m3EnableStrace == 1
76
    // Flat trace
77
    #define d_m3TracePrepare
78
    #define d_m3TracePrint(fmt, ...)            fprintf(stderr, fmt "\n", ##__VA_ARGS__)
79
#elif d_m3EnableStrace >= 2
80
    // Structured trace
81
    #define d_m3TracePrepare                    const IM3Runtime trace_rt = m3MemRuntime(_mem);
82
    #define d_m3TracePrint(fmt, ...)            fprintf(stderr, "%*s" fmt "\n", (trace_rt->callDepth)*2, "", ##__VA_ARGS__)
83
#else
84
    #define d_m3TracePrepare
85
    #define d_m3TracePrint(fmt, ...)
86
#endif
87
88
#if d_m3EnableStrace >= 3
89
    #define d_m3TraceLoad(TYPE,offset,val)      d_m3TracePrint("load." #TYPE "  0x%x = %" PRI##TYPE, offset, val)
90
    #define d_m3TraceStore(TYPE,offset,val)     d_m3TracePrint("store." #TYPE " 0x%x , %" PRI##TYPE, offset, val)
91
#else
92
    #define d_m3TraceLoad(TYPE,offset,val)
93
    #define d_m3TraceStore(TYPE,offset,val)
94
#endif
95
96
#ifdef DEBUG
97
  #define d_outOfBounds newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess,   \
98
                        _mem->runtime, "memory size: %zu; access offset: %zu",      \
99
                        _mem->length, operand))
100
101
#   define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess,   \
102
                      _mem->runtime, "memory size: %zu; access offset: %zu; size: %u",     \
103
                      _mem->length, OFFSET, SIZE))
104
#else
105
0
  #define d_outOfBounds newTrap (m3Err_trapOutOfBoundsMemoryAccess)
106
107
0
#   define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (m3Err_trapOutOfBoundsMemoryAccess)
108
109
#endif
110
111
112
d_m3RetSig  Call  (d_m3OpSig)
113
0
{
114
0
    m3ret_t possible_trap = m3_Yield ();
115
0
    if (M3_UNLIKELY(possible_trap)) return possible_trap;
116
117
0
    nextOpDirect();
118
0
}
119
120
// TODO: OK, this needs some explanation here ;0
121
122
#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \
123
0
d_m3Op(TYPE##_##NAME##_rs)                              \
124
0
{                                                       \
125
0
    TYPE operand = slot (TYPE);                         \
126
0
    OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__);    \
127
0
    nextOp ();                                          \
128
0
}                                                       \
Unexecuted instantiation: m3_compile.c:op_i32_Equal_rs
Unexecuted instantiation: m3_compile.c:op_i32_NotEqual_rs
Unexecuted instantiation: m3_compile.c:op_i32_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_u32_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_i32_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_u32_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_i64_Equal_rs
Unexecuted instantiation: m3_compile.c:op_i64_NotEqual_rs
Unexecuted instantiation: m3_compile.c:op_i64_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_u64_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_i64_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_u64_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_f32_Equal_rs
Unexecuted instantiation: m3_compile.c:op_f32_NotEqual_rs
Unexecuted instantiation: m3_compile.c:op_f32_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_f32_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_f64_Equal_rs
Unexecuted instantiation: m3_compile.c:op_f64_NotEqual_rs
Unexecuted instantiation: m3_compile.c:op_f64_LessThan_rs
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThan_rs
Unexecuted instantiation: m3_compile.c:op_f64_LessThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThanOrEqual_rs
Unexecuted instantiation: m3_compile.c:op_i32_Add_rs
Unexecuted instantiation: m3_compile.c:op_i32_Subtract_rs
Unexecuted instantiation: m3_compile.c:op_i32_Multiply_rs
Unexecuted instantiation: m3_compile.c:op_i32_Divide_rs
Unexecuted instantiation: m3_compile.c:op_u32_Divide_rs
Unexecuted instantiation: m3_compile.c:op_i32_Remainder_rs
Unexecuted instantiation: m3_compile.c:op_u32_Remainder_rs
Unexecuted instantiation: m3_compile.c:op_u32_And_rs
Unexecuted instantiation: m3_compile.c:op_u32_Or_rs
Unexecuted instantiation: m3_compile.c:op_u32_Xor_rs
Unexecuted instantiation: m3_compile.c:op_u32_ShiftLeft_rs
Unexecuted instantiation: m3_compile.c:op_i32_ShiftRight_rs
Unexecuted instantiation: m3_compile.c:op_u32_ShiftRight_rs
Unexecuted instantiation: m3_compile.c:op_u32_Rotl_rs
Unexecuted instantiation: m3_compile.c:op_u32_Rotr_rs
Unexecuted instantiation: m3_compile.c:op_i64_Add_rs
Unexecuted instantiation: m3_compile.c:op_i64_Subtract_rs
Unexecuted instantiation: m3_compile.c:op_i64_Multiply_rs
Unexecuted instantiation: m3_compile.c:op_i64_Divide_rs
Unexecuted instantiation: m3_compile.c:op_u64_Divide_rs
Unexecuted instantiation: m3_compile.c:op_i64_Remainder_rs
Unexecuted instantiation: m3_compile.c:op_u64_Remainder_rs
Unexecuted instantiation: m3_compile.c:op_u64_And_rs
Unexecuted instantiation: m3_compile.c:op_u64_Or_rs
Unexecuted instantiation: m3_compile.c:op_u64_Xor_rs
Unexecuted instantiation: m3_compile.c:op_u64_ShiftLeft_rs
Unexecuted instantiation: m3_compile.c:op_i64_ShiftRight_rs
Unexecuted instantiation: m3_compile.c:op_u64_ShiftRight_rs
Unexecuted instantiation: m3_compile.c:op_u64_Rotl_rs
Unexecuted instantiation: m3_compile.c:op_u64_Rotr_rs
Unexecuted instantiation: m3_compile.c:op_f32_Add_rs
Unexecuted instantiation: m3_compile.c:op_f32_Subtract_rs
Unexecuted instantiation: m3_compile.c:op_f32_Multiply_rs
Unexecuted instantiation: m3_compile.c:op_f32_Divide_rs
Unexecuted instantiation: m3_compile.c:op_f32_Min_rs
Unexecuted instantiation: m3_compile.c:op_f32_Max_rs
Unexecuted instantiation: m3_compile.c:op_f32_CopySign_rs
Unexecuted instantiation: m3_compile.c:op_f64_Add_rs
Unexecuted instantiation: m3_compile.c:op_f64_Subtract_rs
Unexecuted instantiation: m3_compile.c:op_f64_Multiply_rs
Unexecuted instantiation: m3_compile.c:op_f64_Divide_rs
Unexecuted instantiation: m3_compile.c:op_f64_Min_rs
Unexecuted instantiation: m3_compile.c:op_f64_Max_rs
Unexecuted instantiation: m3_compile.c:op_f64_CopySign_rs
129
0
d_m3Op(TYPE##_##NAME##_ss)                              \
130
0
{                                                       \
131
0
    TYPE operand2 = slot (TYPE);                        \
132
0
    TYPE operand1 = slot (TYPE);                        \
133
0
    OP((RES), operand1, operand2, ##__VA_ARGS__);       \
134
0
    nextOp ();                                          \
135
0
}
Unexecuted instantiation: m3_compile.c:op_i32_Equal_ss
Unexecuted instantiation: m3_compile.c:op_i32_NotEqual_ss
Unexecuted instantiation: m3_compile.c:op_i32_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_u32_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_i32_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_u32_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_i64_Equal_ss
Unexecuted instantiation: m3_compile.c:op_i64_NotEqual_ss
Unexecuted instantiation: m3_compile.c:op_i64_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_u64_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_i64_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_u64_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_f32_Equal_ss
Unexecuted instantiation: m3_compile.c:op_f32_NotEqual_ss
Unexecuted instantiation: m3_compile.c:op_f32_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_f32_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_f64_Equal_ss
Unexecuted instantiation: m3_compile.c:op_f64_NotEqual_ss
Unexecuted instantiation: m3_compile.c:op_f64_LessThan_ss
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThan_ss
Unexecuted instantiation: m3_compile.c:op_f64_LessThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThanOrEqual_ss
Unexecuted instantiation: m3_compile.c:op_i32_Add_ss
Unexecuted instantiation: m3_compile.c:op_i32_Subtract_ss
Unexecuted instantiation: m3_compile.c:op_i32_Multiply_ss
Unexecuted instantiation: m3_compile.c:op_i32_Divide_ss
Unexecuted instantiation: m3_compile.c:op_u32_Divide_ss
Unexecuted instantiation: m3_compile.c:op_i32_Remainder_ss
Unexecuted instantiation: m3_compile.c:op_u32_Remainder_ss
Unexecuted instantiation: m3_compile.c:op_u32_And_ss
Unexecuted instantiation: m3_compile.c:op_u32_Or_ss
Unexecuted instantiation: m3_compile.c:op_u32_Xor_ss
Unexecuted instantiation: m3_compile.c:op_u32_ShiftLeft_ss
Unexecuted instantiation: m3_compile.c:op_i32_ShiftRight_ss
Unexecuted instantiation: m3_compile.c:op_u32_ShiftRight_ss
Unexecuted instantiation: m3_compile.c:op_u32_Rotl_ss
Unexecuted instantiation: m3_compile.c:op_u32_Rotr_ss
Unexecuted instantiation: m3_compile.c:op_i64_Add_ss
Unexecuted instantiation: m3_compile.c:op_i64_Subtract_ss
Unexecuted instantiation: m3_compile.c:op_i64_Multiply_ss
Unexecuted instantiation: m3_compile.c:op_i64_Divide_ss
Unexecuted instantiation: m3_compile.c:op_u64_Divide_ss
Unexecuted instantiation: m3_compile.c:op_i64_Remainder_ss
Unexecuted instantiation: m3_compile.c:op_u64_Remainder_ss
Unexecuted instantiation: m3_compile.c:op_u64_And_ss
Unexecuted instantiation: m3_compile.c:op_u64_Or_ss
Unexecuted instantiation: m3_compile.c:op_u64_Xor_ss
Unexecuted instantiation: m3_compile.c:op_u64_ShiftLeft_ss
Unexecuted instantiation: m3_compile.c:op_i64_ShiftRight_ss
Unexecuted instantiation: m3_compile.c:op_u64_ShiftRight_ss
Unexecuted instantiation: m3_compile.c:op_u64_Rotl_ss
Unexecuted instantiation: m3_compile.c:op_u64_Rotr_ss
Unexecuted instantiation: m3_compile.c:op_f32_Add_ss
Unexecuted instantiation: m3_compile.c:op_f32_Subtract_ss
Unexecuted instantiation: m3_compile.c:op_f32_Multiply_ss
Unexecuted instantiation: m3_compile.c:op_f32_Divide_ss
Unexecuted instantiation: m3_compile.c:op_f32_Min_ss
Unexecuted instantiation: m3_compile.c:op_f32_Max_ss
Unexecuted instantiation: m3_compile.c:op_f32_CopySign_ss
Unexecuted instantiation: m3_compile.c:op_f64_Add_ss
Unexecuted instantiation: m3_compile.c:op_f64_Subtract_ss
Unexecuted instantiation: m3_compile.c:op_f64_Multiply_ss
Unexecuted instantiation: m3_compile.c:op_f64_Divide_ss
Unexecuted instantiation: m3_compile.c:op_f64_Min_ss
Unexecuted instantiation: m3_compile.c:op_f64_Max_ss
Unexecuted instantiation: m3_compile.c:op_f64_CopySign_ss
136
137
#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...)      \
138
0
d_m3Op(TYPE##_##NAME##_sr)                              \
139
0
{                                                       \
140
0
    TYPE operand = slot (TYPE);                         \
141
0
    OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__);    \
142
0
    nextOp ();                                          \
143
0
}                                                       \
Unexecuted instantiation: m3_compile.c:op_i32_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_u32_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_i32_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_u32_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_i32_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_u32_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_i64_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_u64_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_i64_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_u64_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_i64_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_u64_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_f32_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_f32_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_f32_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_f64_LessThan_sr
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThan_sr
Unexecuted instantiation: m3_compile.c:op_f64_LessThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_f64_GreaterThanOrEqual_sr
Unexecuted instantiation: m3_compile.c:op_i32_Subtract_sr
Unexecuted instantiation: m3_compile.c:op_i32_Divide_sr
Unexecuted instantiation: m3_compile.c:op_u32_Divide_sr
Unexecuted instantiation: m3_compile.c:op_i32_Remainder_sr
Unexecuted instantiation: m3_compile.c:op_u32_Remainder_sr
Unexecuted instantiation: m3_compile.c:op_u32_ShiftLeft_sr
Unexecuted instantiation: m3_compile.c:op_i32_ShiftRight_sr
Unexecuted instantiation: m3_compile.c:op_u32_ShiftRight_sr
Unexecuted instantiation: m3_compile.c:op_u32_Rotl_sr
Unexecuted instantiation: m3_compile.c:op_u32_Rotr_sr
Unexecuted instantiation: m3_compile.c:op_i64_Subtract_sr
Unexecuted instantiation: m3_compile.c:op_i64_Divide_sr
Unexecuted instantiation: m3_compile.c:op_u64_Divide_sr
Unexecuted instantiation: m3_compile.c:op_i64_Remainder_sr
Unexecuted instantiation: m3_compile.c:op_u64_Remainder_sr
Unexecuted instantiation: m3_compile.c:op_u64_ShiftLeft_sr
Unexecuted instantiation: m3_compile.c:op_i64_ShiftRight_sr
Unexecuted instantiation: m3_compile.c:op_u64_ShiftRight_sr
Unexecuted instantiation: m3_compile.c:op_u64_Rotl_sr
Unexecuted instantiation: m3_compile.c:op_u64_Rotr_sr
Unexecuted instantiation: m3_compile.c:op_f32_Subtract_sr
Unexecuted instantiation: m3_compile.c:op_f32_Divide_sr
Unexecuted instantiation: m3_compile.c:op_f32_CopySign_sr
Unexecuted instantiation: m3_compile.c:op_f64_Subtract_sr
Unexecuted instantiation: m3_compile.c:op_f64_Divide_sr
Unexecuted instantiation: m3_compile.c:op_f64_CopySign_sr
Unexecuted instantiation: m3_compile.c:op_f32_Min_sr
Unexecuted instantiation: m3_compile.c:op_f32_Max_sr
Unexecuted instantiation: m3_compile.c:op_f64_Min_sr
Unexecuted instantiation: m3_compile.c:op_f64_Max_sr
144
d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__)
145
146
// Accept macros
147
#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...)    d_m3CommutativeOpMacro  ( _r0,  _r0, TYPE, NAME, MACRO, ##__VA_ARGS__)
148
#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...)               d_m3OpMacro             ( _r0,  _r0, TYPE, NAME, MACRO, ##__VA_ARGS__)
149
#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...)    d_m3CommutativeOpMacro  (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__)
150
#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...)               d_m3OpMacro             (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__)
151
152
0
#define M3_FUNC(RES, A, B, OP)  (RES) = OP((A), (B))    // Accept functions: res = OP(a,b)
153
0
#define M3_OPER(RES, A, B, OP)  (RES) = ((A) OP (B))    // Accept operators: res = a OP b
154
155
#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP)     d_m3CommutativeOpMacro_i    (TYPE, NAME, M3_FUNC, OP)
156
0
#define d_m3OpFunc_i(TYPE, NAME, OP)                d_m3OpMacro_i               (TYPE, NAME, M3_FUNC, OP)
157
#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP)     d_m3CommutativeOpMacro_f    (TYPE, NAME, M3_FUNC, OP)
158
0
#define d_m3OpFunc_f(TYPE, NAME, OP)                d_m3OpMacro_f               (TYPE, NAME, M3_FUNC, OP)
159
160
0
#define d_m3CommutativeOp_i(TYPE, NAME, OP)         d_m3CommutativeOpMacro_i    (TYPE, NAME, M3_OPER, OP)
161
0
#define d_m3Op_i(TYPE, NAME, OP)                    d_m3OpMacro_i               (TYPE, NAME, M3_OPER, OP)
162
0
#define d_m3CommutativeOp_f(TYPE, NAME, OP)         d_m3CommutativeOpMacro_f    (TYPE, NAME, M3_OPER, OP)
163
0
#define d_m3Op_f(TYPE, NAME, OP)                    d_m3OpMacro_f               (TYPE, NAME, M3_OPER, OP)
164
165
// compare needs to be distinct for fp 'cause the result must be _r0
166
0
#define d_m3CompareOp_f(TYPE, NAME, OP)             d_m3OpMacro                 (_r0, _fp0, TYPE, NAME, M3_OPER, OP)
167
0
#define d_m3CommutativeCmpOp_f(TYPE, NAME, OP)      d_m3CommutativeOpMacro      (_r0, _fp0, TYPE, NAME, M3_OPER, OP)
168
169
170
//-----------------------
171
172
// signed
173
d_m3CommutativeOp_i (i32, Equal,            ==)     d_m3CommutativeOp_i (i64, Equal,            ==)
174
d_m3CommutativeOp_i (i32, NotEqual,         !=)     d_m3CommutativeOp_i (i64, NotEqual,         !=)
175
176
d_m3Op_i (i32, LessThan,                    < )     d_m3Op_i (i64, LessThan,                    < )
177
d_m3Op_i (i32, GreaterThan,                 > )     d_m3Op_i (i64, GreaterThan,                 > )
178
d_m3Op_i (i32, LessThanOrEqual,             <=)     d_m3Op_i (i64, LessThanOrEqual,             <=)
179
d_m3Op_i (i32, GreaterThanOrEqual,          >=)     d_m3Op_i (i64, GreaterThanOrEqual,          >=)
180
181
// unsigned
182
d_m3Op_i (u32, LessThan,                    < )     d_m3Op_i (u64, LessThan,                    < )
183
d_m3Op_i (u32, GreaterThan,                 > )     d_m3Op_i (u64, GreaterThan,                 > )
184
d_m3Op_i (u32, LessThanOrEqual,             <=)     d_m3Op_i (u64, LessThanOrEqual,             <=)
185
d_m3Op_i (u32, GreaterThanOrEqual,          >=)     d_m3Op_i (u64, GreaterThanOrEqual,          >=)
186
187
#if d_m3HasFloat
188
d_m3CommutativeCmpOp_f (f32, Equal,         ==)     d_m3CommutativeCmpOp_f (f64, Equal,         ==)
189
d_m3CommutativeCmpOp_f (f32, NotEqual,      !=)     d_m3CommutativeCmpOp_f (f64, NotEqual,      !=)
190
d_m3CompareOp_f (f32, LessThan,             < )     d_m3CompareOp_f (f64, LessThan,             < )
191
d_m3CompareOp_f (f32, GreaterThan,          > )     d_m3CompareOp_f (f64, GreaterThan,          > )
192
d_m3CompareOp_f (f32, LessThanOrEqual,      <=)     d_m3CompareOp_f (f64, LessThanOrEqual,      <=)
193
d_m3CompareOp_f (f32, GreaterThanOrEqual,   >=)     d_m3CompareOp_f (f64, GreaterThanOrEqual,   >=)
194
#endif
195
196
d_m3CommutativeOp_i (i32, Add,              +)      d_m3CommutativeOp_i (i64, Add,              +)
197
d_m3CommutativeOp_i (i32, Multiply,         *)      d_m3CommutativeOp_i (i64, Multiply,         *)
198
199
d_m3Op_i (i32, Subtract,                    -)      d_m3Op_i (i64, Subtract,                    -)
200
201
0
#define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32))
202
0
#define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64))
203
0
#define OP_SHR_32(X,N) ((X) >> ((u32)(N) % 32))
204
0
#define OP_SHR_64(X,N) ((X) >> ((u64)(N) % 64))
205
206
0
d_m3OpFunc_i (u32, ShiftLeft,       OP_SHL_32)      d_m3OpFunc_i (u64, ShiftLeft,       OP_SHL_64)
207
0
d_m3OpFunc_i (i32, ShiftRight,      OP_SHR_32)      d_m3OpFunc_i (i64, ShiftRight,      OP_SHR_64)
208
0
d_m3OpFunc_i (u32, ShiftRight,      OP_SHR_32)      d_m3OpFunc_i (u64, ShiftRight,      OP_SHR_64)
209
210
d_m3CommutativeOp_i (u32, And,              &)
211
d_m3CommutativeOp_i (u32, Or,               |)
212
d_m3CommutativeOp_i (u32, Xor,              ^)
213
214
d_m3CommutativeOp_i (u64, And,              &)
215
d_m3CommutativeOp_i (u64, Or,               |)
216
d_m3CommutativeOp_i (u64, Xor,              ^)
217
218
#if d_m3HasFloat
219
d_m3CommutativeOp_f (f32, Add,              +)      d_m3CommutativeOp_f (f64, Add,              +)
220
d_m3CommutativeOp_f (f32, Multiply,         *)      d_m3CommutativeOp_f (f64, Multiply,         *)
221
d_m3Op_f (f32, Subtract,                    -)      d_m3Op_f (f64, Subtract,                    -)
222
d_m3Op_f (f32, Divide,                      /)      d_m3Op_f (f64, Divide,                      /)
223
#endif
224
225
d_m3OpFunc_i(u32, Rotl, rotl32)
226
d_m3OpFunc_i(u32, Rotr, rotr32)
227
d_m3OpFunc_i(u64, Rotl, rotl64)
228
d_m3OpFunc_i(u64, Rotr, rotr64)
229
230
0
d_m3OpMacro_i(u32, Divide, OP_DIV_U);
231
0
d_m3OpMacro_i(i32, Divide, OP_DIV_S, INT32_MIN);
232
0
d_m3OpMacro_i(u64, Divide, OP_DIV_U);
233
0
d_m3OpMacro_i(i64, Divide, OP_DIV_S, INT64_MIN);
234
235
0
d_m3OpMacro_i(u32, Remainder, OP_REM_U);
236
0
d_m3OpMacro_i(i32, Remainder, OP_REM_S, INT32_MIN);
237
0
d_m3OpMacro_i(u64, Remainder, OP_REM_U);
238
0
d_m3OpMacro_i(i64, Remainder, OP_REM_S, INT64_MIN);
239
240
#if d_m3HasFloat
241
d_m3OpFunc_f(f32, Min, min_f32);
242
d_m3OpFunc_f(f32, Max, max_f32);
243
d_m3OpFunc_f(f64, Min, min_f64);
244
d_m3OpFunc_f(f64, Max, max_f64);
245
246
d_m3OpFunc_f(f32, CopySign, copysignf);
247
d_m3OpFunc_f(f64, CopySign, copysign);
248
#endif
249
250
// Unary operations
251
// Note: This macro follows the principle of d_m3OpMacro
252
253
#define d_m3UnaryMacro(RES, REG, TYPE, NAME, OP, ...)   \
254
0
d_m3Op(TYPE##_##NAME##_r)                           \
255
0
{                                                   \
256
0
    OP((RES), (TYPE) REG, ##__VA_ARGS__);           \
257
0
    nextOp ();                                      \
258
0
}                                                   \
Unexecuted instantiation: m3_compile.c:op_i32_EqualToZero_r
Unexecuted instantiation: m3_compile.c:op_i64_EqualToZero_r
Unexecuted instantiation: m3_compile.c:op_u32_Clz_r
Unexecuted instantiation: m3_compile.c:op_u32_Ctz_r
Unexecuted instantiation: m3_compile.c:op_u32_Popcnt_r
Unexecuted instantiation: m3_compile.c:op_u64_Clz_r
Unexecuted instantiation: m3_compile.c:op_u64_Ctz_r
Unexecuted instantiation: m3_compile.c:op_u64_Popcnt_r
Unexecuted instantiation: m3_compile.c:op_f32_Abs_r
Unexecuted instantiation: m3_compile.c:op_f32_Negate_r
Unexecuted instantiation: m3_compile.c:op_f32_Ceil_r
Unexecuted instantiation: m3_compile.c:op_f32_Floor_r
Unexecuted instantiation: m3_compile.c:op_f32_Trunc_r
Unexecuted instantiation: m3_compile.c:op_f32_Nearest_r
Unexecuted instantiation: m3_compile.c:op_f32_Sqrt_r
Unexecuted instantiation: m3_compile.c:op_f64_Abs_r
Unexecuted instantiation: m3_compile.c:op_f64_Negate_r
Unexecuted instantiation: m3_compile.c:op_f64_Ceil_r
Unexecuted instantiation: m3_compile.c:op_f64_Floor_r
Unexecuted instantiation: m3_compile.c:op_f64_Trunc_r
Unexecuted instantiation: m3_compile.c:op_f64_Nearest_r
Unexecuted instantiation: m3_compile.c:op_f64_Sqrt_r
Unexecuted instantiation: m3_compile.c:op_i32_Extend8_s_r
Unexecuted instantiation: m3_compile.c:op_i32_Extend16_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Extend8_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Extend16_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Extend32_s_r
259
0
d_m3Op(TYPE##_##NAME##_s)                           \
260
0
{                                                   \
261
0
    TYPE operand = slot (TYPE);                     \
262
0
    OP((RES), operand, ##__VA_ARGS__);              \
263
0
    nextOp ();                                      \
264
0
}
Unexecuted instantiation: m3_compile.c:op_i32_EqualToZero_s
Unexecuted instantiation: m3_compile.c:op_i64_EqualToZero_s
Unexecuted instantiation: m3_compile.c:op_u32_Clz_s
Unexecuted instantiation: m3_compile.c:op_u32_Ctz_s
Unexecuted instantiation: m3_compile.c:op_u32_Popcnt_s
Unexecuted instantiation: m3_compile.c:op_u64_Clz_s
Unexecuted instantiation: m3_compile.c:op_u64_Ctz_s
Unexecuted instantiation: m3_compile.c:op_u64_Popcnt_s
Unexecuted instantiation: m3_compile.c:op_f32_Abs_s
Unexecuted instantiation: m3_compile.c:op_f32_Negate_s
Unexecuted instantiation: m3_compile.c:op_f32_Ceil_s
Unexecuted instantiation: m3_compile.c:op_f32_Floor_s
Unexecuted instantiation: m3_compile.c:op_f32_Trunc_s
Unexecuted instantiation: m3_compile.c:op_f32_Nearest_s
Unexecuted instantiation: m3_compile.c:op_f32_Sqrt_s
Unexecuted instantiation: m3_compile.c:op_f64_Abs_s
Unexecuted instantiation: m3_compile.c:op_f64_Negate_s
Unexecuted instantiation: m3_compile.c:op_f64_Ceil_s
Unexecuted instantiation: m3_compile.c:op_f64_Floor_s
Unexecuted instantiation: m3_compile.c:op_f64_Trunc_s
Unexecuted instantiation: m3_compile.c:op_f64_Nearest_s
Unexecuted instantiation: m3_compile.c:op_f64_Sqrt_s
Unexecuted instantiation: m3_compile.c:op_i32_Extend8_s_s
Unexecuted instantiation: m3_compile.c:op_i32_Extend16_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Extend8_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Extend16_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Extend32_s_s
265
266
0
#define M3_UNARY(RES, X, OP) (RES) = OP(X)
267
0
#define d_m3UnaryOp_i(TYPE, NAME, OPERATION)        d_m3UnaryMacro( _r0,  _r0, TYPE, NAME, M3_UNARY, OPERATION)
268
0
#define d_m3UnaryOp_f(TYPE, NAME, OPERATION)        d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY, OPERATION)
269
270
#if d_m3HasFloat
271
d_m3UnaryOp_f (f32, Abs,        fabsf);         d_m3UnaryOp_f (f64, Abs,        fabs);
272
d_m3UnaryOp_f (f32, Ceil,       ceilf);         d_m3UnaryOp_f (f64, Ceil,       ceil);
273
d_m3UnaryOp_f (f32, Floor,      floorf);        d_m3UnaryOp_f (f64, Floor,      floor);
274
d_m3UnaryOp_f (f32, Trunc,      truncf);        d_m3UnaryOp_f (f64, Trunc,      trunc);
275
d_m3UnaryOp_f (f32, Sqrt,       sqrtf);         d_m3UnaryOp_f (f64, Sqrt,       sqrt);
276
d_m3UnaryOp_f (f32, Nearest,    rintf);         d_m3UnaryOp_f (f64, Nearest,    rint);
277
d_m3UnaryOp_f (f32, Negate,     -);             d_m3UnaryOp_f (f64, Negate,     -);
278
#endif
279
280
0
#define OP_EQZ(x) ((x) == 0)
281
282
0
d_m3UnaryOp_i (i32, EqualToZero, OP_EQZ)
283
0
d_m3UnaryOp_i (i64, EqualToZero, OP_EQZ)
284
285
// clz(0), ctz(0) results are undefined for rest platforms, fix it
286
#if (defined(__i386__) || defined(__x86_64__)) && !(defined(__AVX2__) || (defined(__ABM__) && defined(__BMI__)))
287
    #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x))
288
    #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x))
289
    // for 64-bit instructions branchless approach more preferable
290
    #define OP_CLZ_64(x) (__builtin_clzll((x) | (1LL <<  0)) + OP_EQZ(x))
291
    #define OP_CTZ_64(x) (__builtin_ctzll((x) | (1LL << 63)) + OP_EQZ(x))
292
#elif defined(__ppc__) || defined(__ppc64__)
293
// PowerPC is defined for __builtin_clz(0) and __builtin_ctz(0).
294
// See (https://github.com/aquynh/capstone/blob/master/MathExtras.h#L99)
295
    #define OP_CLZ_32(x) __builtin_clz(x)
296
    #define OP_CTZ_32(x) __builtin_ctz(x)
297
    #define OP_CLZ_64(x) __builtin_clzll(x)
298
    #define OP_CTZ_64(x) __builtin_ctzll(x)
299
#else
300
0
    #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x))
301
0
    #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x))
302
0
    #define OP_CLZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_clzll(x))
303
0
    #define OP_CTZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_ctzll(x))
304
#endif
305
306
0
d_m3UnaryOp_i (u32, Clz, OP_CLZ_32)
307
0
d_m3UnaryOp_i (u64, Clz, OP_CLZ_64)
308
309
0
d_m3UnaryOp_i (u32, Ctz, OP_CTZ_32)
310
0
d_m3UnaryOp_i (u64, Ctz, OP_CTZ_64)
311
312
d_m3UnaryOp_i (u32, Popcnt, __builtin_popcount)
313
d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll)
314
315
0
#define OP_WRAP_I64(X) ((X) & 0x00000000ffffffff)
316
317
d_m3Op(i32_Wrap_i64_r)
318
0
{
319
0
    _r0 = OP_WRAP_I64((i64) _r0);
320
0
    nextOp ();
321
0
}
322
323
d_m3Op(i32_Wrap_i64_s)
324
0
{
325
0
    i64 operand = slot (i64);
326
0
    _r0 = OP_WRAP_I64(operand);
327
0
    nextOp ();
328
0
}
329
330
// Integer sign extension operations
331
0
#define OP_EXTEND8_S_I32(X)  ((int32_t)(int8_t)(X))
332
0
#define OP_EXTEND16_S_I32(X) ((int32_t)(int16_t)(X))
333
0
#define OP_EXTEND8_S_I64(X)  ((int64_t)(int8_t)(X))
334
0
#define OP_EXTEND16_S_I64(X) ((int64_t)(int16_t)(X))
335
0
#define OP_EXTEND32_S_I64(X) ((int64_t)(int32_t)(X))
336
337
0
d_m3UnaryOp_i (i32, Extend8_s,  OP_EXTEND8_S_I32)
338
0
d_m3UnaryOp_i (i32, Extend16_s, OP_EXTEND16_S_I32)
339
0
d_m3UnaryOp_i (i64, Extend8_s,  OP_EXTEND8_S_I64)
340
0
d_m3UnaryOp_i (i64, Extend16_s, OP_EXTEND16_S_I64)
341
0
d_m3UnaryOp_i (i64, Extend32_s, OP_EXTEND32_S_I64)
342
343
#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...)   \
344
0
d_m3Op(TYPE##_##NAME##_##FROM##_r_r)                \
345
0
{                                                   \
346
0
    OP((DEST), (FROM) SRC, ##__VA_ARGS__);          \
347
0
    nextOp ();                                      \
348
0
}                                                   \
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f32_r_r
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f32_r_r
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f64_r_r
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f64_r_r
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f32_r_r
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f32_r_r
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f64_r_r
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f64_r_r
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f32_r_r
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f32_r_r
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f64_r_r
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f64_r_r
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f32_r_r
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f32_r_r
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f64_r_r
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f64_r_r
349
0
d_m3Op(TYPE##_##NAME##_##FROM##_r_s)                \
350
0
{                                                   \
351
0
    FROM * stack = slot_ptr (FROM);                 \
352
0
    OP((DEST), (* stack), ##__VA_ARGS__);           \
353
0
    nextOp ();                                      \
354
0
}                                                   \
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f32_r_s
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f32_r_s
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f64_r_s
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f64_r_s
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f32_r_s
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f32_r_s
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f64_r_s
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f64_r_s
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f32_r_s
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f32_r_s
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f64_r_s
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f64_r_s
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f32_r_s
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f32_r_s
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f64_r_s
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f64_r_s
355
0
d_m3Op(TYPE##_##NAME##_##FROM##_s_r)                \
356
0
{                                                   \
357
0
    TYPE * dest = slot_ptr (TYPE);                  \
358
0
    OP((* dest), (FROM) SRC, ##__VA_ARGS__);        \
359
0
    nextOp ();                                      \
360
0
}                                                   \
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f32_s_r
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f32_s_r
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f64_s_r
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f64_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f32_s_r
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f32_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f64_s_r
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f64_s_r
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f32_s_r
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f32_s_r
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f64_s_r
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f64_s_r
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f32_s_r
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f32_s_r
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f64_s_r
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f64_s_r
361
0
d_m3Op(TYPE##_##NAME##_##FROM##_s_s)                \
362
0
{                                                   \
363
0
    FROM * stack = slot_ptr (FROM);                 \
364
0
    TYPE * dest = slot_ptr (TYPE);                  \
365
0
    OP((* dest), (* stack), ##__VA_ARGS__);         \
366
0
    nextOp ();                                      \
367
0
}
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f32_s_s
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f32_s_s
Unexecuted instantiation: m3_compile.c:op_i32_Trunc_f64_s_s
Unexecuted instantiation: m3_compile.c:op_u32_Trunc_f64_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f32_s_s
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f32_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Trunc_f64_s_s
Unexecuted instantiation: m3_compile.c:op_u64_Trunc_f64_s_s
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f32_s_s
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f32_s_s
Unexecuted instantiation: m3_compile.c:op_i32_TruncSat_f64_s_s
Unexecuted instantiation: m3_compile.c:op_u32_TruncSat_f64_s_s
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f32_s_s
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f32_s_s
Unexecuted instantiation: m3_compile.c:op_i64_TruncSat_f64_s_s
Unexecuted instantiation: m3_compile.c:op_u64_TruncSat_f64_s_s
368
369
#if d_m3HasFloat
370
0
d_m3TruncMacro(_r0, _fp0, i32, Trunc, f32, OP_I32_TRUNC_F32)
371
0
d_m3TruncMacro(_r0, _fp0, u32, Trunc, f32, OP_U32_TRUNC_F32)
372
0
d_m3TruncMacro(_r0, _fp0, i32, Trunc, f64, OP_I32_TRUNC_F64)
373
0
d_m3TruncMacro(_r0, _fp0, u32, Trunc, f64, OP_U32_TRUNC_F64)
374
375
0
d_m3TruncMacro(_r0, _fp0, i64, Trunc, f32, OP_I64_TRUNC_F32)
376
0
d_m3TruncMacro(_r0, _fp0, u64, Trunc, f32, OP_U64_TRUNC_F32)
377
0
d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64)
378
0
d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64)
379
380
0
d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f32, OP_I32_TRUNC_SAT_F32)
381
0
d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f32, OP_U32_TRUNC_SAT_F32)
382
0
d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f64, OP_I32_TRUNC_SAT_F64)
383
0
d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f64, OP_U32_TRUNC_SAT_F64)
384
385
0
d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f32, OP_I64_TRUNC_SAT_F32)
386
0
d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f32, OP_U64_TRUNC_SAT_F32)
387
0
d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f64, OP_I64_TRUNC_SAT_F64)
388
0
d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f64, OP_U64_TRUNC_SAT_F64)
389
#endif
390
391
#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM)  \
392
0
d_m3Op(TO##_##NAME##_##FROM##_r)                            \
393
0
{                                                           \
394
0
    REG_TO = (TO) ((FROM) REG_FROM);                        \
395
0
    nextOp ();                                              \
396
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_i64_Extend_i32_r
Unexecuted instantiation: m3_compile.c:op_i64_Extend_u32_r
Unexecuted instantiation: m3_compile.c:op_f32_Demote_f64_r
Unexecuted instantiation: m3_compile.c:op_f64_Promote_f32_r
397
                                                            \
398
0
d_m3Op(TO##_##NAME##_##FROM##_s)                            \
399
0
{                                                           \
400
0
    FROM from = slot (FROM);                                \
401
0
    REG_TO = (TO) (from);                                   \
402
0
    nextOp ();                                              \
403
0
}
Unexecuted instantiation: m3_compile.c:op_i64_Extend_i32_s
Unexecuted instantiation: m3_compile.c:op_i64_Extend_u32_s
Unexecuted instantiation: m3_compile.c:op_f32_Demote_f64_s
Unexecuted instantiation: m3_compile.c:op_f64_Promote_f32_s
404
405
// Int to int
406
d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32);
407
d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32);
408
409
// Float to float
410
#if d_m3HasFloat
411
d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64);
412
d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32);
413
#endif
414
415
#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \
416
0
d_m3Op(TO##_##NAME##_##FROM##_r_r)                          \
417
0
{                                                           \
418
0
    REG_TO = (TO) ((FROM) REG_FROM);                        \
419
0
    nextOp ();                                              \
420
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i32_r_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u32_r_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i64_r_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u64_r_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i32_r_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u32_r_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i64_r_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u64_r_r
421
                                                            \
422
0
d_m3Op(TO##_##NAME##_##FROM##_s_r)                          \
423
0
{                                                           \
424
0
    slot (TO) = (TO) ((FROM) REG_FROM);                     \
425
0
    nextOp ();                                              \
426
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i32_s_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u32_s_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i64_s_r
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u64_s_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i32_s_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u32_s_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i64_s_r
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u64_s_r
427
                                                            \
428
0
d_m3Op(TO##_##NAME##_##FROM##_r_s)                          \
429
0
{                                                           \
430
0
    FROM from = slot (FROM);                                \
431
0
    REG_TO = (TO) (from);                                   \
432
0
    nextOp ();                                              \
433
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i32_r_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u32_r_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i64_r_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u64_r_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i32_r_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u32_r_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i64_r_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u64_r_s
434
                                                            \
435
0
d_m3Op(TO##_##NAME##_##FROM##_s_s)                          \
436
0
{                                                           \
437
0
    FROM from = slot (FROM);                                \
438
0
    slot (TO) = (TO) (from);                                \
439
0
    nextOp ();                                              \
440
0
}
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i32_s_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u32_s_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_i64_s_s
Unexecuted instantiation: m3_compile.c:op_f32_Convert_u64_s_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i32_s_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u32_s_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_i64_s_s
Unexecuted instantiation: m3_compile.c:op_f64_Convert_u64_s_s
441
442
// Int to float
443
#if d_m3HasFloat
444
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32);
445
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32);
446
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64);
447
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64);
448
449
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32);
450
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32);
451
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64);
452
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64);
453
#endif
454
455
#define d_m3ReinterpretOp(REG, TO, SRC, FROM)               \
456
0
d_m3Op(TO##_Reinterpret_##FROM##_r_r)                       \
457
0
{                                                           \
458
0
    union { FROM c; TO t; } u;                              \
459
0
    u.c = (FROM) SRC;                                       \
460
0
    REG = u.t;                                              \
461
0
    nextOp ();                                              \
462
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_i32_Reinterpret_f32_r_r
Unexecuted instantiation: m3_compile.c:op_i64_Reinterpret_f64_r_r
Unexecuted instantiation: m3_compile.c:op_f32_Reinterpret_i32_r_r
Unexecuted instantiation: m3_compile.c:op_f64_Reinterpret_i64_r_r
463
                                                            \
464
0
d_m3Op(TO##_Reinterpret_##FROM##_r_s)                       \
465
0
{                                                           \
466
0
    union { FROM c; TO t; } u;                              \
467
0
    u.c = slot (FROM);                                      \
468
0
    REG = u.t;                                              \
469
0
    nextOp ();                                              \
470
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_i32_Reinterpret_f32_r_s
Unexecuted instantiation: m3_compile.c:op_i64_Reinterpret_f64_r_s
Unexecuted instantiation: m3_compile.c:op_f32_Reinterpret_i32_r_s
Unexecuted instantiation: m3_compile.c:op_f64_Reinterpret_i64_r_s
471
                                                            \
472
0
d_m3Op(TO##_Reinterpret_##FROM##_s_r)                       \
473
0
{                                                           \
474
0
    union { FROM c; TO t; } u;                              \
475
0
    u.c = (FROM) SRC;                                       \
476
0
    slot (TO) = u.t;                                        \
477
0
    nextOp ();                                              \
478
0
}                                                           \
Unexecuted instantiation: m3_compile.c:op_i32_Reinterpret_f32_s_r
Unexecuted instantiation: m3_compile.c:op_i64_Reinterpret_f64_s_r
Unexecuted instantiation: m3_compile.c:op_f32_Reinterpret_i32_s_r
Unexecuted instantiation: m3_compile.c:op_f64_Reinterpret_i64_s_r
479
                                                            \
480
0
d_m3Op(TO##_Reinterpret_##FROM##_s_s)                       \
481
0
{                                                           \
482
0
    union { FROM c; TO t; } u;                              \
483
0
    u.c = slot (FROM);                                      \
484
0
    slot (TO) = u.t;                                        \
485
0
    nextOp ();                                              \
486
0
}
Unexecuted instantiation: m3_compile.c:op_i32_Reinterpret_f32_s_s
Unexecuted instantiation: m3_compile.c:op_i64_Reinterpret_f64_s_s
Unexecuted instantiation: m3_compile.c:op_f32_Reinterpret_i32_s_s
Unexecuted instantiation: m3_compile.c:op_f64_Reinterpret_i64_s_s
487
488
#if d_m3HasFloat
489
d_m3ReinterpretOp (_r0, i32, _fp0, f32)
490
d_m3ReinterpretOp (_r0, i64, _fp0, f64)
491
d_m3ReinterpretOp (_fp0, f32, _r0, i32)
492
d_m3ReinterpretOp (_fp0, f64, _r0, i64)
493
#endif
494
495
496
d_m3Op  (GetGlobal_s32)
497
591
{
498
591
    u32 * global = immediate (u32 *);
499
591
    slot (u32) = * global;                        //  printf ("get global: %p %" PRIi64 "\n", global, *global);
500
501
591
    nextOp ();
502
591
}
503
504
505
d_m3Op  (GetGlobal_s64)
506
357
{
507
357
    u64 * global = immediate (u64 *);
508
357
    slot (u64) = * global;                        // printf ("get global: %p %" PRIi64 "\n", global, *global);
509
510
357
    nextOp ();
511
357
}
512
513
514
d_m3Op  (SetGlobal_i32)
515
0
{
516
0
    u32 * global = immediate (u32 *);
517
0
    * global = (u32) _r0;                         //  printf ("set global: %p %" PRIi64 "\n", global, _r0);
518
519
0
    nextOp ();
520
0
}
521
522
523
d_m3Op  (SetGlobal_i64)
524
0
{
525
0
    u64 * global = immediate (u64 *);
526
0
    * global = (u64) _r0;                         //  printf ("set global: %p %" PRIi64 "\n", global, _r0);
527
528
0
    nextOp ();
529
0
}
530
531
532
d_m3Op  (Call)
533
0
{
534
0
    pc_t callPC                 = immediate (pc_t);
535
0
    i32 stackOffset             = immediate (i32);
536
0
    IM3Memory memory            = m3MemInfo (_mem);
537
538
0
    m3stack_t sp = _sp + stackOffset;
539
540
0
    m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs);
541
0
    _mem = memory->mallocated;
542
543
0
    if (M3_LIKELY(not r))
544
0
        nextOp ();
545
0
    else
546
0
    {
547
0
        pushBacktraceFrame ();
548
0
        forwardTrap (r);
549
0
    }
550
0
}
551
552
553
d_m3Op  (CallIndirect)
554
0
{
555
0
    u32 tableIndex              = slot (u32);
556
0
    IM3Module module            = immediate (IM3Module);
557
0
    IM3FuncType type            = immediate (IM3FuncType);
558
0
    i32 stackOffset             = immediate (i32);
559
0
    IM3Memory memory            = m3MemInfo (_mem);
560
561
0
    m3stack_t sp = _sp + stackOffset;
562
563
0
    m3ret_t r = m3Err_none;
564
565
0
    if (M3_LIKELY(tableIndex < module->table0Size))
566
0
    {
567
0
        IM3Function function = module->table0 [tableIndex];
568
569
0
        if (M3_LIKELY(function))
570
0
        {
571
0
            if (M3_LIKELY(type == function->funcType))
572
0
            {
573
0
                if (M3_UNLIKELY(not function->compiled))
574
0
                    r = CompileFunction (function);
575
576
0
                if (M3_LIKELY(not r))
577
0
                {
578
0
                    r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs);
579
0
                    _mem = memory->mallocated;
580
581
0
                    if (M3_LIKELY(not r))
582
0
                        nextOpDirect ();
583
0
                    else
584
0
                    {
585
0
                        pushBacktraceFrame ();
586
0
                        forwardTrap (r);
587
0
                    }
588
0
                }
589
0
            }
590
0
            else r = m3Err_trapIndirectCallTypeMismatch;
591
0
        }
592
0
        else r = m3Err_trapTableElementIsNull;
593
0
    }
594
0
    else r = m3Err_trapTableIndexOutOfRange;
595
596
0
    if (M3_UNLIKELY(r))
597
0
        newTrap (r);
598
0
    else forwardTrap (r);
599
0
}
600
601
602
d_m3Op  (CallRawFunction)
603
0
{
604
0
    d_m3TracePrepare
605
606
0
    M3ImportContext ctx;
607
608
0
    M3RawCall call = (M3RawCall) (* _pc++);
609
0
    ctx.function = immediate (IM3Function);
610
0
    ctx.userdata = immediate (void *);
611
0
    u64* const sp = ((u64*)_sp);
612
0
    IM3Memory memory = m3MemInfo (_mem);
613
614
0
    IM3Runtime runtime = m3MemRuntime(_mem);
615
616
#if d_m3EnableStrace
617
    IM3FuncType ftype = ctx.function->funcType;
618
619
    FILE* out = stderr;
620
    char outbuff[1024];
621
    char* outp = outbuff;
622
    char* oute = outbuff+1024;
623
624
    outp += snprintf(outp, oute-outp, "%s!%s(", ctx.function->import.moduleUtf8, ctx.function->import.fieldUtf8);
625
626
    const int nArgs = ftype->numArgs;
627
    const int nRets = ftype->numRets;
628
    u64 * args = sp + nRets;
629
    for (int i=0; i<nArgs; i++) {
630
        const int type = ftype->types[nRets + i];
631
        switch (type) {
632
        case c_m3Type_i32:  outp += snprintf(outp, oute-outp, "%" PRIi32, *(i32*)(args+i)); break;
633
        case c_m3Type_i64:  outp += snprintf(outp, oute-outp, "%" PRIi64, *(i64*)(args+i)); break;
634
        case c_m3Type_f32:  outp += snprintf(outp, oute-outp, "%" PRIf32, *(f32*)(args+i)); break;
635
        case c_m3Type_f64:  outp += snprintf(outp, oute-outp, "%" PRIf64, *(f64*)(args+i)); break;
636
        default:            outp += snprintf(outp, oute-outp, "<type %d>", type);         break;
637
        }
638
        outp += snprintf(outp, oute-outp, (i < nArgs-1) ? ", " : ")");
639
    }
640
# if d_m3EnableStrace >= 2
641
    outp += snprintf(outp, oute-outp, " { <native> }");
642
# endif
643
#endif
644
645
    // m3_Call uses runtime->stack to set-up initial exported function stack.
646
    // Reconfigure the stack to enable recursive invocations of m3_Call.
647
    // I.e. exported/table function can be called from an impoted function.
648
0
    void* stack_backup = runtime->stack;
649
0
    runtime->stack = sp;
650
0
    m3ret_t possible_trap = call (runtime, &ctx, sp, m3MemData(_mem));
651
0
    runtime->stack = stack_backup;
652
653
#if d_m3EnableStrace
654
    if (M3_UNLIKELY(possible_trap)) {
655
        d_m3TracePrint("%s -> %s", outbuff, (char*)possible_trap);
656
    } else {
657
        switch (GetSingleRetType(ftype)) {
658
        case c_m3Type_none: d_m3TracePrint("%s", outbuff); break;
659
        case c_m3Type_i32:  d_m3TracePrint("%s = %" PRIi32, outbuff, *(i32*)sp); break;
660
        case c_m3Type_i64:  d_m3TracePrint("%s = %" PRIi64, outbuff, *(i64*)sp); break;
661
        case c_m3Type_f32:  d_m3TracePrint("%s = %" PRIf32, outbuff, *(f32*)sp); break;
662
        case c_m3Type_f64:  d_m3TracePrint("%s = %" PRIf64, outbuff, *(f64*)sp); break;
663
        }
664
    }
665
#endif
666
667
0
    if (M3_UNLIKELY(possible_trap)) {
668
0
        _mem = memory->mallocated;
669
0
        pushBacktraceFrame ();
670
0
    }
671
0
    forwardTrap (possible_trap);
672
0
}
673
674
675
d_m3Op  (MemSize)
676
0
{
677
0
    IM3Memory memory            = m3MemInfo (_mem);
678
679
0
    _r0 = memory->numPages;
680
681
0
    nextOp ();
682
0
}
683
684
685
d_m3Op  (MemGrow)
686
0
{
687
0
    IM3Runtime runtime          = m3MemRuntime(_mem);
688
0
    IM3Memory memory            = & runtime->memory;
689
690
0
    u32 numPagesToGrow = (u32) _r0;
691
0
    _r0 = memory->numPages;
692
693
0
    if (M3_LIKELY(numPagesToGrow))
694
0
    {
695
0
        u32 requiredPages = memory->numPages + numPagesToGrow;
696
697
0
        M3Result r = ResizeMemory (runtime, requiredPages);
698
0
        if (r)
699
0
            _r0 = -1;
700
701
0
        _mem = memory->mallocated;
702
0
    }
703
704
0
    nextOp ();
705
0
}
706
707
708
d_m3Op  (MemCopy)
709
0
{
710
0
    u32 size = (u32) _r0;
711
0
    u64 source = slot (u32);
712
0
    u64 destination = slot (u32);
713
714
0
    if (M3_LIKELY(destination + size <= _mem->length))
715
0
    {
716
0
        if (M3_LIKELY(source + size <= _mem->length))
717
0
        {
718
0
            u8 * dst = m3MemData (_mem) + destination;
719
0
            u8 * src = m3MemData (_mem) + source;
720
0
            memmove (dst, src, size);
721
722
0
            nextOp ();
723
0
        }
724
0
        else d_outOfBoundsMemOp (source, size);
725
0
    }
726
0
    else d_outOfBoundsMemOp (destination, size);
727
0
}
728
729
730
d_m3Op  (MemFill)
731
0
{
732
0
    u32 size = (u32) _r0;
733
0
    u32 byte = slot (u32);
734
0
    u64 destination = slot (u32);
735
736
0
    if (M3_LIKELY(destination + size <= _mem->length))
737
0
    {
738
0
        u8 * mem8 = m3MemData (_mem) + destination;
739
0
        memset (mem8, (u8) byte, size);
740
0
        nextOp ();
741
0
    }
742
0
    else d_outOfBoundsMemOp (destination, size);
743
0
}
744
745
746
// it's a debate: should the compilation be trigger be the caller or callee page.
747
// it's a much easier to put it in the caller pager. if it's in the callee, either the entire page
748
// has be left dangling or it's just a stub that jumps to a newly acquired page.  In Gestalt, I opted
749
// for the stub approach. Stubbing makes it easier to dynamically free the compilation. You can also
750
// do both.
751
d_m3Op  (Compile)
752
0
{
753
0
    rewrite_op (op_Call);
754
755
0
    IM3Function function        = immediate (IM3Function);
756
757
0
    m3ret_t result = m3Err_none;
758
759
0
    if (M3_UNLIKELY(not function->compiled)) // check to see if function was compiled since this operation was emitted.
760
0
        result = CompileFunction (function);
761
762
0
    if (not result)
763
0
    {
764
        // patch up compiled pc and call rewritten op_Call
765
0
        * ((void**) --_pc) = (void*) (function->compiled);
766
0
        --_pc;
767
0
        nextOpDirect ();
768
0
    }
769
770
0
    newTrap (result);
771
0
}
772
773
774
775
d_m3Op  (Entry)
776
0
{
777
0
    d_m3ClearRegisters
778
779
    d_m3TracePrepare
780
781
0
    IM3Function function = immediate (IM3Function);
782
0
    IM3Memory memory = m3MemInfo (_mem);
783
784
#if d_m3SkipStackCheck
785
    if (true)
786
#else
787
0
    if (M3_LIKELY ((void *) (_sp + function->maxStackSlots) < _mem->maxStack))
788
0
#endif
789
0
    {
790
#if defined(DEBUG)
791
        function->hits++;
792
#endif
793
0
        u8 * stack = (u8 *) ((m3slot_t *) _sp + function->numRetAndArgSlots);
794
795
0
        memset (stack, 0x0, function->numLocalBytes);
796
0
        stack += function->numLocalBytes;
797
798
0
        if (function->constants)
799
0
        {
800
0
            memcpy (stack, function->constants, function->numConstantBytes);
801
0
        }
802
803
#if d_m3EnableStrace >= 2
804
        d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList (function, _sp + function->numRetSlots));
805
        trace_rt->callDepth++;
806
#endif
807
808
0
        m3ret_t r = nextOpImpl ();
809
810
#if d_m3EnableStrace >= 2
811
        trace_rt->callDepth--;
812
813
        if (r) {
814
            d_m3TracePrint("} !trap = %s", (char*)r);
815
        } else {
816
            int rettype = GetSingleRetType(function->funcType);
817
            if (rettype != c_m3Type_none) {
818
                char str [128] = { 0 };
819
                SPrintArg (str, 127, _sp, rettype);
820
                d_m3TracePrint("} = %s", str);
821
            } else {
822
                d_m3TracePrint("}");
823
            }
824
        }
825
#endif
826
827
0
        if (M3_UNLIKELY(r)) {
828
0
            _mem = memory->mallocated;
829
0
            fillBacktraceFrame ();
830
0
        }
831
0
        forwardTrap (r);
832
0
    }
833
0
    else newTrap (m3Err_trapStackOverflow);
834
0
}
835
836
837
d_m3Op  (Loop)
838
0
{
839
0
    d_m3TracePrepare
840
841
    // regs are unused coming into a loop anyway
842
    // this reduces code size & stack usage
843
0
    d_m3ClearRegisters
844
845
0
    m3ret_t r;
846
847
0
    IM3Memory memory = m3MemInfo (_mem);
848
849
0
    do
850
0
    {
851
#if d_m3EnableStrace >= 3
852
        d_m3TracePrint("iter {");
853
        trace_rt->callDepth++;
854
#endif
855
0
        r = nextOpImpl ();
856
857
#if d_m3EnableStrace >= 3
858
        trace_rt->callDepth--;
859
        d_m3TracePrint("}");
860
#endif
861
        // linear memory pointer needs refreshed here because the block it's looping over
862
        // can potentially invoke the grow operation.
863
0
        _mem = memory->mallocated;
864
0
    }
865
0
    while (r == _pc);
866
867
0
    forwardTrap (r);
868
0
}
869
870
871
d_m3Op  (Branch)
872
0
{
873
0
    jumpOp (* _pc);
874
0
}
875
876
877
d_m3Op  (If_r)
878
0
{
879
0
    i32 condition = (i32) _r0;
880
881
0
    pc_t elsePC = immediate (pc_t);
882
883
0
    if (condition)
884
0
        nextOp ();
885
0
    else
886
0
        jumpOp (elsePC);
887
0
}
888
889
890
d_m3Op  (If_s)
891
0
{
892
0
    i32 condition = slot (i32);
893
894
0
    pc_t elsePC = immediate (pc_t);
895
896
0
    if (condition)
897
0
        nextOp ();
898
0
    else
899
0
        jumpOp (elsePC);
900
0
}
901
902
903
d_m3Op  (BranchTable)
904
0
{
905
0
    u32 branchIndex = slot (u32);           // branch index is always in a slot
906
0
    u32 numTargets  = immediate (u32);
907
908
0
    pc_t * branches = (pc_t *) _pc;
909
910
0
    if (branchIndex > numTargets)
911
0
        branchIndex = numTargets; // the default index
912
913
0
    jumpOp (branches [branchIndex]);
914
0
}
915
916
917
#define d_m3SetRegisterSetSlot(TYPE, REG) \
918
0
d_m3Op  (SetRegister_##TYPE)            \
919
0
{                                       \
920
0
    REG = slot (TYPE);                  \
921
0
    nextOp ();                          \
922
0
}                                       \
Unexecuted instantiation: m3_compile.c:op_SetRegister_i32
Unexecuted instantiation: m3_compile.c:op_SetRegister_i64
Unexecuted instantiation: m3_compile.c:op_SetRegister_f32
Unexecuted instantiation: m3_compile.c:op_SetRegister_f64
923
                                        \
924
0
d_m3Op (SetSlot_##TYPE)                 \
925
0
{                                       \
926
0
    slot (TYPE) = (TYPE) REG;           \
927
0
    nextOp ();                          \
928
0
}                                       \
Unexecuted instantiation: m3_compile.c:op_SetSlot_i32
Unexecuted instantiation: m3_compile.c:op_SetSlot_i64
Unexecuted instantiation: m3_compile.c:op_SetSlot_f32
Unexecuted instantiation: m3_compile.c:op_SetSlot_f64
929
                                        \
930
0
d_m3Op (PreserveSetSlot_##TYPE)         \
931
0
{                                       \
932
0
    TYPE * stack     = slot_ptr (TYPE); \
933
0
    TYPE * preserve  = slot_ptr (TYPE); \
934
0
                                        \
935
0
    * preserve = * stack;               \
936
0
    * stack = (TYPE) REG;               \
937
0
                                        \
938
0
    nextOp ();                          \
939
0
}
Unexecuted instantiation: m3_compile.c:op_PreserveSetSlot_i32
Unexecuted instantiation: m3_compile.c:op_PreserveSetSlot_i64
Unexecuted instantiation: m3_compile.c:op_PreserveSetSlot_f32
Unexecuted instantiation: m3_compile.c:op_PreserveSetSlot_f64
940
941
d_m3SetRegisterSetSlot (i32, _r0)
942
d_m3SetRegisterSetSlot (i64, _r0)
943
#if d_m3HasFloat
944
d_m3SetRegisterSetSlot (f32, _fp0)
945
d_m3SetRegisterSetSlot (f64, _fp0)
946
#endif
947
948
d_m3Op (CopySlot_32)
949
0
{
950
0
    u32 * dst = slot_ptr (u32);
951
0
    u32 * src = slot_ptr (u32);
952
953
0
    * dst = * src;
954
955
0
    nextOp ();
956
0
}
957
958
959
d_m3Op (PreserveCopySlot_32)
960
0
{
961
0
    u32 * dest      = slot_ptr (u32);
962
0
    u32 * src       = slot_ptr (u32);
963
0
    u32 * preserve  = slot_ptr (u32);
964
965
0
    * preserve = * dest;
966
0
    * dest = * src;
967
968
0
    nextOp ();
969
0
}
970
971
972
d_m3Op (CopySlot_64)
973
0
{
974
0
    u64 * dst = slot_ptr (u64);
975
0
    u64 * src = slot_ptr (u64);
976
977
0
    * dst = * src;                  // printf ("copy: %p <- %" PRIi64 " <- %p\n", dst, * dst, src);
978
979
0
    nextOp ();
980
0
}
981
982
983
d_m3Op (PreserveCopySlot_64)
984
0
{
985
0
    u64 * dest      = slot_ptr (u64);
986
0
    u64 * src       = slot_ptr (u64);
987
0
    u64 * preserve  = slot_ptr (u64);
988
989
0
    * preserve = * dest;
990
0
    * dest = * src;
991
992
0
    nextOp ();
993
0
}
994
995
996
#if d_m3EnableOpTracing
997
//--------------------------------------------------------------------------------------------------------
998
d_m3Op  (DumpStack)
999
{
1000
    u32 opcodeIndex         = immediate (u32);
1001
    u32 stackHeight         = immediate (u32);
1002
    IM3Function function    = immediate (IM3Function);
1003
1004
    cstr_t funcName = (function) ? m3_GetFunctionName(function) : "";
1005
1006
    printf (" %4d ", opcodeIndex);
1007
    printf (" %-25s     r0: 0x%016" PRIx64 "  i:%" PRIi64 "  u:%" PRIu64 "\n", funcName, _r0, _r0, _r0);
1008
#if d_m3HasFloat
1009
    printf ("                                    fp0: %" PRIf64 "\n", _fp0);
1010
#endif
1011
    m3stack_t sp = _sp;
1012
1013
    for (u32 i = 0; i < stackHeight; ++i)
1014
    {
1015
        cstr_t kind = "";
1016
1017
        printf ("%p  %5s  %2d: 0x%" PRIx64 "  i:%" PRIi64 "\n", sp, kind, i, (u64) *(sp), (i64) *(sp));
1018
1019
        ++sp;
1020
    }
1021
    printf ("---------------------------------------------------------------------------------------------------------\n");
1022
1023
    nextOpDirect();
1024
}
1025
#endif
1026
1027
1028
#define d_m3Select_i(TYPE, REG)                 \
1029
0
d_m3Op  (Select_##TYPE##_rss)                   \
1030
0
{                                               \
1031
0
    i32 condition = (i32) _r0;                  \
1032
0
                                                \
1033
0
    TYPE operand2 = slot (TYPE);                \
1034
0
    TYPE operand1 = slot (TYPE);                \
1035
0
                                                \
1036
0
    REG = (condition) ? operand1 : operand2;    \
1037
0
                                                \
1038
0
    nextOp ();                                  \
1039
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_rss
Unexecuted instantiation: m3_compile.c:op_Select_i64_rss
1040
                                                \
1041
0
d_m3Op  (Select_##TYPE##_srs)                   \
1042
0
{                                               \
1043
0
    i32 condition = slot (i32);                 \
1044
0
                                                \
1045
0
    TYPE operand2 = (TYPE) REG;                 \
1046
0
    TYPE operand1 = slot (TYPE);                \
1047
0
                                                \
1048
0
    REG = (condition) ? operand1 : operand2;    \
1049
0
                                                \
1050
0
    nextOp ();                                  \
1051
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_srs
Unexecuted instantiation: m3_compile.c:op_Select_i64_srs
1052
                                                \
1053
0
d_m3Op  (Select_##TYPE##_ssr)                   \
1054
0
{                                               \
1055
0
    i32 condition = slot (i32);                 \
1056
0
                                                \
1057
0
    TYPE operand2 = slot (TYPE);                \
1058
0
    TYPE operand1 = (TYPE) REG;                 \
1059
0
                                                \
1060
0
    REG = (condition) ? operand1 : operand2;    \
1061
0
                                                \
1062
0
    nextOp ();                                  \
1063
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_ssr
Unexecuted instantiation: m3_compile.c:op_Select_i64_ssr
1064
                                                \
1065
0
d_m3Op  (Select_##TYPE##_sss)                   \
1066
0
{                                               \
1067
0
    i32 condition = slot (i32);                 \
1068
0
                                                \
1069
0
    TYPE operand2 = slot (TYPE);                \
1070
0
    TYPE operand1 = slot (TYPE);                \
1071
0
                                                \
1072
0
    REG = (condition) ? operand1 : operand2;    \
1073
0
                                                \
1074
0
    nextOp ();                                  \
1075
0
}
Unexecuted instantiation: m3_compile.c:op_Select_i32_sss
Unexecuted instantiation: m3_compile.c:op_Select_i64_sss
1076
1077
1078
d_m3Select_i (i32, _r0)
1079
d_m3Select_i (i64, _r0)
1080
1081
1082
#define d_m3Select_f(TYPE, REG, LABEL, SELECTOR)  \
1083
0
d_m3Op  (Select_##TYPE##_##LABEL##ss)           \
1084
0
{                                               \
1085
0
    i32 condition = (i32) SELECTOR;             \
1086
0
                                                \
1087
0
    TYPE operand2 = slot (TYPE);                \
1088
0
    TYPE operand1 = slot (TYPE);                \
1089
0
                                                \
1090
0
    REG = (condition) ? operand1 : operand2;    \
1091
0
                                                \
1092
0
    nextOp ();                                  \
1093
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_f32_sss
Unexecuted instantiation: m3_compile.c:op_Select_f32_rss
Unexecuted instantiation: m3_compile.c:op_Select_f64_sss
Unexecuted instantiation: m3_compile.c:op_Select_f64_rss
1094
                                                \
1095
0
d_m3Op  (Select_##TYPE##_##LABEL##rs)           \
1096
0
{                                               \
1097
0
    i32 condition = (i32) SELECTOR;             \
1098
0
                                                \
1099
0
    TYPE operand2 = (TYPE) REG;                 \
1100
0
    TYPE operand1 = slot (TYPE);                \
1101
0
                                                \
1102
0
    REG = (condition) ? operand1 : operand2;    \
1103
0
                                                \
1104
0
    nextOp ();                                  \
1105
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_f32_srs
Unexecuted instantiation: m3_compile.c:op_Select_f32_rrs
Unexecuted instantiation: m3_compile.c:op_Select_f64_srs
Unexecuted instantiation: m3_compile.c:op_Select_f64_rrs
1106
                                                \
1107
0
d_m3Op  (Select_##TYPE##_##LABEL##sr)           \
1108
0
{                                               \
1109
0
    i32 condition = (i32) SELECTOR;             \
1110
0
                                                \
1111
0
    TYPE operand2 = slot (TYPE);                \
1112
0
    TYPE operand1 = (TYPE) REG;                 \
1113
0
                                                \
1114
0
    REG = (condition) ? operand1 : operand2;    \
1115
0
                                                \
1116
0
    nextOp ();                                  \
1117
0
}
Unexecuted instantiation: m3_compile.c:op_Select_f32_ssr
Unexecuted instantiation: m3_compile.c:op_Select_f32_rsr
Unexecuted instantiation: m3_compile.c:op_Select_f64_ssr
Unexecuted instantiation: m3_compile.c:op_Select_f64_rsr
1118
1119
#if d_m3HasFloat
1120
d_m3Select_f (f32, _fp0, r, _r0)
1121
d_m3Select_f (f32, _fp0, s, slot (i32))
1122
1123
d_m3Select_f (f64, _fp0, r, _r0)
1124
d_m3Select_f (f64, _fp0, s, slot (i32))
1125
#endif
1126
1127
d_m3Op  (Return)
1128
2.03k
{
1129
2.03k
    m3StackCheck();
1130
2.03k
    return m3Err_none;
1131
2.03k
}
1132
1133
1134
d_m3Op  (BranchIf_r)
1135
0
{
1136
0
    i32 condition   = (i32) _r0;
1137
0
    pc_t branch     = immediate (pc_t);
1138
1139
0
    if (condition)
1140
0
    {
1141
0
        jumpOp (branch);
1142
0
    }
1143
0
    else nextOp ();
1144
0
}
1145
1146
1147
d_m3Op  (BranchIf_s)
1148
0
{
1149
0
    i32 condition   = slot (i32);
1150
0
    pc_t branch     = immediate (pc_t);
1151
1152
0
    if (condition)
1153
0
    {
1154
0
        jumpOp (branch);
1155
0
    }
1156
0
    else nextOp ();
1157
0
}
1158
1159
1160
d_m3Op  (BranchIfPrologue_r)
1161
0
{
1162
0
    i32 condition   = (i32) _r0;
1163
0
    pc_t branch     = immediate (pc_t);
1164
1165
0
    if (condition)
1166
0
    {
1167
        // this is the "prologue" that ends with
1168
        // a plain branch to the actual target
1169
0
        nextOp ();
1170
0
    }
1171
0
    else jumpOp (branch); // jump over the prologue
1172
0
}
1173
1174
1175
d_m3Op  (BranchIfPrologue_s)
1176
0
{
1177
0
    i32 condition   = slot (i32);
1178
0
    pc_t branch     = immediate (pc_t);
1179
1180
0
    if (condition)
1181
0
    {
1182
0
        nextOp ();
1183
0
    }
1184
0
    else jumpOp (branch);
1185
0
}
1186
1187
1188
d_m3Op  (ContinueLoop)
1189
0
{
1190
0
    m3StackCheck();
1191
1192
    // TODO: this is where execution can "escape" the M3 code and callback to the client / fiber switch
1193
    // OR it can go in the Loop operation. I think it's best to do here. adding code to the loop operation
1194
    // has the potential to increase its native-stack usage. (don't forget ContinueLoopIf too.)
1195
1196
0
    void * loopId = immediate (void *);
1197
0
    return loopId;
1198
0
}
1199
1200
1201
d_m3Op  (ContinueLoopIf)
1202
0
{
1203
0
    i32 condition = (i32) _r0;
1204
0
    void * loopId = immediate (void *);
1205
1206
0
    if (condition)
1207
0
    {
1208
0
        return loopId;
1209
0
    }
1210
0
    else nextOp ();
1211
0
}
1212
1213
1214
d_m3Op  (Const32)
1215
1.14k
{
1216
1.14k
    u32 value = * (u32 *)_pc++;
1217
1.14k
    slot (u32) = value;
1218
1.14k
    nextOp ();
1219
1.14k
}
1220
1221
1222
d_m3Op  (Const64)
1223
1.41k
{
1224
1.41k
    u64 value = * (u64 *)_pc;
1225
1.41k
    _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1;
1226
1.41k
    slot (u64) = value;
1227
1.41k
    nextOp ();
1228
1.41k
}
1229
1230
d_m3Op  (Unsupported)
1231
0
{
1232
0
    newTrap ("unsupported instruction executed");
1233
0
}
1234
1235
d_m3Op  (Unreachable)
1236
0
{
1237
0
    m3StackCheck();
1238
0
    newTrap (m3Err_trapUnreachable);
1239
0
}
1240
1241
1242
d_m3Op  (End)
1243
0
{
1244
0
    m3StackCheck();
1245
0
    return m3Err_none;
1246
0
}
1247
1248
1249
d_m3Op  (SetGlobal_s32)
1250
0
{
1251
0
    u32 * global = immediate (u32 *);
1252
0
    * global = slot (u32);
1253
1254
0
    nextOp ();
1255
0
}
1256
1257
1258
d_m3Op  (SetGlobal_s64)
1259
0
{
1260
0
    u64 * global = immediate (u64 *);
1261
0
    * global = slot (u64);
1262
1263
0
    nextOp ();
1264
0
}
1265
1266
#if d_m3HasFloat
1267
d_m3Op  (SetGlobal_f32)
1268
0
{
1269
0
    f32 * global = immediate (f32 *);
1270
0
    * global = _fp0;
1271
1272
0
    nextOp ();
1273
0
}
1274
1275
1276
d_m3Op  (SetGlobal_f64)
1277
0
{
1278
0
    f64 * global = immediate (f64 *);
1279
0
    * global = _fp0;
1280
1281
0
    nextOp ();
1282
0
}
1283
#endif
1284
1285
1286
#if d_m3SkipMemoryBoundsCheck
1287
#  define m3MemCheck(x) true
1288
#else
1289
0
#  define m3MemCheck(x) M3_LIKELY(x)
1290
#endif
1291
1292
// memcpy here is to support non-aligned access on some platforms.
1293
1294
#define d_m3Load(REG,DEST_TYPE,SRC_TYPE)                \
1295
0
d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r)                 \
1296
0
{                                                       \
1297
0
    d_m3TracePrepare                                    \
1298
0
    u32 offset = immediate (u32);                       \
1299
0
    u64 operand = (u32) _r0;                            \
1300
0
    operand += offset;                                  \
1301
0
                                                        \
1302
0
    if (m3MemCheck(                                     \
1303
0
        operand + sizeof (SRC_TYPE) <= _mem->length     \
1304
0
    )) {                                                \
1305
0
        {                                               \
1306
0
            u8* src8 = m3MemData(_mem) + operand;       \
1307
0
            SRC_TYPE value;                             \
1308
0
            memcpy(&value, src8, sizeof(value));        \
1309
0
            M3_BSWAP_##SRC_TYPE(value);                 \
1310
0
            REG = (DEST_TYPE)value;                     \
1311
0
            d_m3TraceLoad(DEST_TYPE, operand, REG);     \
1312
0
        }                                               \
1313
0
        nextOp ();                                      \
1314
0
    } else d_outOfBounds;                               \
1315
0
}                                                       \
Unexecuted instantiation: m3_compile.c:op_i32_Load_i32_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_i64_r
Unexecuted instantiation: m3_compile.c:op_f32_Load_f32_r
Unexecuted instantiation: m3_compile.c:op_f64_Load_f64_r
Unexecuted instantiation: m3_compile.c:op_i32_Load_i8_r
Unexecuted instantiation: m3_compile.c:op_i32_Load_u8_r
Unexecuted instantiation: m3_compile.c:op_i32_Load_i16_r
Unexecuted instantiation: m3_compile.c:op_i32_Load_u16_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_i8_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_u8_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_i16_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_u16_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_i32_r
Unexecuted instantiation: m3_compile.c:op_i64_Load_u32_r
1316
0
d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s)                 \
1317
0
{                                                       \
1318
0
    d_m3TracePrepare                                    \
1319
0
    u64 operand = slot (u32);                           \
1320
0
    u32 offset = immediate (u32);                       \
1321
0
    operand += offset;                                  \
1322
0
                                                        \
1323
0
    if (m3MemCheck(                                     \
1324
0
        operand + sizeof (SRC_TYPE) <= _mem->length     \
1325
0
    )) {                                                \
1326
0
        {                                               \
1327
0
            u8* src8 = m3MemData(_mem) + operand;       \
1328
0
            SRC_TYPE value;                             \
1329
0
            memcpy(&value, src8, sizeof(value));        \
1330
0
            M3_BSWAP_##SRC_TYPE(value);                 \
1331
0
            REG = (DEST_TYPE)value;                     \
1332
0
            d_m3TraceLoad(DEST_TYPE, operand, REG);     \
1333
0
        }                                               \
1334
0
        nextOp ();                                      \
1335
0
    } else d_outOfBounds;                               \
1336
0
}
Unexecuted instantiation: m3_compile.c:op_i32_Load_i32_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_i64_s
Unexecuted instantiation: m3_compile.c:op_f32_Load_f32_s
Unexecuted instantiation: m3_compile.c:op_f64_Load_f64_s
Unexecuted instantiation: m3_compile.c:op_i32_Load_i8_s
Unexecuted instantiation: m3_compile.c:op_i32_Load_u8_s
Unexecuted instantiation: m3_compile.c:op_i32_Load_i16_s
Unexecuted instantiation: m3_compile.c:op_i32_Load_u16_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_i8_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_u8_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_i16_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_u16_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_i32_s
Unexecuted instantiation: m3_compile.c:op_i64_Load_u32_s
1337
1338
//  printf ("get: %d -> %d\n", operand + offset, (i64) REG);
1339
1340
1341
#define d_m3Load_i(DEST_TYPE, SRC_TYPE) d_m3Load(_r0, DEST_TYPE, SRC_TYPE)
1342
#define d_m3Load_f(DEST_TYPE, SRC_TYPE) d_m3Load(_fp0, DEST_TYPE, SRC_TYPE)
1343
1344
#if d_m3HasFloat
1345
d_m3Load_f (f32, f32);
1346
d_m3Load_f (f64, f64);
1347
#endif
1348
1349
d_m3Load_i (i32, i8);
1350
d_m3Load_i (i32, u8);
1351
d_m3Load_i (i32, i16);
1352
d_m3Load_i (i32, u16);
1353
d_m3Load_i (i32, i32);
1354
1355
d_m3Load_i (i64, i8);
1356
d_m3Load_i (i64, u8);
1357
d_m3Load_i (i64, i16);
1358
d_m3Load_i (i64, u16);
1359
d_m3Load_i (i64, i32);
1360
d_m3Load_i (i64, u32);
1361
d_m3Load_i (i64, i64);
1362
1363
#define d_m3Store(REG, SRC_TYPE, DEST_TYPE)             \
1364
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_rs)             \
1365
0
{                                                       \
1366
0
    d_m3TracePrepare                                    \
1367
0
    u64 operand = slot (u32);                           \
1368
0
    u32 offset = immediate (u32);                       \
1369
0
    operand += offset;                                  \
1370
0
                                                        \
1371
0
    if (m3MemCheck(                                     \
1372
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1373
0
    )) {                                                \
1374
0
        {                                               \
1375
0
            d_m3TraceStore(SRC_TYPE, operand, REG);     \
1376
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1377
0
            DEST_TYPE val = (DEST_TYPE) REG;            \
1378
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1379
0
            memcpy(mem8, &val, sizeof(val));            \
1380
0
        }                                               \
1381
0
        nextOp ();                                      \
1382
0
    } else d_outOfBounds;                               \
1383
0
}                                                       \
Unexecuted instantiation: m3_compile.c:op_i32_Store_i32_rs
Unexecuted instantiation: m3_compile.c:op_i64_Store_i64_rs
Unexecuted instantiation: m3_compile.c:op_f32_Store_f32_rs
Unexecuted instantiation: m3_compile.c:op_f64_Store_f64_rs
Unexecuted instantiation: m3_compile.c:op_i32_Store_u8_rs
Unexecuted instantiation: m3_compile.c:op_i32_Store_i16_rs
Unexecuted instantiation: m3_compile.c:op_i64_Store_u8_rs
Unexecuted instantiation: m3_compile.c:op_i64_Store_i16_rs
Unexecuted instantiation: m3_compile.c:op_i64_Store_i32_rs
1384
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_sr)             \
1385
0
{                                                       \
1386
0
    d_m3TracePrepare                                    \
1387
0
    const SRC_TYPE value = slot (SRC_TYPE);             \
1388
0
    u64 operand = (u32) _r0;                            \
1389
0
    u32 offset = immediate (u32);                       \
1390
0
    operand += offset;                                  \
1391
0
                                                        \
1392
0
    if (m3MemCheck(                                     \
1393
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1394
0
    )) {                                                \
1395
0
        {                                               \
1396
0
            d_m3TraceStore(SRC_TYPE, operand, value);   \
1397
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1398
0
            DEST_TYPE val = (DEST_TYPE) value;          \
1399
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1400
0
            memcpy(mem8, &val, sizeof(val));            \
1401
0
        }                                               \
1402
0
        nextOp ();                                      \
1403
0
    } else d_outOfBounds;                               \
1404
0
}                                                       \
Unexecuted instantiation: m3_compile.c:op_i32_Store_i32_sr
Unexecuted instantiation: m3_compile.c:op_i64_Store_i64_sr
Unexecuted instantiation: m3_compile.c:op_f32_Store_f32_sr
Unexecuted instantiation: m3_compile.c:op_f64_Store_f64_sr
Unexecuted instantiation: m3_compile.c:op_i32_Store_u8_sr
Unexecuted instantiation: m3_compile.c:op_i32_Store_i16_sr
Unexecuted instantiation: m3_compile.c:op_i64_Store_u8_sr
Unexecuted instantiation: m3_compile.c:op_i64_Store_i16_sr
Unexecuted instantiation: m3_compile.c:op_i64_Store_i32_sr
1405
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_ss)             \
1406
0
{                                                       \
1407
0
    d_m3TracePrepare                                    \
1408
0
    const SRC_TYPE value = slot (SRC_TYPE);             \
1409
0
    u64 operand = slot (u32);                           \
1410
0
    u32 offset = immediate (u32);                       \
1411
0
    operand += offset;                                  \
1412
0
                                                        \
1413
0
    if (m3MemCheck(                                     \
1414
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1415
0
    )) {                                                \
1416
0
        {                                               \
1417
0
            d_m3TraceStore(SRC_TYPE, operand, value);   \
1418
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1419
0
            DEST_TYPE val = (DEST_TYPE) value;          \
1420
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1421
0
            memcpy(mem8, &val, sizeof(val));            \
1422
0
        }                                               \
1423
0
        nextOp ();                                      \
1424
0
    } else d_outOfBounds;                               \
1425
0
}
Unexecuted instantiation: m3_compile.c:op_i32_Store_i32_ss
Unexecuted instantiation: m3_compile.c:op_i64_Store_i64_ss
Unexecuted instantiation: m3_compile.c:op_f32_Store_f32_ss
Unexecuted instantiation: m3_compile.c:op_f64_Store_f64_ss
Unexecuted instantiation: m3_compile.c:op_i32_Store_u8_ss
Unexecuted instantiation: m3_compile.c:op_i32_Store_i16_ss
Unexecuted instantiation: m3_compile.c:op_i64_Store_u8_ss
Unexecuted instantiation: m3_compile.c:op_i64_Store_i16_ss
Unexecuted instantiation: m3_compile.c:op_i64_Store_i32_ss
1426
1427
// both operands can be in regs when storing a float
1428
#define d_m3StoreFp(REG, TYPE)                          \
1429
0
d_m3Op  (TYPE##_Store_##TYPE##_rr)                      \
1430
0
{                                                       \
1431
0
    d_m3TracePrepare                                    \
1432
0
    u64 operand = (u32) _r0;                            \
1433
0
    u32 offset = immediate (u32);                       \
1434
0
    operand += offset;                                  \
1435
0
                                                        \
1436
0
    if (m3MemCheck(                                     \
1437
0
        operand + sizeof (TYPE) <= _mem->length         \
1438
0
    )) {                                                \
1439
0
        {                                               \
1440
0
            d_m3TraceStore(TYPE, operand, REG);         \
1441
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1442
0
            TYPE val = (TYPE) REG;                      \
1443
0
            M3_BSWAP_##TYPE(val);                       \
1444
0
            memcpy(mem8, &val, sizeof(val));            \
1445
0
        }                                               \
1446
0
        nextOp ();                                      \
1447
0
    } else d_outOfBounds;                               \
1448
0
}
Unexecuted instantiation: m3_compile.c:op_f32_Store_f32_rr
Unexecuted instantiation: m3_compile.c:op_f64_Store_f64_rr
1449
1450
1451
#define d_m3Store_i(SRC_TYPE, DEST_TYPE) d_m3Store(_r0, SRC_TYPE, DEST_TYPE)
1452
#define d_m3Store_f(SRC_TYPE, DEST_TYPE) d_m3Store(_fp0, SRC_TYPE, DEST_TYPE) d_m3StoreFp (_fp0, SRC_TYPE);
1453
1454
#if d_m3HasFloat
1455
d_m3Store_f (f32, f32)
1456
d_m3Store_f (f64, f64)
1457
#endif
1458
1459
d_m3Store_i (i32, u8)
1460
d_m3Store_i (i32, i16)
1461
d_m3Store_i (i32, i32)
1462
1463
d_m3Store_i (i64, u8)
1464
d_m3Store_i (i64, i16)
1465
d_m3Store_i (i64, i32)
1466
d_m3Store_i (i64, i64)
1467
1468
#undef m3MemCheck
1469
1470
1471
//---------------------------------------------------------------------------------------------------------------------
1472
// debug/profiling
1473
//---------------------------------------------------------------------------------------------------------------------
1474
#if d_m3EnableOpTracing
1475
d_m3RetSig  debugOp  (d_m3OpSig, cstr_t i_opcode)
1476
{
1477
    char name [100];
1478
    strcpy (name, strstr (i_opcode, "op_") + 3);
1479
    char * bracket = strstr (name, "(");
1480
    if (bracket) {
1481
        *bracket  = 0;
1482
    }
1483
1484
    puts (name);
1485
    nextOpDirect();
1486
}
1487
# endif
1488
1489
# if d_m3EnableOpProfiling
1490
d_m3RetSig  profileOp  (d_m3OpSig, cstr_t i_operationName)
1491
{
1492
    ProfileHit (i_operationName);
1493
1494
    nextOpDirect();
1495
}
1496
# endif
1497
1498
d_m3EndExternC
1499
1500
#endif // m3_exec_h