Coverage Report

Created: 2025-07-11 06:27

/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
2.07k
# define immediate(TYPE)            * ((TYPE *) _pc++)
42
# define skip_immediate(TYPE)       (_pc++)
43
44
1.31k
# 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
1.31k
#   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
# if (d_m3EnableOpProfiling || d_m3EnableOpTracing)
112
d_m3RetSig  Call  (d_m3OpSig, cstr_t i_operationName)
113
# else
114
d_m3RetSig  Call  (d_m3OpSig)
115
# endif
116
0
{
117
0
    m3ret_t possible_trap = m3_Yield ();
118
0
    if (M3_UNLIKELY(possible_trap)) return possible_trap;
119
120
0
    nextOpDirect();
121
0
}
122
123
// TODO: OK, this needs some explanation here ;0
124
125
#define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \
126
0
d_m3Op(TYPE##_##NAME##_rs)                              \
127
0
{                                                       \
128
0
    TYPE operand = slot (TYPE);                         \
129
0
    OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__);    \
130
0
    nextOp ();                                          \
131
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
132
0
d_m3Op(TYPE##_##NAME##_ss)                              \
133
0
{                                                       \
134
0
    TYPE operand2 = slot (TYPE);                        \
135
0
    TYPE operand1 = slot (TYPE);                        \
136
0
    OP((RES), operand1, operand2, ##__VA_ARGS__);       \
137
0
    nextOp ();                                          \
138
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
139
140
#define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...)      \
141
0
d_m3Op(TYPE##_##NAME##_sr)                              \
142
0
{                                                       \
143
0
    TYPE operand = slot (TYPE);                         \
144
0
    OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__);    \
145
0
    nextOp ();                                          \
146
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
147
d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__)
148
149
// Accept macros
150
#define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...)    d_m3CommutativeOpMacro  ( _r0,  _r0, TYPE, NAME, MACRO, ##__VA_ARGS__)
151
#define d_m3OpMacro_i(TYPE, NAME, MACRO, ...)               d_m3OpMacro             ( _r0,  _r0, TYPE, NAME, MACRO, ##__VA_ARGS__)
152
#define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...)    d_m3CommutativeOpMacro  (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__)
153
#define d_m3OpMacro_f(TYPE, NAME, MACRO, ...)               d_m3OpMacro             (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__)
154
155
0
#define M3_FUNC(RES, A, B, OP)  (RES) = OP((A), (B))        // Accept functions: res = OP(a,b)
156
0
#define M3_OPER(RES, A, B, OP)  (RES) = ((A) OP (B))        // Accept operators: res = a OP b
157
158
0
#define d_m3CommutativeOpFunc_i(TYPE, NAME, OP)     d_m3CommutativeOpMacro_i    (TYPE, NAME, M3_FUNC, OP)
159
0
#define d_m3OpFunc_i(TYPE, NAME, OP)                d_m3OpMacro_i               (TYPE, NAME, M3_FUNC, OP)
160
#define d_m3CommutativeOpFunc_f(TYPE, NAME, OP)     d_m3CommutativeOpMacro_f    (TYPE, NAME, M3_FUNC, OP)
161
0
#define d_m3OpFunc_f(TYPE, NAME, OP)                d_m3OpMacro_f               (TYPE, NAME, M3_FUNC, OP)
162
163
0
#define d_m3CommutativeOp_i(TYPE, NAME, OP)         d_m3CommutativeOpMacro_i    (TYPE, NAME, M3_OPER, OP)
164
0
#define d_m3Op_i(TYPE, NAME, OP)                    d_m3OpMacro_i               (TYPE, NAME, M3_OPER, OP)
165
0
#define d_m3CommutativeOp_f(TYPE, NAME, OP)         d_m3CommutativeOpMacro_f    (TYPE, NAME, M3_OPER, OP)
166
0
#define d_m3Op_f(TYPE, NAME, OP)                    d_m3OpMacro_f               (TYPE, NAME, M3_OPER, OP)
167
168
// compare needs to be distinct for fp 'cause the result must be _r0
169
0
#define d_m3CompareOp_f(TYPE, NAME, OP)             d_m3OpMacro                 (_r0, _fp0, TYPE, NAME, M3_OPER, OP)
170
0
#define d_m3CommutativeCmpOp_f(TYPE, NAME, OP)      d_m3CommutativeOpMacro      (_r0, _fp0, TYPE, NAME, M3_OPER, OP)
171
172
173
//-----------------------
174
175
// signed
176
d_m3CommutativeOp_i (i32, Equal,            ==)     d_m3CommutativeOp_i (i64, Equal,            ==)
177
d_m3CommutativeOp_i (i32, NotEqual,         !=)     d_m3CommutativeOp_i (i64, NotEqual,         !=)
178
179
d_m3Op_i (i32, LessThan,                    < )     d_m3Op_i (i64, LessThan,                    < )
180
d_m3Op_i (i32, GreaterThan,                 > )     d_m3Op_i (i64, GreaterThan,                 > )
181
d_m3Op_i (i32, LessThanOrEqual,             <=)     d_m3Op_i (i64, LessThanOrEqual,             <=)
182
d_m3Op_i (i32, GreaterThanOrEqual,          >=)     d_m3Op_i (i64, GreaterThanOrEqual,          >=)
183
184
// unsigned
185
d_m3Op_i (u32, LessThan,                    < )     d_m3Op_i (u64, LessThan,                    < )
186
d_m3Op_i (u32, GreaterThan,                 > )     d_m3Op_i (u64, GreaterThan,                 > )
187
d_m3Op_i (u32, LessThanOrEqual,             <=)     d_m3Op_i (u64, LessThanOrEqual,             <=)
188
d_m3Op_i (u32, GreaterThanOrEqual,          >=)     d_m3Op_i (u64, GreaterThanOrEqual,          >=)
189
190
#if d_m3HasFloat
191
d_m3CommutativeCmpOp_f (f32, Equal,         ==)     d_m3CommutativeCmpOp_f (f64, Equal,         ==)
192
d_m3CommutativeCmpOp_f (f32, NotEqual,      !=)     d_m3CommutativeCmpOp_f (f64, NotEqual,      !=)
193
d_m3CompareOp_f (f32, LessThan,             < )     d_m3CompareOp_f (f64, LessThan,             < )
194
d_m3CompareOp_f (f32, GreaterThan,          > )     d_m3CompareOp_f (f64, GreaterThan,          > )
195
d_m3CompareOp_f (f32, LessThanOrEqual,      <=)     d_m3CompareOp_f (f64, LessThanOrEqual,      <=)
196
d_m3CompareOp_f (f32, GreaterThanOrEqual,   >=)     d_m3CompareOp_f (f64, GreaterThanOrEqual,   >=)
197
#endif
198
199
0
#define OP_ADD_32(A,B) (i32)((u32)(A) + (u32)(B))
200
0
#define OP_ADD_64(A,B) (i64)((u64)(A) + (u64)(B))
201
0
#define OP_SUB_32(A,B) (i32)((u32)(A) - (u32)(B))
202
0
#define OP_SUB_64(A,B) (i64)((u64)(A) - (u64)(B))
203
0
#define OP_MUL_32(A,B) (i32)((u32)(A) * (u32)(B))
204
0
#define OP_MUL_64(A,B) (i64)((u64)(A) * (u64)(B))
205
206
0
d_m3CommutativeOpFunc_i (i32, Add,      OP_ADD_32)  d_m3CommutativeOpFunc_i (i64, Add,      OP_ADD_64)
207
0
d_m3CommutativeOpFunc_i (i32, Multiply, OP_MUL_32)  d_m3CommutativeOpFunc_i (i64, Multiply, OP_MUL_64)
208
209
0
d_m3OpFunc_i (i32, Subtract,            OP_SUB_32)  d_m3OpFunc_i (i64, Subtract,            OP_SUB_64)
210
211
0
#define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32))
212
0
#define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64))
213
0
#define OP_SHR_32(X,N) ((X) >> ((u32)(N) % 32))
214
0
#define OP_SHR_64(X,N) ((X) >> ((u64)(N) % 64))
215
216
0
d_m3OpFunc_i (u32, ShiftLeft,       OP_SHL_32)      d_m3OpFunc_i (u64, ShiftLeft,       OP_SHL_64)
217
0
d_m3OpFunc_i (i32, ShiftRight,      OP_SHR_32)      d_m3OpFunc_i (i64, ShiftRight,      OP_SHR_64)
218
0
d_m3OpFunc_i (u32, ShiftRight,      OP_SHR_32)      d_m3OpFunc_i (u64, ShiftRight,      OP_SHR_64)
219
220
d_m3CommutativeOp_i (u32, And,              &)
221
d_m3CommutativeOp_i (u32, Or,               |)
222
d_m3CommutativeOp_i (u32, Xor,              ^)
223
224
d_m3CommutativeOp_i (u64, And,              &)
225
d_m3CommutativeOp_i (u64, Or,               |)
226
d_m3CommutativeOp_i (u64, Xor,              ^)
227
228
#if d_m3HasFloat
229
d_m3CommutativeOp_f (f32, Add,              +)      d_m3CommutativeOp_f (f64, Add,              +)
230
d_m3CommutativeOp_f (f32, Multiply,         *)      d_m3CommutativeOp_f (f64, Multiply,         *)
231
d_m3Op_f (f32, Subtract,                    -)      d_m3Op_f (f64, Subtract,                    -)
232
d_m3Op_f (f32, Divide,                      /)      d_m3Op_f (f64, Divide,                      /)
233
#endif
234
235
d_m3OpFunc_i(u32, Rotl, rotl32)
236
d_m3OpFunc_i(u32, Rotr, rotr32)
237
d_m3OpFunc_i(u64, Rotl, rotl64)
238
d_m3OpFunc_i(u64, Rotr, rotr64)
239
240
0
d_m3OpMacro_i(u32, Divide, OP_DIV_U);
241
0
d_m3OpMacro_i(i32, Divide, OP_DIV_S, INT32_MIN);
242
0
d_m3OpMacro_i(u64, Divide, OP_DIV_U);
243
0
d_m3OpMacro_i(i64, Divide, OP_DIV_S, INT64_MIN);
244
245
0
d_m3OpMacro_i(u32, Remainder, OP_REM_U);
246
0
d_m3OpMacro_i(i32, Remainder, OP_REM_S, INT32_MIN);
247
0
d_m3OpMacro_i(u64, Remainder, OP_REM_U);
248
0
d_m3OpMacro_i(i64, Remainder, OP_REM_S, INT64_MIN);
249
250
#if d_m3HasFloat
251
d_m3OpFunc_f(f32, Min, min_f32);
252
d_m3OpFunc_f(f32, Max, max_f32);
253
d_m3OpFunc_f(f64, Min, min_f64);
254
d_m3OpFunc_f(f64, Max, max_f64);
255
256
d_m3OpFunc_f(f32, CopySign, copysignf);
257
d_m3OpFunc_f(f64, CopySign, copysign);
258
#endif
259
260
// Unary operations
261
// Note: This macro follows the principle of d_m3OpMacro
262
263
#define d_m3UnaryMacro(RES, REG, TYPE, NAME, OP, ...)   \
264
0
d_m3Op(TYPE##_##NAME##_r)                           \
265
0
{                                                   \
266
0
    OP((RES), (TYPE) REG, ##__VA_ARGS__);           \
267
0
    nextOp ();                                      \
268
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
269
0
d_m3Op(TYPE##_##NAME##_s)                           \
270
0
{                                                   \
271
0
    TYPE operand = slot (TYPE);                     \
272
0
    OP((RES), operand, ##__VA_ARGS__);              \
273
0
    nextOp ();                                      \
274
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
275
276
0
#define M3_UNARY(RES, X, OP) (RES) = OP(X)
277
0
#define d_m3UnaryOp_i(TYPE, NAME, OPERATION)        d_m3UnaryMacro( _r0,  _r0, TYPE, NAME, M3_UNARY, OPERATION)
278
0
#define d_m3UnaryOp_f(TYPE, NAME, OPERATION)        d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY, OPERATION)
279
280
#if d_m3HasFloat
281
d_m3UnaryOp_f (f32, Abs,        fabsf);         d_m3UnaryOp_f (f64, Abs,        fabs);
282
d_m3UnaryOp_f (f32, Ceil,       ceilf);         d_m3UnaryOp_f (f64, Ceil,       ceil);
283
d_m3UnaryOp_f (f32, Floor,      floorf);        d_m3UnaryOp_f (f64, Floor,      floor);
284
d_m3UnaryOp_f (f32, Trunc,      truncf);        d_m3UnaryOp_f (f64, Trunc,      trunc);
285
d_m3UnaryOp_f (f32, Sqrt,       sqrtf);         d_m3UnaryOp_f (f64, Sqrt,       sqrt);
286
d_m3UnaryOp_f (f32, Nearest,    rintf);         d_m3UnaryOp_f (f64, Nearest,    rint);
287
d_m3UnaryOp_f (f32, Negate,     -);             d_m3UnaryOp_f (f64, Negate,     -);
288
#endif
289
290
0
#define OP_EQZ(x) ((x) == 0)
291
292
0
d_m3UnaryOp_i (i32, EqualToZero, OP_EQZ)
293
0
d_m3UnaryOp_i (i64, EqualToZero, OP_EQZ)
294
295
// clz(0), ctz(0) results are undefined for rest platforms, fix it
296
#if (defined(__i386__) || defined(__x86_64__)) && !(defined(__AVX2__) || (defined(__ABM__) && defined(__BMI__)))
297
    #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x))
298
    #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x))
299
    // for 64-bit instructions branchless approach more preferable
300
    #define OP_CLZ_64(x) (__builtin_clzll((x) | (1LL <<  0)) + OP_EQZ(x))
301
    #define OP_CTZ_64(x) (__builtin_ctzll((x) | (1LL << 63)) + OP_EQZ(x))
302
#elif defined(__ppc__) || defined(__ppc64__)
303
// PowerPC is defined for __builtin_clz(0) and __builtin_ctz(0).
304
// See (https://github.com/aquynh/capstone/blob/master/MathExtras.h#L99)
305
    #define OP_CLZ_32(x) __builtin_clz(x)
306
    #define OP_CTZ_32(x) __builtin_ctz(x)
307
    #define OP_CLZ_64(x) __builtin_clzll(x)
308
    #define OP_CTZ_64(x) __builtin_ctzll(x)
309
#else
310
0
    #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x))
311
0
    #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x))
312
0
    #define OP_CLZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_clzll(x))
313
0
    #define OP_CTZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_ctzll(x))
314
#endif
315
316
0
d_m3UnaryOp_i (u32, Clz, OP_CLZ_32)
317
0
d_m3UnaryOp_i (u64, Clz, OP_CLZ_64)
318
319
0
d_m3UnaryOp_i (u32, Ctz, OP_CTZ_32)
320
0
d_m3UnaryOp_i (u64, Ctz, OP_CTZ_64)
321
322
d_m3UnaryOp_i (u32, Popcnt, __builtin_popcount)
323
d_m3UnaryOp_i (u64, Popcnt, __builtin_popcountll)
324
325
0
#define OP_WRAP_I64(X) ((X) & 0x00000000ffffffff)
326
327
d_m3Op(i32_Wrap_i64_r)
328
0
{
329
0
    _r0 = OP_WRAP_I64((i64) _r0);
330
0
    nextOp ();
331
0
}
332
333
d_m3Op(i32_Wrap_i64_s)
334
0
{
335
0
    i64 operand = slot (i64);
336
0
    _r0 = OP_WRAP_I64(operand);
337
0
    nextOp ();
338
0
}
339
340
// Integer sign extension operations
341
0
#define OP_EXTEND8_S_I32(X)  ((int32_t)(int8_t)(X))
342
0
#define OP_EXTEND16_S_I32(X) ((int32_t)(int16_t)(X))
343
0
#define OP_EXTEND8_S_I64(X)  ((int64_t)(int8_t)(X))
344
0
#define OP_EXTEND16_S_I64(X) ((int64_t)(int16_t)(X))
345
0
#define OP_EXTEND32_S_I64(X) ((int64_t)(int32_t)(X))
346
347
0
d_m3UnaryOp_i (i32, Extend8_s,  OP_EXTEND8_S_I32)
348
0
d_m3UnaryOp_i (i32, Extend16_s, OP_EXTEND16_S_I32)
349
0
d_m3UnaryOp_i (i64, Extend8_s,  OP_EXTEND8_S_I64)
350
0
d_m3UnaryOp_i (i64, Extend16_s, OP_EXTEND16_S_I64)
351
0
d_m3UnaryOp_i (i64, Extend32_s, OP_EXTEND32_S_I64)
352
353
#define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...)   \
354
0
d_m3Op(TYPE##_##NAME##_##FROM##_r_r)                \
355
0
{                                                   \
356
0
    OP((DEST), (FROM) SRC, ##__VA_ARGS__);          \
357
0
    nextOp ();                                      \
358
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
359
0
d_m3Op(TYPE##_##NAME##_##FROM##_r_s)                \
360
0
{                                                   \
361
0
    FROM * stack = slot_ptr (FROM);                 \
362
0
    OP((DEST), (* stack), ##__VA_ARGS__);           \
363
0
    nextOp ();                                      \
364
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
365
0
d_m3Op(TYPE##_##NAME##_##FROM##_s_r)                \
366
0
{                                                   \
367
0
    TYPE * dest = slot_ptr (TYPE);                  \
368
0
    OP((* dest), (FROM) SRC, ##__VA_ARGS__);        \
369
0
    nextOp ();                                      \
370
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
371
0
d_m3Op(TYPE##_##NAME##_##FROM##_s_s)                \
372
0
{                                                   \
373
0
    FROM * stack = slot_ptr (FROM);                 \
374
0
    TYPE * dest = slot_ptr (TYPE);                  \
375
0
    OP((* dest), (* stack), ##__VA_ARGS__);         \
376
0
    nextOp ();                                      \
377
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
378
379
#if d_m3HasFloat
380
0
d_m3TruncMacro(_r0, _fp0, i32, Trunc, f32, OP_I32_TRUNC_F32)
381
0
d_m3TruncMacro(_r0, _fp0, u32, Trunc, f32, OP_U32_TRUNC_F32)
382
0
d_m3TruncMacro(_r0, _fp0, i32, Trunc, f64, OP_I32_TRUNC_F64)
383
0
d_m3TruncMacro(_r0, _fp0, u32, Trunc, f64, OP_U32_TRUNC_F64)
384
385
0
d_m3TruncMacro(_r0, _fp0, i64, Trunc, f32, OP_I64_TRUNC_F32)
386
0
d_m3TruncMacro(_r0, _fp0, u64, Trunc, f32, OP_U64_TRUNC_F32)
387
0
d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64)
388
0
d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64)
389
390
0
d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f32, OP_I32_TRUNC_SAT_F32)
391
0
d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f32, OP_U32_TRUNC_SAT_F32)
392
0
d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f64, OP_I32_TRUNC_SAT_F64)
393
0
d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f64, OP_U32_TRUNC_SAT_F64)
394
395
0
d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f32, OP_I64_TRUNC_SAT_F32)
396
0
d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f32, OP_U64_TRUNC_SAT_F32)
397
0
d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f64, OP_I64_TRUNC_SAT_F64)
398
0
d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f64, OP_U64_TRUNC_SAT_F64)
399
#endif
400
401
#define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM)  \
402
0
d_m3Op(TO##_##NAME##_##FROM##_r)                            \
403
0
{                                                           \
404
0
    REG_TO = (TO) ((FROM) REG_FROM);                        \
405
0
    nextOp ();                                              \
406
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
407
                                                            \
408
0
d_m3Op(TO##_##NAME##_##FROM##_s)                            \
409
0
{                                                           \
410
0
    FROM from = slot (FROM);                                \
411
0
    REG_TO = (TO) (from);                                   \
412
0
    nextOp ();                                              \
413
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
414
415
// Int to int
416
d_m3TypeModifyOp (_r0, _r0, i64, Extend, i32);
417
d_m3TypeModifyOp (_r0, _r0, i64, Extend, u32);
418
419
// Float to float
420
#if d_m3HasFloat
421
d_m3TypeModifyOp (_fp0, _fp0, f32, Demote, f64);
422
d_m3TypeModifyOp (_fp0, _fp0, f64, Promote, f32);
423
#endif
424
425
#define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \
426
0
d_m3Op(TO##_##NAME##_##FROM##_r_r)                          \
427
0
{                                                           \
428
0
    REG_TO = (TO) ((FROM) REG_FROM);                        \
429
0
    nextOp ();                                              \
430
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
431
                                                            \
432
0
d_m3Op(TO##_##NAME##_##FROM##_s_r)                          \
433
0
{                                                           \
434
0
    slot (TO) = (TO) ((FROM) REG_FROM);                     \
435
0
    nextOp ();                                              \
436
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
437
                                                            \
438
0
d_m3Op(TO##_##NAME##_##FROM##_r_s)                          \
439
0
{                                                           \
440
0
    FROM from = slot (FROM);                                \
441
0
    REG_TO = (TO) (from);                                   \
442
0
    nextOp ();                                              \
443
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
444
                                                            \
445
0
d_m3Op(TO##_##NAME##_##FROM##_s_s)                          \
446
0
{                                                           \
447
0
    FROM from = slot (FROM);                                \
448
0
    slot (TO) = (TO) (from);                                \
449
0
    nextOp ();                                              \
450
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
451
452
// Int to float
453
#if d_m3HasFloat
454
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i32);
455
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u32);
456
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, i64);
457
d_m3TypeConvertOp (_fp0, _r0, f64, Convert, u64);
458
459
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i32);
460
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u32);
461
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, i64);
462
d_m3TypeConvertOp (_fp0, _r0, f32, Convert, u64);
463
#endif
464
465
#define d_m3ReinterpretOp(REG, TO, SRC, FROM)               \
466
0
d_m3Op(TO##_Reinterpret_##FROM##_r_r)                       \
467
0
{                                                           \
468
0
    union { FROM c; TO t; } u;                              \
469
0
    u.c = (FROM) SRC;                                       \
470
0
    REG = u.t;                                              \
471
0
    nextOp ();                                              \
472
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
473
                                                            \
474
0
d_m3Op(TO##_Reinterpret_##FROM##_r_s)                       \
475
0
{                                                           \
476
0
    union { FROM c; TO t; } u;                              \
477
0
    u.c = slot (FROM);                                      \
478
0
    REG = u.t;                                              \
479
0
    nextOp ();                                              \
480
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
481
                                                            \
482
0
d_m3Op(TO##_Reinterpret_##FROM##_s_r)                       \
483
0
{                                                           \
484
0
    union { FROM c; TO t; } u;                              \
485
0
    u.c = (FROM) SRC;                                       \
486
0
    slot (TO) = u.t;                                        \
487
0
    nextOp ();                                              \
488
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
489
                                                            \
490
0
d_m3Op(TO##_Reinterpret_##FROM##_s_s)                       \
491
0
{                                                           \
492
0
    union { FROM c; TO t; } u;                              \
493
0
    u.c = slot (FROM);                                      \
494
0
    slot (TO) = u.t;                                        \
495
0
    nextOp ();                                              \
496
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
497
498
#if d_m3HasFloat
499
d_m3ReinterpretOp (_r0, i32, _fp0, f32)
500
d_m3ReinterpretOp (_r0, i64, _fp0, f64)
501
d_m3ReinterpretOp (_fp0, f32, _r0, i32)
502
d_m3ReinterpretOp (_fp0, f64, _r0, i64)
503
#endif
504
505
506
d_m3Op  (GetGlobal_s32)
507
407
{
508
407
    u32 * global = immediate (u32 *);
509
407
    slot (u32) = * global;                        //  printf ("get global: %p %" PRIi64 "\n", global, *global);
510
511
407
    nextOp ();
512
407
}
513
514
515
d_m3Op  (GetGlobal_s64)
516
356
{
517
356
    u64 * global = immediate (u64 *);
518
356
    slot (u64) = * global;                        // printf ("get global: %p %" PRIi64 "\n", global, *global);
519
520
356
    nextOp ();
521
356
}
522
523
524
d_m3Op  (SetGlobal_i32)
525
0
{
526
0
    u32 * global = immediate (u32 *);
527
0
    * global = (u32) _r0;                         //  printf ("set global: %p %" PRIi64 "\n", global, _r0);
528
529
0
    nextOp ();
530
0
}
531
532
533
d_m3Op  (SetGlobal_i64)
534
0
{
535
0
    u64 * global = immediate (u64 *);
536
0
    * global = (u64) _r0;                         //  printf ("set global: %p %" PRIi64 "\n", global, _r0);
537
538
0
    nextOp ();
539
0
}
540
541
542
d_m3Op  (Call)
543
0
{
544
0
    pc_t callPC                 = immediate (pc_t);
545
0
    i32 stackOffset             = immediate (i32);
546
0
    IM3Memory memory            = m3MemInfo (_mem);
547
548
0
    m3stack_t sp = _sp + stackOffset;
549
550
# if (d_m3EnableOpProfiling || d_m3EnableOpTracing)
551
    m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr);
552
# else
553
0
    m3ret_t r = Call (callPC, sp, _mem, d_m3OpDefaultArgs);
554
0
# endif
555
556
0
    _mem = memory->mallocated;
557
558
0
    if (M3_LIKELY(not r))
559
0
        nextOp ();
560
0
    else
561
0
    {
562
0
        pushBacktraceFrame ();
563
0
        forwardTrap (r);
564
0
    }
565
0
}
566
567
568
d_m3Op  (CallIndirect)
569
0
{
570
0
    u32 tableIndex              = slot (u32);
571
0
    IM3Module module            = immediate (IM3Module);
572
0
    IM3FuncType type            = immediate (IM3FuncType);
573
0
    i32 stackOffset             = immediate (i32);
574
0
    IM3Memory memory            = m3MemInfo (_mem);
575
576
0
    m3stack_t sp = _sp + stackOffset;
577
578
0
    m3ret_t r = m3Err_none;
579
580
0
    if (M3_LIKELY(tableIndex < module->table0Size))
581
0
    {
582
0
        IM3Function function = module->table0 [tableIndex];
583
584
0
        if (M3_LIKELY(function))
585
0
        {
586
0
            if (M3_LIKELY(type == function->funcType))
587
0
            {
588
0
                if (M3_UNLIKELY(not function->compiled))
589
0
                    r = CompileFunction (function);
590
591
0
                if (M3_LIKELY(not r))
592
0
                {
593
594
# if (d_m3EnableOpProfiling || d_m3EnableOpTracing)
595
                    r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr);
596
# else
597
0
                    r = Call (function->compiled, sp, _mem, d_m3OpDefaultArgs);
598
0
# endif
599
600
0
                    _mem = memory->mallocated;
601
602
0
                    if (M3_LIKELY(not r))
603
0
                        nextOpDirect ();
604
0
                    else
605
0
                    {
606
0
                        pushBacktraceFrame ();
607
0
                        forwardTrap (r);
608
0
                    }
609
0
                }
610
0
            }
611
0
            else r = m3Err_trapIndirectCallTypeMismatch;
612
0
        }
613
0
        else r = m3Err_trapTableElementIsNull;
614
0
    }
615
0
    else r = m3Err_trapTableIndexOutOfRange;
616
617
0
    if (M3_UNLIKELY(r))
618
0
        newTrap (r);
619
0
    else forwardTrap (r);
620
0
}
621
622
623
d_m3Op  (CallRawFunction)
624
0
{
625
0
    d_m3TracePrepare
626
627
0
    M3ImportContext ctx;
628
629
0
    M3RawCall call = (M3RawCall) (* _pc++);
630
0
    ctx.function = immediate (IM3Function);
631
0
    ctx.userdata = immediate (void *);
632
0
    u64* const sp = ((u64*)_sp);
633
0
    IM3Memory memory = m3MemInfo (_mem);
634
635
0
    IM3Runtime runtime = m3MemRuntime(_mem);
636
637
#if d_m3EnableStrace
638
    IM3FuncType ftype = ctx.function->funcType;
639
640
    FILE* out = stderr;
641
    char outbuff[1024];
642
    char* outp = outbuff;
643
    char* oute = outbuff+1024;
644
645
    outp += snprintf(outp, oute-outp, "%s!%s(", ctx.function->import.moduleUtf8, ctx.function->import.fieldUtf8);
646
647
    const int nArgs = ftype->numArgs;
648
    const int nRets = ftype->numRets;
649
    u64 * args = sp + nRets;
650
    for (int i=0; i<nArgs; i++) {
651
        const int type = ftype->types[nRets + i];
652
        switch (type) {
653
        case c_m3Type_i32:  outp += snprintf(outp, oute-outp, "%" PRIi32, *(i32*)(args+i)); break;
654
        case c_m3Type_i64:  outp += snprintf(outp, oute-outp, "%" PRIi64, *(i64*)(args+i)); break;
655
        case c_m3Type_f32:  outp += snprintf(outp, oute-outp, "%" PRIf32, *(f32*)(args+i)); break;
656
        case c_m3Type_f64:  outp += snprintf(outp, oute-outp, "%" PRIf64, *(f64*)(args+i)); break;
657
        default:            outp += snprintf(outp, oute-outp, "<type %d>", type);         break;
658
        }
659
        outp += snprintf(outp, oute-outp, (i < nArgs-1) ? ", " : ")");
660
    }
661
# if d_m3EnableStrace >= 2
662
    outp += snprintf(outp, oute-outp, " { <native> }");
663
# endif
664
#endif
665
666
    // m3_Call uses runtime->stack to set-up initial exported function stack.
667
    // Reconfigure the stack to enable recursive invocations of m3_Call.
668
    // I.e. exported/table function can be called from an impoted function.
669
0
    void* stack_backup = runtime->stack;
670
0
    runtime->stack = sp;
671
0
    m3ret_t possible_trap = call (runtime, &ctx, sp, m3MemData(_mem));
672
0
    runtime->stack = stack_backup;
673
674
#if d_m3EnableStrace
675
    if (M3_UNLIKELY(possible_trap)) {
676
        d_m3TracePrint("%s -> %s", outbuff, (char*)possible_trap);
677
    } else {
678
        switch (GetSingleRetType(ftype)) {
679
        case c_m3Type_none: d_m3TracePrint("%s", outbuff); break;
680
        case c_m3Type_i32:  d_m3TracePrint("%s = %" PRIi32, outbuff, *(i32*)sp); break;
681
        case c_m3Type_i64:  d_m3TracePrint("%s = %" PRIi64, outbuff, *(i64*)sp); break;
682
        case c_m3Type_f32:  d_m3TracePrint("%s = %" PRIf32, outbuff, *(f32*)sp); break;
683
        case c_m3Type_f64:  d_m3TracePrint("%s = %" PRIf64, outbuff, *(f64*)sp); break;
684
        }
685
    }
686
#endif
687
688
0
    if (M3_UNLIKELY(possible_trap)) {
689
0
        _mem = memory->mallocated;
690
0
        pushBacktraceFrame ();
691
0
    }
692
0
    forwardTrap (possible_trap);
693
0
}
694
695
696
d_m3Op  (MemSize)
697
0
{
698
0
    IM3Memory memory            = m3MemInfo (_mem);
699
700
0
    _r0 = memory->numPages;
701
702
0
    nextOp ();
703
0
}
704
705
706
d_m3Op  (MemGrow)
707
0
{
708
0
    IM3Runtime runtime          = m3MemRuntime(_mem);
709
0
    IM3Memory memory            = & runtime->memory;
710
711
0
    i32 numPagesToGrow = _r0;
712
0
    if (numPagesToGrow >= 0) {
713
0
        _r0 = memory->numPages;
714
715
0
        if (M3_LIKELY(numPagesToGrow))
716
0
        {
717
0
            u32 requiredPages = memory->numPages + numPagesToGrow;
718
719
0
            M3Result r = ResizeMemory (runtime, requiredPages);
720
0
            if (r)
721
0
                _r0 = -1;
722
723
0
            _mem = memory->mallocated;
724
0
        }
725
0
    }
726
0
    else
727
0
    {
728
0
        _r0 = -1;
729
0
    }
730
731
0
    nextOp ();
732
0
}
733
734
735
d_m3Op  (MemCopy)
736
0
{
737
0
    u32 size = (u32) _r0;
738
0
    u64 source = slot (u32);
739
0
    u64 destination = slot (u32);
740
741
0
    if (M3_LIKELY(destination + size <= _mem->length))
742
0
    {
743
0
        if (M3_LIKELY(source + size <= _mem->length))
744
0
        {
745
0
            u8 * dst = m3MemData (_mem) + destination;
746
0
            u8 * src = m3MemData (_mem) + source;
747
0
            memmove (dst, src, size);
748
749
0
            nextOp ();
750
0
        }
751
0
        else d_outOfBoundsMemOp (source, size);
752
0
    }
753
0
    else d_outOfBoundsMemOp (destination, size);
754
0
}
755
756
757
d_m3Op  (MemFill)
758
0
{
759
0
    u32 size = (u32) _r0;
760
0
    u32 byte = slot (u32);
761
0
    u64 destination = slot (u32);
762
763
0
    if (M3_LIKELY(destination + size <= _mem->length))
764
0
    {
765
0
        u8 * mem8 = m3MemData (_mem) + destination;
766
0
        memset (mem8, (u8) byte, size);
767
0
        nextOp ();
768
0
    }
769
0
    else d_outOfBoundsMemOp (destination, size);
770
0
}
771
772
773
// it's a debate: should the compilation be trigger be the caller or callee page.
774
// it's a much easier to put it in the caller pager. if it's in the callee, either the entire page
775
// has be left dangling or it's just a stub that jumps to a newly acquired page.  In Gestalt, I opted
776
// for the stub approach. Stubbing makes it easier to dynamically free the compilation. You can also
777
// do both.
778
d_m3Op  (Compile)
779
0
{
780
0
    rewrite_op (op_Call);
781
782
0
    IM3Function function        = immediate (IM3Function);
783
784
0
    m3ret_t result = m3Err_none;
785
786
0
    if (M3_UNLIKELY(not function->compiled)) // check to see if function was compiled since this operation was emitted.
787
0
        result = CompileFunction (function);
788
789
0
    if (not result)
790
0
    {
791
        // patch up compiled pc and call rewritten op_Call
792
0
        * ((void**) --_pc) = (void*) (function->compiled);
793
0
        --_pc;
794
0
        nextOpDirect ();
795
0
    }
796
797
0
    newTrap (result);
798
0
}
799
800
801
802
d_m3Op  (Entry)
803
0
{
804
0
    d_m3ClearRegisters
805
806
    d_m3TracePrepare
807
808
0
    IM3Function function = immediate (IM3Function);
809
0
    IM3Memory memory = m3MemInfo (_mem);
810
811
#if d_m3SkipStackCheck
812
    if (true)
813
#else
814
0
    if (M3_LIKELY ((void *) (_sp + function->maxStackSlots) < _mem->maxStack))
815
0
#endif
816
0
    {
817
#if defined(DEBUG)
818
        function->hits++;
819
#endif
820
0
        u8 * stack = (u8 *) ((m3slot_t *) _sp + function->numRetAndArgSlots);
821
822
0
        memset (stack, 0x0, function->numLocalBytes);
823
0
        stack += function->numLocalBytes;
824
825
0
        if (function->constants)
826
0
        {
827
0
            memcpy (stack, function->constants, function->numConstantBytes);
828
0
        }
829
830
#if d_m3EnableStrace >= 2
831
        d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList (function, _sp + function->numRetSlots));
832
        trace_rt->callDepth++;
833
#endif
834
835
0
        m3ret_t r = nextOpImpl ();
836
837
#if d_m3EnableStrace >= 2
838
        trace_rt->callDepth--;
839
840
        if (r) {
841
            d_m3TracePrint("} !trap = %s", (char*)r);
842
        } else {
843
            int rettype = GetSingleRetType(function->funcType);
844
            if (rettype != c_m3Type_none) {
845
                char str [128] = { 0 };
846
                SPrintArg (str, 127, _sp, rettype);
847
                d_m3TracePrint("} = %s", str);
848
            } else {
849
                d_m3TracePrint("}");
850
            }
851
        }
852
#endif
853
854
0
        if (M3_UNLIKELY(r)) {
855
0
            _mem = memory->mallocated;
856
0
            fillBacktraceFrame ();
857
0
        }
858
0
        forwardTrap (r);
859
0
    }
860
0
    else newTrap (m3Err_trapStackOverflow);
861
0
}
862
863
864
d_m3Op  (Loop)
865
0
{
866
0
    d_m3TracePrepare
867
868
    // regs are unused coming into a loop anyway
869
    // this reduces code size & stack usage
870
0
    d_m3ClearRegisters
871
872
0
    m3ret_t r;
873
874
0
    IM3Memory memory = m3MemInfo (_mem);
875
876
0
    do
877
0
    {
878
#if d_m3EnableStrace >= 3
879
        d_m3TracePrint("iter {");
880
        trace_rt->callDepth++;
881
#endif
882
0
        r = nextOpImpl ();
883
884
#if d_m3EnableStrace >= 3
885
        trace_rt->callDepth--;
886
        d_m3TracePrint("}");
887
#endif
888
        // linear memory pointer needs refreshed here because the block it's looping over
889
        // can potentially invoke the grow operation.
890
0
        _mem = memory->mallocated;
891
0
    }
892
0
    while (r == _pc);
893
894
0
    forwardTrap (r);
895
0
}
896
897
898
d_m3Op  (Branch)
899
0
{
900
0
    jumpOp (* _pc);
901
0
}
902
903
904
d_m3Op  (If_r)
905
0
{
906
0
    i32 condition = (i32) _r0;
907
908
0
    pc_t elsePC = immediate (pc_t);
909
910
0
    if (condition)
911
0
        nextOp ();
912
0
    else
913
0
        jumpOp (elsePC);
914
0
}
915
916
917
d_m3Op  (If_s)
918
0
{
919
0
    i32 condition = slot (i32);
920
921
0
    pc_t elsePC = immediate (pc_t);
922
923
0
    if (condition)
924
0
        nextOp ();
925
0
    else
926
0
        jumpOp (elsePC);
927
0
}
928
929
930
d_m3Op  (BranchTable)
931
0
{
932
0
    u32 branchIndex = slot (u32);           // branch index is always in a slot
933
0
    u32 numTargets  = immediate (u32);
934
935
0
    pc_t * branches = (pc_t *) _pc;
936
937
0
    if (branchIndex > numTargets)
938
0
        branchIndex = numTargets; // the default index
939
940
0
    jumpOp (branches [branchIndex]);
941
0
}
942
943
944
#define d_m3SetRegisterSetSlot(TYPE, REG) \
945
0
d_m3Op  (SetRegister_##TYPE)            \
946
0
{                                       \
947
0
    REG = slot (TYPE);                  \
948
0
    nextOp ();                          \
949
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
950
                                        \
951
0
d_m3Op (SetSlot_##TYPE)                 \
952
0
{                                       \
953
0
    slot (TYPE) = (TYPE) REG;           \
954
0
    nextOp ();                          \
955
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
956
                                        \
957
0
d_m3Op (PreserveSetSlot_##TYPE)         \
958
0
{                                       \
959
0
    TYPE * stack     = slot_ptr (TYPE); \
960
0
    TYPE * preserve  = slot_ptr (TYPE); \
961
0
                                        \
962
0
    * preserve = * stack;               \
963
0
    * stack = (TYPE) REG;               \
964
0
                                        \
965
0
    nextOp ();                          \
966
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
967
968
d_m3SetRegisterSetSlot (i32, _r0)
969
d_m3SetRegisterSetSlot (i64, _r0)
970
#if d_m3HasFloat
971
d_m3SetRegisterSetSlot (f32, _fp0)
972
d_m3SetRegisterSetSlot (f64, _fp0)
973
#endif
974
975
d_m3Op (CopySlot_32)
976
0
{
977
0
    u32 * dst = slot_ptr (u32);
978
0
    u32 * src = slot_ptr (u32);
979
980
0
    * dst = * src;
981
982
0
    nextOp ();
983
0
}
984
985
986
d_m3Op (PreserveCopySlot_32)
987
0
{
988
0
    u32 * dest      = slot_ptr (u32);
989
0
    u32 * src       = slot_ptr (u32);
990
0
    u32 * preserve  = slot_ptr (u32);
991
992
0
    * preserve = * dest;
993
0
    * dest = * src;
994
995
0
    nextOp ();
996
0
}
997
998
999
d_m3Op (CopySlot_64)
1000
0
{
1001
0
    u64 * dst = slot_ptr (u64);
1002
0
    u64 * src = slot_ptr (u64);
1003
1004
0
    * dst = * src;                  // printf ("copy: %p <- %" PRIi64 " <- %p\n", dst, * dst, src);
1005
1006
0
    nextOp ();
1007
0
}
1008
1009
1010
d_m3Op (PreserveCopySlot_64)
1011
0
{
1012
0
    u64 * dest      = slot_ptr (u64);
1013
0
    u64 * src       = slot_ptr (u64);
1014
0
    u64 * preserve  = slot_ptr (u64);
1015
1016
0
    * preserve = * dest;
1017
0
    * dest = * src;
1018
1019
0
    nextOp ();
1020
0
}
1021
1022
1023
#if d_m3EnableOpTracing
1024
//--------------------------------------------------------------------------------------------------------
1025
d_m3Op  (DumpStack)
1026
{
1027
    u32 opcodeIndex         = immediate (u32);
1028
    u32 stackHeight         = immediate (u32);
1029
    IM3Function function    = immediate (IM3Function);
1030
1031
    cstr_t funcName = (function) ? m3_GetFunctionName(function) : "";
1032
1033
    printf (" %4d ", opcodeIndex);
1034
    printf (" %-25s     r0: 0x%016" PRIx64 "  i:%" PRIi64 "  u:%" PRIu64 "\n", funcName, _r0, _r0, _r0);
1035
#if d_m3HasFloat
1036
    printf ("                                    fp0: %" PRIf64 "\n", _fp0);
1037
#endif
1038
    m3stack_t sp = _sp;
1039
1040
    for (u32 i = 0; i < stackHeight; ++i)
1041
    {
1042
        cstr_t kind = "";
1043
1044
        printf ("%p  %5s  %2d: 0x%" PRIx64 "  i:%" PRIi64 "\n", sp, kind, i, (u64) *(sp), (i64) *(sp));
1045
1046
        ++sp;
1047
    }
1048
    printf ("---------------------------------------------------------------------------------------------------------\n");
1049
1050
    nextOpDirect();
1051
}
1052
#endif
1053
1054
1055
#define d_m3Select_i(TYPE, REG)                 \
1056
0
d_m3Op  (Select_##TYPE##_rss)                   \
1057
0
{                                               \
1058
0
    i32 condition = (i32) _r0;                  \
1059
0
                                                \
1060
0
    TYPE operand2 = slot (TYPE);                \
1061
0
    TYPE operand1 = slot (TYPE);                \
1062
0
                                                \
1063
0
    REG = (condition) ? operand1 : operand2;    \
1064
0
                                                \
1065
0
    nextOp ();                                  \
1066
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_rss
Unexecuted instantiation: m3_compile.c:op_Select_i64_rss
1067
                                                \
1068
0
d_m3Op  (Select_##TYPE##_srs)                   \
1069
0
{                                               \
1070
0
    i32 condition = slot (i32);                 \
1071
0
                                                \
1072
0
    TYPE operand2 = (TYPE) REG;                 \
1073
0
    TYPE operand1 = slot (TYPE);                \
1074
0
                                                \
1075
0
    REG = (condition) ? operand1 : operand2;    \
1076
0
                                                \
1077
0
    nextOp ();                                  \
1078
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_srs
Unexecuted instantiation: m3_compile.c:op_Select_i64_srs
1079
                                                \
1080
0
d_m3Op  (Select_##TYPE##_ssr)                   \
1081
0
{                                               \
1082
0
    i32 condition = slot (i32);                 \
1083
0
                                                \
1084
0
    TYPE operand2 = slot (TYPE);                \
1085
0
    TYPE operand1 = (TYPE) REG;                 \
1086
0
                                                \
1087
0
    REG = (condition) ? operand1 : operand2;    \
1088
0
                                                \
1089
0
    nextOp ();                                  \
1090
0
}                                               \
Unexecuted instantiation: m3_compile.c:op_Select_i32_ssr
Unexecuted instantiation: m3_compile.c:op_Select_i64_ssr
1091
                                                \
1092
0
d_m3Op  (Select_##TYPE##_sss)                   \
1093
0
{                                               \
1094
0
    i32 condition = slot (i32);                 \
1095
0
                                                \
1096
0
    TYPE operand2 = slot (TYPE);                \
1097
0
    TYPE operand1 = slot (TYPE);                \
1098
0
                                                \
1099
0
    REG = (condition) ? operand1 : operand2;    \
1100
0
                                                \
1101
0
    nextOp ();                                  \
1102
0
}
Unexecuted instantiation: m3_compile.c:op_Select_i32_sss
Unexecuted instantiation: m3_compile.c:op_Select_i64_sss
1103
1104
1105
d_m3Select_i (i32, _r0)
1106
d_m3Select_i (i64, _r0)
1107
1108
1109
#define d_m3Select_f(TYPE, REG, LABEL, SELECTOR)  \
1110
0
d_m3Op  (Select_##TYPE##_##LABEL##ss)           \
1111
0
{                                               \
1112
0
    i32 condition = (i32) SELECTOR;             \
1113
0
                                                \
1114
0
    TYPE operand2 = slot (TYPE);                \
1115
0
    TYPE operand1 = slot (TYPE);                \
1116
0
                                                \
1117
0
    REG = (condition) ? operand1 : operand2;    \
1118
0
                                                \
1119
0
    nextOp ();                                  \
1120
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
1121
                                                \
1122
0
d_m3Op  (Select_##TYPE##_##LABEL##rs)           \
1123
0
{                                               \
1124
0
    i32 condition = (i32) SELECTOR;             \
1125
0
                                                \
1126
0
    TYPE operand2 = (TYPE) REG;                 \
1127
0
    TYPE operand1 = slot (TYPE);                \
1128
0
                                                \
1129
0
    REG = (condition) ? operand1 : operand2;    \
1130
0
                                                \
1131
0
    nextOp ();                                  \
1132
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
1133
                                                \
1134
0
d_m3Op  (Select_##TYPE##_##LABEL##sr)           \
1135
0
{                                               \
1136
0
    i32 condition = (i32) SELECTOR;             \
1137
0
                                                \
1138
0
    TYPE operand2 = slot (TYPE);                \
1139
0
    TYPE operand1 = (TYPE) REG;                 \
1140
0
                                                \
1141
0
    REG = (condition) ? operand1 : operand2;    \
1142
0
                                                \
1143
0
    nextOp ();                                  \
1144
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
1145
1146
#if d_m3HasFloat
1147
d_m3Select_f (f32, _fp0, r, _r0)
1148
d_m3Select_f (f32, _fp0, s, slot (i32))
1149
1150
d_m3Select_f (f64, _fp0, r, _r0)
1151
d_m3Select_f (f64, _fp0, s, slot (i32))
1152
#endif
1153
1154
d_m3Op  (Return)
1155
335
{
1156
335
    m3StackCheck();
1157
335
    return m3Err_none;
1158
335
}
1159
1160
1161
d_m3Op  (BranchIf_r)
1162
0
{
1163
0
    i32 condition   = (i32) _r0;
1164
0
    pc_t branch     = immediate (pc_t);
1165
1166
0
    if (condition)
1167
0
    {
1168
0
        jumpOp (branch);
1169
0
    }
1170
0
    else nextOp ();
1171
0
}
1172
1173
1174
d_m3Op  (BranchIf_s)
1175
0
{
1176
0
    i32 condition   = slot (i32);
1177
0
    pc_t branch     = immediate (pc_t);
1178
1179
0
    if (condition)
1180
0
    {
1181
0
        jumpOp (branch);
1182
0
    }
1183
0
    else nextOp ();
1184
0
}
1185
1186
1187
d_m3Op  (BranchIfPrologue_r)
1188
0
{
1189
0
    i32 condition   = (i32) _r0;
1190
0
    pc_t branch     = immediate (pc_t);
1191
1192
0
    if (condition)
1193
0
    {
1194
        // this is the "prologue" that ends with
1195
        // a plain branch to the actual target
1196
0
        nextOp ();
1197
0
    }
1198
0
    else jumpOp (branch); // jump over the prologue
1199
0
}
1200
1201
1202
d_m3Op  (BranchIfPrologue_s)
1203
0
{
1204
0
    i32 condition   = slot (i32);
1205
0
    pc_t branch     = immediate (pc_t);
1206
1207
0
    if (condition)
1208
0
    {
1209
0
        nextOp ();
1210
0
    }
1211
0
    else jumpOp (branch);
1212
0
}
1213
1214
1215
d_m3Op  (ContinueLoop)
1216
0
{
1217
0
    m3StackCheck();
1218
1219
    // TODO: this is where execution can "escape" the M3 code and callback to the client / fiber switch
1220
    // OR it can go in the Loop operation. I think it's best to do here. adding code to the loop operation
1221
    // has the potential to increase its native-stack usage. (don't forget ContinueLoopIf too.)
1222
1223
0
    void * loopId = immediate (void *);
1224
0
    return loopId;
1225
0
}
1226
1227
1228
d_m3Op  (ContinueLoopIf)
1229
0
{
1230
0
    i32 condition = (i32) _r0;
1231
0
    void * loopId = immediate (void *);
1232
1233
0
    if (condition)
1234
0
    {
1235
0
        return loopId;
1236
0
    }
1237
0
    else nextOp ();
1238
0
}
1239
1240
1241
d_m3Op  (Const32)
1242
164
{
1243
164
    u32 value = * (u32 *)_pc++;
1244
164
    slot (u32) = value;
1245
164
    nextOp ();
1246
164
}
1247
1248
1249
d_m3Op  (Const64)
1250
384
{
1251
384
    u64 value = * (u64 *)_pc;
1252
384
    _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1;
1253
384
    slot (u64) = value;
1254
384
    nextOp ();
1255
384
}
1256
1257
d_m3Op  (Unsupported)
1258
0
{
1259
0
    newTrap ("unsupported instruction executed");
1260
0
}
1261
1262
d_m3Op  (Unreachable)
1263
0
{
1264
0
    m3StackCheck();
1265
0
    newTrap (m3Err_trapUnreachable);
1266
0
}
1267
1268
1269
d_m3Op  (End)
1270
0
{
1271
0
    m3StackCheck();
1272
0
    return m3Err_none;
1273
0
}
1274
1275
1276
d_m3Op  (SetGlobal_s32)
1277
0
{
1278
0
    u32 * global = immediate (u32 *);
1279
0
    * global = slot (u32);
1280
1281
0
    nextOp ();
1282
0
}
1283
1284
1285
d_m3Op  (SetGlobal_s64)
1286
0
{
1287
0
    u64 * global = immediate (u64 *);
1288
0
    * global = slot (u64);
1289
1290
0
    nextOp ();
1291
0
}
1292
1293
#if d_m3HasFloat
1294
d_m3Op  (SetGlobal_f32)
1295
0
{
1296
0
    f32 * global = immediate (f32 *);
1297
0
    * global = _fp0;
1298
1299
0
    nextOp ();
1300
0
}
1301
1302
1303
d_m3Op  (SetGlobal_f64)
1304
0
{
1305
0
    f64 * global = immediate (f64 *);
1306
0
    * global = _fp0;
1307
1308
0
    nextOp ();
1309
0
}
1310
#endif
1311
1312
1313
#if d_m3SkipMemoryBoundsCheck
1314
#  define m3MemCheck(x) true
1315
#else
1316
0
#  define m3MemCheck(x) M3_LIKELY(x)
1317
#endif
1318
1319
// memcpy here is to support non-aligned access on some platforms.
1320
1321
#define d_m3Load(REG,DEST_TYPE,SRC_TYPE)                \
1322
0
d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r)                 \
1323
0
{                                                       \
1324
0
    d_m3TracePrepare                                    \
1325
0
    u32 offset = immediate (u32);                       \
1326
0
    u64 operand = (u32) _r0;                            \
1327
0
    operand += offset;                                  \
1328
0
                                                        \
1329
0
    if (m3MemCheck(                                     \
1330
0
        operand + sizeof (SRC_TYPE) <= _mem->length     \
1331
0
    )) {                                                \
1332
0
        {                                               \
1333
0
            u8* src8 = m3MemData(_mem) + operand;       \
1334
0
            SRC_TYPE value;                             \
1335
0
            memcpy(&value, src8, sizeof(value));        \
1336
0
            M3_BSWAP_##SRC_TYPE(value);                 \
1337
0
            REG = (DEST_TYPE)value;                     \
1338
0
            d_m3TraceLoad(DEST_TYPE, operand, REG);     \
1339
0
        }                                               \
1340
0
        nextOp ();                                      \
1341
0
    } else d_outOfBounds;                               \
1342
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
1343
0
d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s)                 \
1344
0
{                                                       \
1345
0
    d_m3TracePrepare                                    \
1346
0
    u64 operand = slot (u32);                           \
1347
0
    u32 offset = immediate (u32);                       \
1348
0
    operand += offset;                                  \
1349
0
                                                        \
1350
0
    if (m3MemCheck(                                     \
1351
0
        operand + sizeof (SRC_TYPE) <= _mem->length     \
1352
0
    )) {                                                \
1353
0
        {                                               \
1354
0
            u8* src8 = m3MemData(_mem) + operand;       \
1355
0
            SRC_TYPE value;                             \
1356
0
            memcpy(&value, src8, sizeof(value));        \
1357
0
            M3_BSWAP_##SRC_TYPE(value);                 \
1358
0
            REG = (DEST_TYPE)value;                     \
1359
0
            d_m3TraceLoad(DEST_TYPE, operand, REG);     \
1360
0
        }                                               \
1361
0
        nextOp ();                                      \
1362
0
    } else d_outOfBounds;                               \
1363
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
1364
1365
//  printf ("get: %d -> %d\n", operand + offset, (i64) REG);
1366
1367
1368
#define d_m3Load_i(DEST_TYPE, SRC_TYPE) d_m3Load(_r0, DEST_TYPE, SRC_TYPE)
1369
#define d_m3Load_f(DEST_TYPE, SRC_TYPE) d_m3Load(_fp0, DEST_TYPE, SRC_TYPE)
1370
1371
#if d_m3HasFloat
1372
d_m3Load_f (f32, f32);
1373
d_m3Load_f (f64, f64);
1374
#endif
1375
1376
d_m3Load_i (i32, i8);
1377
d_m3Load_i (i32, u8);
1378
d_m3Load_i (i32, i16);
1379
d_m3Load_i (i32, u16);
1380
d_m3Load_i (i32, i32);
1381
1382
d_m3Load_i (i64, i8);
1383
d_m3Load_i (i64, u8);
1384
d_m3Load_i (i64, i16);
1385
d_m3Load_i (i64, u16);
1386
d_m3Load_i (i64, i32);
1387
d_m3Load_i (i64, u32);
1388
d_m3Load_i (i64, i64);
1389
1390
#define d_m3Store(REG, SRC_TYPE, DEST_TYPE)             \
1391
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_rs)             \
1392
0
{                                                       \
1393
0
    d_m3TracePrepare                                    \
1394
0
    u64 operand = slot (u32);                           \
1395
0
    u32 offset = immediate (u32);                       \
1396
0
    operand += offset;                                  \
1397
0
                                                        \
1398
0
    if (m3MemCheck(                                     \
1399
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1400
0
    )) {                                                \
1401
0
        {                                               \
1402
0
            d_m3TraceStore(SRC_TYPE, operand, REG);     \
1403
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1404
0
            DEST_TYPE val = (DEST_TYPE) REG;            \
1405
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1406
0
            memcpy(mem8, &val, sizeof(val));            \
1407
0
        }                                               \
1408
0
        nextOp ();                                      \
1409
0
    } else d_outOfBounds;                               \
1410
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
1411
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_sr)             \
1412
0
{                                                       \
1413
0
    d_m3TracePrepare                                    \
1414
0
    const SRC_TYPE value = slot (SRC_TYPE);             \
1415
0
    u64 operand = (u32) _r0;                            \
1416
0
    u32 offset = immediate (u32);                       \
1417
0
    operand += offset;                                  \
1418
0
                                                        \
1419
0
    if (m3MemCheck(                                     \
1420
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1421
0
    )) {                                                \
1422
0
        {                                               \
1423
0
            d_m3TraceStore(SRC_TYPE, operand, value);   \
1424
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1425
0
            DEST_TYPE val = (DEST_TYPE) value;          \
1426
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1427
0
            memcpy(mem8, &val, sizeof(val));            \
1428
0
        }                                               \
1429
0
        nextOp ();                                      \
1430
0
    } else d_outOfBounds;                               \
1431
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
1432
0
d_m3Op  (SRC_TYPE##_Store_##DEST_TYPE##_ss)             \
1433
0
{                                                       \
1434
0
    d_m3TracePrepare                                    \
1435
0
    const SRC_TYPE value = slot (SRC_TYPE);             \
1436
0
    u64 operand = slot (u32);                           \
1437
0
    u32 offset = immediate (u32);                       \
1438
0
    operand += offset;                                  \
1439
0
                                                        \
1440
0
    if (m3MemCheck(                                     \
1441
0
        operand + sizeof (DEST_TYPE) <= _mem->length    \
1442
0
    )) {                                                \
1443
0
        {                                               \
1444
0
            d_m3TraceStore(SRC_TYPE, operand, value);   \
1445
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1446
0
            DEST_TYPE val = (DEST_TYPE) value;          \
1447
0
            M3_BSWAP_##DEST_TYPE(val);                  \
1448
0
            memcpy(mem8, &val, sizeof(val));            \
1449
0
        }                                               \
1450
0
        nextOp ();                                      \
1451
0
    } else d_outOfBounds;                               \
1452
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
1453
1454
// both operands can be in regs when storing a float
1455
#define d_m3StoreFp(REG, TYPE)                          \
1456
0
d_m3Op  (TYPE##_Store_##TYPE##_rr)                      \
1457
0
{                                                       \
1458
0
    d_m3TracePrepare                                    \
1459
0
    u64 operand = (u32) _r0;                            \
1460
0
    u32 offset = immediate (u32);                       \
1461
0
    operand += offset;                                  \
1462
0
                                                        \
1463
0
    if (m3MemCheck(                                     \
1464
0
        operand + sizeof (TYPE) <= _mem->length         \
1465
0
    )) {                                                \
1466
0
        {                                               \
1467
0
            d_m3TraceStore(TYPE, operand, REG);         \
1468
0
            u8* mem8 = m3MemData(_mem) + operand;       \
1469
0
            TYPE val = (TYPE) REG;                      \
1470
0
            M3_BSWAP_##TYPE(val);                       \
1471
0
            memcpy(mem8, &val, sizeof(val));            \
1472
0
        }                                               \
1473
0
        nextOp ();                                      \
1474
0
    } else d_outOfBounds;                               \
1475
0
}
Unexecuted instantiation: m3_compile.c:op_f32_Store_f32_rr
Unexecuted instantiation: m3_compile.c:op_f64_Store_f64_rr
1476
1477
1478
#define d_m3Store_i(SRC_TYPE, DEST_TYPE) d_m3Store(_r0, SRC_TYPE, DEST_TYPE)
1479
#define d_m3Store_f(SRC_TYPE, DEST_TYPE) d_m3Store(_fp0, SRC_TYPE, DEST_TYPE) d_m3StoreFp (_fp0, SRC_TYPE);
1480
1481
#if d_m3HasFloat
1482
d_m3Store_f (f32, f32)
1483
d_m3Store_f (f64, f64)
1484
#endif
1485
1486
d_m3Store_i (i32, u8)
1487
d_m3Store_i (i32, i16)
1488
d_m3Store_i (i32, i32)
1489
1490
d_m3Store_i (i64, u8)
1491
d_m3Store_i (i64, i16)
1492
d_m3Store_i (i64, i32)
1493
d_m3Store_i (i64, i64)
1494
1495
#undef m3MemCheck
1496
1497
1498
//---------------------------------------------------------------------------------------------------------------------
1499
// debug/profiling
1500
//---------------------------------------------------------------------------------------------------------------------
1501
#if d_m3EnableOpTracing
1502
d_m3RetSig  debugOp  (d_m3OpSig, cstr_t i_opcode)
1503
{
1504
    char name [100];
1505
    strcpy (name, strstr (i_opcode, "op_") + 3);
1506
    char * bracket = strstr (name, "(");
1507
    if (bracket) {
1508
        *bracket  = 0;
1509
    }
1510
1511
    puts (name);
1512
    nextOpDirect();
1513
}
1514
# endif
1515
1516
# if d_m3EnableOpProfiling
1517
d_m3RetSig  profileOp  (d_m3OpSig, cstr_t i_operationName)
1518
{
1519
    ProfileHit (i_operationName);
1520
1521
    nextOpDirect();
1522
}
1523
# endif
1524
1525
d_m3EndExternC
1526
1527
#endif // m3_exec_h