/src/wasm3/source/m3_exec.h
Line | Count | Source |
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 | | // 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 | | #include "m3_atomic.h" |
35 | | #include "m3_host.h" |
36 | | |
37 | | #include <limits.h> |
38 | | |
39 | | d_m3BeginExternC |
40 | | |
41 | 15.0k | #define rewrite_op(OP) * ((void **) (_pc-1)) = (void*)(OP) |
42 | | |
43 | 2.10G | #define immediate(TYPE) * ((TYPE *) _pc++) |
44 | 0 | #define skip_immediate(TYPE) (_pc++) |
45 | | |
46 | 630M | #define slot(TYPE) * (TYPE *) (_sp + immediate (i32)) |
47 | 194M | #define slot_ptr(TYPE) (TYPE *) (_sp + immediate (i32)) |
48 | | |
49 | | // Reads one address, index or length operand from a slot, at the width the |
50 | | // memory or table it belongs to is addressed by. Either way exactly one slot |
51 | | // immediate is consumed; only how much of the slot is read differs. |
52 | 266k | #define d_m3WideOperand(IS64) ((IS64) ? slot (u64) : (u64) slot (u32)) |
53 | | |
54 | | // Whether a range fits a memory, written so that it holds for operands of any |
55 | | // magnitude: the subtraction cannot wrap once the start is known to be within |
56 | | // the memory, where start + length could. |
57 | | #define d_m3MemRangeOk(START, LENGTH, MEM) \ |
58 | | ((START) <= (MEM)->length and (LENGTH) <= (MEM)->length - (START)) |
59 | | |
60 | | |
61 | | #if d_m3EnableOpProfiling |
62 | | d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName); |
63 | | # define nextOp() M3_MUSTTAIL return profileOp (d_m3OpAllArgs, __FUNCTION__) |
64 | | #elif d_m3EnableOpTracing |
65 | | d_m3RetSig debugOp (d_m3OpSig, cstr_t i_operationName); |
66 | | # define nextOp() M3_MUSTTAIL return debugOp (d_m3OpAllArgs, __FUNCTION__) |
67 | | #else |
68 | 1.00G | # define nextOp() nextOpDirect() |
69 | | #endif |
70 | | |
71 | | // Next-operation preloading. The dispatch load and the indirect jump that consumes it |
72 | | // sit next to each other, so the jump cannot resolve until the load returns. An |
73 | | // operation's _pc is final as soon as it has taken its immediates -- the offsets are |
74 | | // compile-time constants -- so the load can be issued there instead, leaving the |
75 | | // operation's own work as cover for its latency. |
76 | | // |
77 | | // Preloading is dropped in profiling and tracing builds, where dispatch goes through a |
78 | | // hook instead and the loaded pointer would be the wrong thing to call. |
79 | | #if d_m3PreloadNextOp && !(d_m3EnableOpProfiling || d_m3EnableOpTracing) |
80 | | # define d_m3PreloadNext() const IM3Operation _nextOp = (IM3Operation) (* _pc) |
81 | | # define nextOpPreloaded() M3_MUSTTAIL return _nextOp (_pc + 1, d_m3OpArgs) |
82 | | #else |
83 | | # define d_m3PreloadNext() |
84 | 329M | # define nextOpPreloaded() nextOp() |
85 | | #endif |
86 | | |
87 | | #if d_m3EnableOpProfiling |
88 | | d_m3RetSig profileJumpOp (d_m3OpSig, cstr_t i_operationName); |
89 | | // An operation that leaves by a branch never reaches nextOp, so without this it is |
90 | | // absent from the profile entirely and its outgoing edges are attributed to whatever |
91 | | // ran before it. Has to stay one statement: jumpOp appears in brace-less else arms. |
92 | | # define jumpOp(PC) M3_MUSTTAIL return profileJumpOp ((pc_t)(PC), d_m3OpArgs, __FUNCTION__) |
93 | | #else |
94 | 47.2M | # define jumpOp(PC) jumpOpDirect(PC) |
95 | | #endif |
96 | | |
97 | | #if d_m3RecordBacktraces |
98 | | # define pushBacktraceFrame() (PushBacktraceFrame (_mem->runtime, _pc - 1)) |
99 | | # define fillBacktraceFrame(FUNCTION) (FillBacktraceFunctionInfo (_mem->runtime, function)) |
100 | | |
101 | | # define newTrap(err) return (pushBacktraceFrame (), err) |
102 | | # define forwardTrap(err) return err |
103 | | #else |
104 | 132k | # define pushBacktraceFrame() do {} while (0) |
105 | | # define fillBacktraceFrame(FUNCTION) do {} while (0) |
106 | | |
107 | 24.4k | # define newTrap(err) return err |
108 | 8.00M | # define forwardTrap(err) return err |
109 | | #endif |
110 | | |
111 | | // Trap before an operation that claims a native frame of its own would drive |
112 | | // the native C stack past runtime->stackLimit. Reads the current stack pointer |
113 | | // via a frame-address probe and compares against the low-water mark set by |
114 | | // d_m3StackLimitEnter. Every op that keeps a frame across an inner dispatch |
115 | | // probes here first -- op_Call and op_CallIndirect, and also op_Loop and |
116 | | // op_TryTable, whose frames outlive the body they run. Guarding the frame |
117 | | // claim rather than the call is what keeps op_ReturnCall bounded: the tail |
118 | | // call itself adds nothing, but the frames it leaves standing behind it do. |
119 | | #if d_m3MaxNativeStack > 0 |
120 | | # define d_m3CheckNativeStack() \ |
121 | 8.85M | do { \ |
122 | 8.85M | void * _m3Limit = m3MemRuntime (_mem)->stackLimit; \ |
123 | 8.85M | if (M3_UNLIKELY (_m3Limit && m3_NativeStackPtr () < _m3Limit)) \ |
124 | 8.85M | newTrap (m3Err_trapStackOverflow); \ |
125 | 8.85M | } while (0) |
126 | | #else |
127 | | # define d_m3CheckNativeStack() do {} while (0) |
128 | | #endif |
129 | | |
130 | | |
131 | | #if d_m3HasStackSwitching |
132 | | |
133 | | // Calling into compiled code with an explicit register pair, which the replay |
134 | | // needs and the d_m3OpDefaultArgs spelling cannot express. |
135 | | # if d_m3HasFloat |
136 | 0 | # define d_m3ExpRegArgs(R0, FP0) (R0), (FP0) |
137 | | # else |
138 | | # define d_m3ExpRegArgs(R0, FP0) (R0) |
139 | | # endif |
140 | | |
141 | | # if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
142 | | # define d_m3CallWithRegs(PC, SP, MEM, R0, FP0) \ |
143 | | Call ((PC), (SP), (MEM), d_m3ExpRegArgs (R0, FP0), d_m3BaseCstr) |
144 | | # else |
145 | | # define d_m3CallWithRegs(PC, SP, MEM, R0, FP0) \ |
146 | 0 | Call ((PC), (SP), (MEM), d_m3ExpRegArgs (R0, FP0)) |
147 | | # endif |
148 | | |
149 | | // A suspend is on its way up the native stack and this call was holding a |
150 | | // frame: record what it takes to stand that frame back up, then keep unwinding |
151 | | // with whatever the recording says. The registers go in because op_Call |
152 | | // resumes the caller with the ones its own frame was holding. |
153 | | // |
154 | | // Out of line, and deliberately so: op_Call and its two siblings are the |
155 | | // deepest-recursing functions in the interpreter, and a whole M3Frame of |
156 | | // locals on every call is stack the recursion cannot spare - least of all in a |
157 | | // sanitizer build, where each local carries a redzone. |
158 | | // |
159 | | // Called ahead of pushBacktraceFrame: a suspend is not a trap and has no |
160 | | // business writing a backtrace. |
161 | | static M3_NOINLINE |
162 | | m3ret_t RecordCallFrame (IM3Runtime i_runtime, pc_t i_pc, m3stack_t i_sp, IM3Memory i_memory, |
163 | | IM3Function i_function, m3reg_t i_r0 |
164 | | # if d_m3HasFloat |
165 | | , |
166 | | f64 i_fp0 |
167 | | # endif |
168 | | ) |
169 | 0 | { |
170 | 0 | M3Frame frame; |
171 | |
|
172 | 0 | frame.kind = frame_call; |
173 | 0 | frame.pc = i_pc; |
174 | 0 | frame.sp = i_sp; |
175 | 0 | frame.memory = i_memory; |
176 | 0 | frame.call.function = i_function; |
177 | 0 | frame.call.r0 = i_r0; |
178 | 0 | # if d_m3HasFloat |
179 | 0 | frame.call.fp0 = i_fp0; |
180 | 0 | # endif |
181 | |
|
182 | 0 | return Continuation_RecordFrame(i_runtime, &frame); |
183 | 0 | } |
184 | | |
185 | | # define d_m3RecordCallFrame(MEMORY, FUNCTION) \ |
186 | 132k | if (M3_UNLIKELY (r == m3Err_continuationSuspended)) { \ |
187 | 0 | return RecordCallFrame (m3MemRuntime (_mem), _pc, _sp, (MEMORY), \ |
188 | 0 | (FUNCTION), d_m3ExpRegArgs (_r0, _fp0)); \ |
189 | 0 | } |
190 | | |
191 | | |
192 | | // op_Loop and op_TryTable hold native frames across their bodies and nest as |
193 | | // deeply as the Wasm does, so they keep their frames out of this too. |
194 | | static M3_NOINLINE |
195 | | m3ret_t RecordLoopFrame (IM3Runtime i_runtime, pc_t i_pc, m3stack_t i_sp, IM3Memory i_memory) |
196 | 0 | { |
197 | 0 | M3Frame frame; |
198 | |
|
199 | 0 | frame.kind = frame_loop; |
200 | 0 | frame.pc = i_pc; |
201 | 0 | frame.sp = i_sp; |
202 | 0 | frame.memory = i_memory; |
203 | |
|
204 | 0 | return Continuation_RecordFrame(i_runtime, &frame); |
205 | 0 | } |
206 | | |
207 | | |
208 | | # if d_m3HasExceptionHandling |
209 | | static M3_NOINLINE |
210 | | m3ret_t RecordTryFrame (IM3Runtime i_runtime, pc_t i_clauses, m3stack_t i_sp, IM3Memory i_memory, |
211 | | u32 i_numClauses, bool i_handlersLive) |
212 | 0 | { |
213 | 0 | M3Frame frame; |
214 | |
|
215 | 0 | frame.kind = frame_try; |
216 | 0 | frame.pc = i_clauses; |
217 | 0 | frame.sp = i_sp; |
218 | 0 | frame.memory = i_memory; |
219 | 0 | frame.try_.numClauses = i_numClauses; |
220 | 0 | frame.try_.handlersLive = i_handlersLive; |
221 | |
|
222 | 0 | return Continuation_RecordFrame(i_runtime, &frame); |
223 | 0 | } |
224 | | # endif |
225 | | |
226 | | |
227 | | # if d_m3EntryKeepsFrame |
228 | | static M3_NOINLINE |
229 | | m3ret_t RecordEntryFrame (IM3Runtime i_runtime, pc_t i_pc, m3stack_t i_sp, IM3Memory i_memory, |
230 | | IM3Function i_function) |
231 | | { |
232 | | M3Frame frame; |
233 | | |
234 | | frame.kind = frame_entry; |
235 | | frame.pc = i_pc; |
236 | | frame.sp = i_sp; |
237 | | frame.memory = i_memory; |
238 | | frame.entry.function = i_function; |
239 | | |
240 | | return Continuation_RecordFrame(i_runtime, &frame); |
241 | | } |
242 | | # endif |
243 | | #else |
244 | | # define d_m3RecordCallFrame(MEMORY, FUNCTION) |
245 | | #endif |
246 | | |
247 | | |
248 | | #if d_m3EnableStrace == 1 |
249 | | // Flat trace |
250 | | # define d_m3TracePrepare |
251 | | # define d_m3TracePrint(fmt, ...) fprintf(stderr, fmt "\n", ##__VA_ARGS__) |
252 | | #elif d_m3EnableStrace >= 2 |
253 | | // Structured trace |
254 | | # define d_m3TracePrepare const IM3Runtime trace_rt = m3MemRuntime(_mem); (void) trace_rt; |
255 | | # define d_m3TracePrint(fmt, ...) fprintf(stderr, "%*s" fmt "\n", (trace_rt->callDepth)*2, "", ##__VA_ARGS__) |
256 | | #else |
257 | | # define d_m3TracePrepare |
258 | | # define d_m3TracePrint(fmt, ...) |
259 | | #endif |
260 | | |
261 | | #if d_m3EnableStrace >= 3 |
262 | | # define d_m3TraceLoad(TYPE,offset,val) d_m3TracePrint("load." #TYPE " 0x%x = %" PRI##TYPE, offset, val) |
263 | | # define d_m3TraceStore(TYPE,offset,val) d_m3TracePrint("store." #TYPE " 0x%x , %" PRI##TYPE, offset, val) |
264 | | #else |
265 | | # define d_m3TraceLoad(TYPE,offset,val) |
266 | | # define d_m3TraceStore(TYPE,offset,val) |
267 | | #endif |
268 | | |
269 | | #ifdef DEBUG |
270 | | #define d_outOfBounds newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ |
271 | | _mem->runtime, "memory size: %zu; access offset: %zu", \ |
272 | | _mem->length, operand)) |
273 | | |
274 | | # define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (ErrorRuntime (m3Err_trapOutOfBoundsMemoryAccess, \ |
275 | | _mem->runtime, "memory size: %zu; access offset: %zu; size: %u", \ |
276 | | _mem->length, OFFSET, SIZE)) |
277 | | #else |
278 | 100 | #define d_outOfBounds newTrap (m3Err_trapOutOfBoundsMemoryAccess) |
279 | | |
280 | 455 | # define d_outOfBoundsMemOp(OFFSET, SIZE) newTrap (m3Err_trapOutOfBoundsMemoryAccess) |
281 | | |
282 | | #endif |
283 | | |
284 | | #if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
285 | | d_m3RetSig Call (d_m3OpSig, cstr_t i_operationName) |
286 | | #else |
287 | | d_m3RetSig Call (d_m3OpSig) |
288 | | #endif |
289 | 133k | { |
290 | 133k | m3ret_t possible_trap = m3_Yield(); |
291 | 133k | if (M3_UNLIKELY(possible_trap)) { |
292 | 0 | return possible_trap; |
293 | 0 | } |
294 | | |
295 | 133k | nextOpDirect(); |
296 | 133k | } |
297 | | |
298 | | #define d_m3CommutativeOpMacro(RES, REG, TYPE, NAME, OP, ...) \ |
299 | 71.1M | d_m3Op(TYPE##_##NAME##_rs) \ |
300 | 71.1M | { \ |
301 | 71.1M | TYPE operand = slot (TYPE); \ |
302 | 71.1M | d_m3PreloadNext (); \ |
303 | 71.1M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ |
304 | 71.1M | nextOpPreloaded (); \ |
305 | 27.3k | } \ m3_compile.c:op_i32_Equal_rs Line | Count | Source | 299 | 2.15M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 2.15M | { \ | 301 | 2.15M | TYPE operand = slot (TYPE); \ | 302 | 2.15M | d_m3PreloadNext (); \ | 303 | 2.15M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 2.15M | nextOpPreloaded (); \ | 305 | 2.15M | } \ |
m3_compile.c:op_i32_NotEqual_rs Line | Count | Source | 299 | 1.97M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.97M | { \ | 301 | 1.97M | TYPE operand = slot (TYPE); \ | 302 | 1.97M | d_m3PreloadNext (); \ | 303 | 1.97M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.97M | nextOpPreloaded (); \ | 305 | 1.97M | } \ |
m3_compile.c:op_i32_LessThan_rs Line | Count | Source | 299 | 1.77M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.77M | { \ | 301 | 1.77M | TYPE operand = slot (TYPE); \ | 302 | 1.77M | d_m3PreloadNext (); \ | 303 | 1.77M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.77M | nextOpPreloaded (); \ | 305 | 1.77M | } \ |
m3_compile.c:op_u32_LessThan_rs Line | Count | Source | 299 | 1.63M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.63M | { \ | 301 | 1.63M | TYPE operand = slot (TYPE); \ | 302 | 1.63M | d_m3PreloadNext (); \ | 303 | 1.63M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.63M | nextOpPreloaded (); \ | 305 | 1.63M | } \ |
m3_compile.c:op_i32_GreaterThan_rs Line | Count | Source | 299 | 1.48M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.48M | { \ | 301 | 1.48M | TYPE operand = slot (TYPE); \ | 302 | 1.48M | d_m3PreloadNext (); \ | 303 | 1.48M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.48M | nextOpPreloaded (); \ | 305 | 1.48M | } \ |
m3_compile.c:op_u32_GreaterThan_rs Line | Count | Source | 299 | 1.63M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.63M | { \ | 301 | 1.63M | TYPE operand = slot (TYPE); \ | 302 | 1.63M | d_m3PreloadNext (); \ | 303 | 1.63M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.63M | nextOpPreloaded (); \ | 305 | 1.63M | } \ |
m3_compile.c:op_i32_LessThanOrEqual_rs Line | Count | Source | 299 | 2.13M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 2.13M | { \ | 301 | 2.13M | TYPE operand = slot (TYPE); \ | 302 | 2.13M | d_m3PreloadNext (); \ | 303 | 2.13M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 2.13M | nextOpPreloaded (); \ | 305 | 2.13M | } \ |
m3_compile.c:op_u32_LessThanOrEqual_rs Line | Count | Source | 299 | 2.34M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 2.34M | { \ | 301 | 2.34M | TYPE operand = slot (TYPE); \ | 302 | 2.34M | d_m3PreloadNext (); \ | 303 | 2.34M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 2.34M | nextOpPreloaded (); \ | 305 | 2.34M | } \ |
m3_compile.c:op_i32_GreaterThanOrEqual_rs Line | Count | Source | 299 | 1.67M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.67M | { \ | 301 | 1.67M | TYPE operand = slot (TYPE); \ | 302 | 1.67M | d_m3PreloadNext (); \ | 303 | 1.67M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.67M | nextOpPreloaded (); \ | 305 | 1.67M | } \ |
m3_compile.c:op_u32_GreaterThanOrEqual_rs Line | Count | Source | 299 | 1.75M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.75M | { \ | 301 | 1.75M | TYPE operand = slot (TYPE); \ | 302 | 1.75M | d_m3PreloadNext (); \ | 303 | 1.75M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.75M | nextOpPreloaded (); \ | 305 | 1.75M | } \ |
m3_compile.c:op_i64_Equal_rs Line | Count | Source | 299 | 1.35M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.35M | { \ | 301 | 1.35M | TYPE operand = slot (TYPE); \ | 302 | 1.35M | d_m3PreloadNext (); \ | 303 | 1.35M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.35M | nextOpPreloaded (); \ | 305 | 1.35M | } \ |
m3_compile.c:op_i64_NotEqual_rs Line | Count | Source | 299 | 1.20M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.20M | { \ | 301 | 1.20M | TYPE operand = slot (TYPE); \ | 302 | 1.20M | d_m3PreloadNext (); \ | 303 | 1.20M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.20M | nextOpPreloaded (); \ | 305 | 1.20M | } \ |
m3_compile.c:op_i64_LessThan_rs Line | Count | Source | 299 | 1.53M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.53M | { \ | 301 | 1.53M | TYPE operand = slot (TYPE); \ | 302 | 1.53M | d_m3PreloadNext (); \ | 303 | 1.53M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.53M | nextOpPreloaded (); \ | 305 | 1.53M | } \ |
m3_compile.c:op_u64_LessThan_rs Line | Count | Source | 299 | 1.54M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.54M | { \ | 301 | 1.54M | TYPE operand = slot (TYPE); \ | 302 | 1.54M | d_m3PreloadNext (); \ | 303 | 1.54M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.54M | nextOpPreloaded (); \ | 305 | 1.54M | } \ |
m3_compile.c:op_i64_GreaterThan_rs Line | Count | Source | 299 | 1.23M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.23M | { \ | 301 | 1.23M | TYPE operand = slot (TYPE); \ | 302 | 1.23M | d_m3PreloadNext (); \ | 303 | 1.23M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.23M | nextOpPreloaded (); \ | 305 | 1.23M | } \ |
m3_compile.c:op_u64_GreaterThan_rs Line | Count | Source | 299 | 1.17M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.17M | { \ | 301 | 1.17M | TYPE operand = slot (TYPE); \ | 302 | 1.17M | d_m3PreloadNext (); \ | 303 | 1.17M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.17M | nextOpPreloaded (); \ | 305 | 1.17M | } \ |
m3_compile.c:op_i64_LessThanOrEqual_rs Line | Count | Source | 299 | 1.71M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.71M | { \ | 301 | 1.71M | TYPE operand = slot (TYPE); \ | 302 | 1.71M | d_m3PreloadNext (); \ | 303 | 1.71M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.71M | nextOpPreloaded (); \ | 305 | 1.71M | } \ |
m3_compile.c:op_u64_LessThanOrEqual_rs Line | Count | Source | 299 | 1.12M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.12M | { \ | 301 | 1.12M | TYPE operand = slot (TYPE); \ | 302 | 1.12M | d_m3PreloadNext (); \ | 303 | 1.12M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.12M | nextOpPreloaded (); \ | 305 | 1.12M | } \ |
m3_compile.c:op_i64_GreaterThanOrEqual_rs Line | Count | Source | 299 | 924k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 924k | { \ | 301 | 924k | TYPE operand = slot (TYPE); \ | 302 | 924k | d_m3PreloadNext (); \ | 303 | 924k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 924k | nextOpPreloaded (); \ | 305 | 924k | } \ |
m3_compile.c:op_u64_GreaterThanOrEqual_rs Line | Count | Source | 299 | 1.05M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.05M | { \ | 301 | 1.05M | TYPE operand = slot (TYPE); \ | 302 | 1.05M | d_m3PreloadNext (); \ | 303 | 1.05M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.05M | nextOpPreloaded (); \ | 305 | 1.05M | } \ |
m3_compile.c:op_f32_Equal_rs Line | Count | Source | 299 | 642k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 642k | { \ | 301 | 642k | TYPE operand = slot (TYPE); \ | 302 | 642k | d_m3PreloadNext (); \ | 303 | 642k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 642k | nextOpPreloaded (); \ | 305 | 642k | } \ |
m3_compile.c:op_f32_NotEqual_rs Line | Count | Source | 299 | 830k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 830k | { \ | 301 | 830k | TYPE operand = slot (TYPE); \ | 302 | 830k | d_m3PreloadNext (); \ | 303 | 830k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 830k | nextOpPreloaded (); \ | 305 | 830k | } \ |
m3_compile.c:op_f32_LessThan_rs Line | Count | Source | 299 | 367k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 367k | { \ | 301 | 367k | TYPE operand = slot (TYPE); \ | 302 | 367k | d_m3PreloadNext (); \ | 303 | 367k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 367k | nextOpPreloaded (); \ | 305 | 367k | } \ |
m3_compile.c:op_f32_GreaterThan_rs Line | Count | Source | 299 | 287k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 287k | { \ | 301 | 287k | TYPE operand = slot (TYPE); \ | 302 | 287k | d_m3PreloadNext (); \ | 303 | 287k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 287k | nextOpPreloaded (); \ | 305 | 287k | } \ |
m3_compile.c:op_f32_LessThanOrEqual_rs Line | Count | Source | 299 | 354k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 354k | { \ | 301 | 354k | TYPE operand = slot (TYPE); \ | 302 | 354k | d_m3PreloadNext (); \ | 303 | 354k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 354k | nextOpPreloaded (); \ | 305 | 354k | } \ |
m3_compile.c:op_f32_GreaterThanOrEqual_rs Line | Count | Source | 299 | 323k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 323k | { \ | 301 | 323k | TYPE operand = slot (TYPE); \ | 302 | 323k | d_m3PreloadNext (); \ | 303 | 323k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 323k | nextOpPreloaded (); \ | 305 | 323k | } \ |
m3_compile.c:op_f64_Equal_rs Line | Count | Source | 299 | 349k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 349k | { \ | 301 | 349k | TYPE operand = slot (TYPE); \ | 302 | 349k | d_m3PreloadNext (); \ | 303 | 349k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 349k | nextOpPreloaded (); \ | 305 | 349k | } \ |
m3_compile.c:op_f64_NotEqual_rs Line | Count | Source | 299 | 388k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 388k | { \ | 301 | 388k | TYPE operand = slot (TYPE); \ | 302 | 388k | d_m3PreloadNext (); \ | 303 | 388k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 388k | nextOpPreloaded (); \ | 305 | 388k | } \ |
m3_compile.c:op_f64_LessThan_rs Line | Count | Source | 299 | 338k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 338k | { \ | 301 | 338k | TYPE operand = slot (TYPE); \ | 302 | 338k | d_m3PreloadNext (); \ | 303 | 338k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 338k | nextOpPreloaded (); \ | 305 | 338k | } \ |
m3_compile.c:op_f64_GreaterThan_rs Line | Count | Source | 299 | 415k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 415k | { \ | 301 | 415k | TYPE operand = slot (TYPE); \ | 302 | 415k | d_m3PreloadNext (); \ | 303 | 415k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 415k | nextOpPreloaded (); \ | 305 | 415k | } \ |
m3_compile.c:op_f64_LessThanOrEqual_rs Line | Count | Source | 299 | 281k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 281k | { \ | 301 | 281k | TYPE operand = slot (TYPE); \ | 302 | 281k | d_m3PreloadNext (); \ | 303 | 281k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 281k | nextOpPreloaded (); \ | 305 | 281k | } \ |
m3_compile.c:op_f64_GreaterThanOrEqual_rs Line | Count | Source | 299 | 453k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 453k | { \ | 301 | 453k | TYPE operand = slot (TYPE); \ | 302 | 453k | d_m3PreloadNext (); \ | 303 | 453k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 453k | nextOpPreloaded (); \ | 305 | 453k | } \ |
m3_compile.c:op_i32_Add_rs Line | Count | Source | 299 | 1.81M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.81M | { \ | 301 | 1.81M | TYPE operand = slot (TYPE); \ | 302 | 1.81M | d_m3PreloadNext (); \ | 303 | 1.81M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.81M | nextOpPreloaded (); \ | 305 | 1.81M | } \ |
m3_compile.c:op_i32_Subtract_rs Line | Count | Source | 299 | 1.12M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.12M | { \ | 301 | 1.12M | TYPE operand = slot (TYPE); \ | 302 | 1.12M | d_m3PreloadNext (); \ | 303 | 1.12M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.12M | nextOpPreloaded (); \ | 305 | 1.12M | } \ |
m3_compile.c:op_i32_Multiply_rs Line | Count | Source | 299 | 1.42M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.42M | { \ | 301 | 1.42M | TYPE operand = slot (TYPE); \ | 302 | 1.42M | d_m3PreloadNext (); \ | 303 | 1.42M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.42M | nextOpPreloaded (); \ | 305 | 1.42M | } \ |
m3_compile.c:op_i32_Divide_rs Line | Count | Source | 299 | 11.1k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 11.1k | { \ | 301 | 11.1k | TYPE operand = slot (TYPE); \ | 302 | 11.1k | d_m3PreloadNext (); \ | 303 | 11.1k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 11.1k | nextOpPreloaded (); \ | 305 | 11.1k | } \ |
m3_compile.c:op_u32_Divide_rs Line | Count | Source | 299 | 9.46k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 9.46k | { \ | 301 | 9.46k | TYPE operand = slot (TYPE); \ | 302 | 9.46k | d_m3PreloadNext (); \ | 303 | 9.46k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 9.44k | nextOpPreloaded (); \ | 305 | 9.46k | } \ |
m3_compile.c:op_i32_Remainder_rs Line | Count | Source | 299 | 15.8k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 15.8k | { \ | 301 | 15.8k | TYPE operand = slot (TYPE); \ | 302 | 15.8k | d_m3PreloadNext (); \ | 303 | 15.8k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 15.7k | nextOpPreloaded (); \ | 305 | 15.8k | } \ |
m3_compile.c:op_u32_Remainder_rs Line | Count | Source | 299 | 9.82k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 9.82k | { \ | 301 | 9.82k | TYPE operand = slot (TYPE); \ | 302 | 9.82k | d_m3PreloadNext (); \ | 303 | 9.82k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 9.79k | nextOpPreloaded (); \ | 305 | 9.82k | } \ |
m3_compile.c:op_u32_And_rs Line | Count | Source | 299 | 1.57M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.57M | { \ | 301 | 1.57M | TYPE operand = slot (TYPE); \ | 302 | 1.57M | d_m3PreloadNext (); \ | 303 | 1.57M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.57M | nextOpPreloaded (); \ | 305 | 1.57M | } \ |
m3_compile.c:op_u32_Or_rs Line | Count | Source | 299 | 1.59M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.59M | { \ | 301 | 1.59M | TYPE operand = slot (TYPE); \ | 302 | 1.59M | d_m3PreloadNext (); \ | 303 | 1.59M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.59M | nextOpPreloaded (); \ | 305 | 1.59M | } \ |
m3_compile.c:op_u32_Xor_rs Line | Count | Source | 299 | 1.78M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.78M | { \ | 301 | 1.78M | TYPE operand = slot (TYPE); \ | 302 | 1.78M | d_m3PreloadNext (); \ | 303 | 1.78M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.78M | nextOpPreloaded (); \ | 305 | 1.78M | } \ |
m3_compile.c:op_u32_ShiftLeft_rs Line | Count | Source | 299 | 1.11M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.11M | { \ | 301 | 1.11M | TYPE operand = slot (TYPE); \ | 302 | 1.11M | d_m3PreloadNext (); \ | 303 | 1.11M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.11M | nextOpPreloaded (); \ | 305 | 1.11M | } \ |
m3_compile.c:op_i32_ShiftRight_rs Line | Count | Source | 299 | 862k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 862k | { \ | 301 | 862k | TYPE operand = slot (TYPE); \ | 302 | 862k | d_m3PreloadNext (); \ | 303 | 862k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 862k | nextOpPreloaded (); \ | 305 | 862k | } \ |
m3_compile.c:op_u32_ShiftRight_rs Line | Count | Source | 299 | 656k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 656k | { \ | 301 | 656k | TYPE operand = slot (TYPE); \ | 302 | 656k | d_m3PreloadNext (); \ | 303 | 656k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 656k | nextOpPreloaded (); \ | 305 | 656k | } \ |
m3_compile.c:op_u32_Rotl_rs Line | Count | Source | 299 | 792k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 792k | { \ | 301 | 792k | TYPE operand = slot (TYPE); \ | 302 | 792k | d_m3PreloadNext (); \ | 303 | 792k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 792k | nextOpPreloaded (); \ | 305 | 792k | } \ |
m3_compile.c:op_u32_Rotr_rs Line | Count | Source | 299 | 1.15M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.15M | { \ | 301 | 1.15M | TYPE operand = slot (TYPE); \ | 302 | 1.15M | d_m3PreloadNext (); \ | 303 | 1.15M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.15M | nextOpPreloaded (); \ | 305 | 1.15M | } \ |
m3_compile.c:op_i64_Add_rs Line | Count | Source | 299 | 1.45M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.45M | { \ | 301 | 1.45M | TYPE operand = slot (TYPE); \ | 302 | 1.45M | d_m3PreloadNext (); \ | 303 | 1.45M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.45M | nextOpPreloaded (); \ | 305 | 1.45M | } \ |
m3_compile.c:op_i64_Subtract_rs Line | Count | Source | 299 | 750k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 750k | { \ | 301 | 750k | TYPE operand = slot (TYPE); \ | 302 | 750k | d_m3PreloadNext (); \ | 303 | 750k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 750k | nextOpPreloaded (); \ | 305 | 750k | } \ |
m3_compile.c:op_i64_Multiply_rs Line | Count | Source | 299 | 1.78M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.78M | { \ | 301 | 1.78M | TYPE operand = slot (TYPE); \ | 302 | 1.78M | d_m3PreloadNext (); \ | 303 | 1.78M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.78M | nextOpPreloaded (); \ | 305 | 1.78M | } \ |
m3_compile.c:op_i64_Divide_rs Line | Count | Source | 299 | 16.2k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 16.2k | { \ | 301 | 16.2k | TYPE operand = slot (TYPE); \ | 302 | 16.2k | d_m3PreloadNext (); \ | 303 | 16.2k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 16.2k | nextOpPreloaded (); \ | 305 | 16.2k | } \ |
m3_compile.c:op_u64_Divide_rs Line | Count | Source | 299 | 6.15k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 6.15k | { \ | 301 | 6.15k | TYPE operand = slot (TYPE); \ | 302 | 6.15k | d_m3PreloadNext (); \ | 303 | 6.15k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 6.12k | nextOpPreloaded (); \ | 305 | 6.15k | } \ |
m3_compile.c:op_i64_Remainder_rs Line | Count | Source | 299 | 14.2k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 14.2k | { \ | 301 | 14.2k | TYPE operand = slot (TYPE); \ | 302 | 14.2k | d_m3PreloadNext (); \ | 303 | 14.2k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 14.2k | nextOpPreloaded (); \ | 305 | 14.2k | } \ |
m3_compile.c:op_u64_Remainder_rs Line | Count | Source | 299 | 13.4k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 13.4k | { \ | 301 | 13.4k | TYPE operand = slot (TYPE); \ | 302 | 13.4k | d_m3PreloadNext (); \ | 303 | 13.4k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 13.4k | nextOpPreloaded (); \ | 305 | 13.4k | } \ |
m3_compile.c:op_u64_And_rs Line | Count | Source | 299 | 906k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 906k | { \ | 301 | 906k | TYPE operand = slot (TYPE); \ | 302 | 906k | d_m3PreloadNext (); \ | 303 | 906k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 906k | nextOpPreloaded (); \ | 305 | 906k | } \ |
m3_compile.c:op_u64_Or_rs Line | Count | Source | 299 | 1.03M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.03M | { \ | 301 | 1.03M | TYPE operand = slot (TYPE); \ | 302 | 1.03M | d_m3PreloadNext (); \ | 303 | 1.03M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.03M | nextOpPreloaded (); \ | 305 | 1.03M | } \ |
m3_compile.c:op_u64_Xor_rs Line | Count | Source | 299 | 1.18M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.18M | { \ | 301 | 1.18M | TYPE operand = slot (TYPE); \ | 302 | 1.18M | d_m3PreloadNext (); \ | 303 | 1.18M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.18M | nextOpPreloaded (); \ | 305 | 1.18M | } \ |
m3_compile.c:op_u64_ShiftLeft_rs Line | Count | Source | 299 | 1.05M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.05M | { \ | 301 | 1.05M | TYPE operand = slot (TYPE); \ | 302 | 1.05M | d_m3PreloadNext (); \ | 303 | 1.05M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.05M | nextOpPreloaded (); \ | 305 | 1.05M | } \ |
m3_compile.c:op_i64_ShiftRight_rs Line | Count | Source | 299 | 531k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 531k | { \ | 301 | 531k | TYPE operand = slot (TYPE); \ | 302 | 531k | d_m3PreloadNext (); \ | 303 | 531k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 531k | nextOpPreloaded (); \ | 305 | 531k | } \ |
m3_compile.c:op_u64_ShiftRight_rs Line | Count | Source | 299 | 897k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 897k | { \ | 301 | 897k | TYPE operand = slot (TYPE); \ | 302 | 897k | d_m3PreloadNext (); \ | 303 | 897k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 897k | nextOpPreloaded (); \ | 305 | 897k | } \ |
m3_compile.c:op_u64_Rotl_rs Line | Count | Source | 299 | 856k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 856k | { \ | 301 | 856k | TYPE operand = slot (TYPE); \ | 302 | 856k | d_m3PreloadNext (); \ | 303 | 856k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 856k | nextOpPreloaded (); \ | 305 | 856k | } \ |
m3_compile.c:op_u64_Rotr_rs Line | Count | Source | 299 | 802k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 802k | { \ | 301 | 802k | TYPE operand = slot (TYPE); \ | 302 | 802k | d_m3PreloadNext (); \ | 303 | 802k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 802k | nextOpPreloaded (); \ | 305 | 802k | } \ |
m3_compile.c:op_f32_Add_rs Line | Count | Source | 299 | 675k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 675k | { \ | 301 | 675k | TYPE operand = slot (TYPE); \ | 302 | 675k | d_m3PreloadNext (); \ | 303 | 675k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 675k | nextOpPreloaded (); \ | 305 | 675k | } \ |
m3_compile.c:op_f32_Subtract_rs Line | Count | Source | 299 | 592k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 592k | { \ | 301 | 592k | TYPE operand = slot (TYPE); \ | 302 | 592k | d_m3PreloadNext (); \ | 303 | 592k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 592k | nextOpPreloaded (); \ | 305 | 592k | } \ |
m3_compile.c:op_f32_Multiply_rs Line | Count | Source | 299 | 512k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 512k | { \ | 301 | 512k | TYPE operand = slot (TYPE); \ | 302 | 512k | d_m3PreloadNext (); \ | 303 | 512k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 512k | nextOpPreloaded (); \ | 305 | 512k | } \ |
m3_compile.c:op_f32_Divide_rs Line | Count | Source | 299 | 4.90k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 4.90k | { \ | 301 | 4.90k | TYPE operand = slot (TYPE); \ | 302 | 4.90k | d_m3PreloadNext (); \ | 303 | 4.90k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 4.90k | nextOpPreloaded (); \ | 305 | 4.90k | } \ |
m3_compile.c:op_f32_Min_rs Line | Count | Source | 299 | 1.58M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.58M | { \ | 301 | 1.58M | TYPE operand = slot (TYPE); \ | 302 | 1.58M | d_m3PreloadNext (); \ | 303 | 1.58M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.58M | nextOpPreloaded (); \ | 305 | 1.58M | } \ |
m3_compile.c:op_f32_Max_rs Line | Count | Source | 299 | 1.81M | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 1.81M | { \ | 301 | 1.81M | TYPE operand = slot (TYPE); \ | 302 | 1.81M | d_m3PreloadNext (); \ | 303 | 1.81M | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 1.81M | nextOpPreloaded (); \ | 305 | 1.81M | } \ |
m3_compile.c:op_f32_CopySign_rs Line | Count | Source | 299 | 318k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 318k | { \ | 301 | 318k | TYPE operand = slot (TYPE); \ | 302 | 318k | d_m3PreloadNext (); \ | 303 | 318k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 318k | nextOpPreloaded (); \ | 305 | 318k | } \ |
m3_compile.c:op_f64_Add_rs Line | Count | Source | 299 | 577k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 577k | { \ | 301 | 577k | TYPE operand = slot (TYPE); \ | 302 | 577k | d_m3PreloadNext (); \ | 303 | 577k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 577k | nextOpPreloaded (); \ | 305 | 577k | } \ |
m3_compile.c:op_f64_Subtract_rs Line | Count | Source | 299 | 553k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 553k | { \ | 301 | 553k | TYPE operand = slot (TYPE); \ | 302 | 553k | d_m3PreloadNext (); \ | 303 | 553k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 553k | nextOpPreloaded (); \ | 305 | 553k | } \ |
m3_compile.c:op_f64_Multiply_rs Line | Count | Source | 299 | 662k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 662k | { \ | 301 | 662k | TYPE operand = slot (TYPE); \ | 302 | 662k | d_m3PreloadNext (); \ | 303 | 662k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 662k | nextOpPreloaded (); \ | 305 | 662k | } \ |
m3_compile.c:op_f64_Divide_rs Line | Count | Source | 299 | 5.21k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 5.21k | { \ | 301 | 5.21k | TYPE operand = slot (TYPE); \ | 302 | 5.21k | d_m3PreloadNext (); \ | 303 | 5.21k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 5.21k | nextOpPreloaded (); \ | 305 | 5.21k | } \ |
m3_compile.c:op_f64_Min_rs Line | Count | Source | 299 | 942k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 942k | { \ | 301 | 942k | TYPE operand = slot (TYPE); \ | 302 | 942k | d_m3PreloadNext (); \ | 303 | 942k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 942k | nextOpPreloaded (); \ | 305 | 942k | } \ |
m3_compile.c:op_f64_Max_rs Line | Count | Source | 299 | 932k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 932k | { \ | 301 | 932k | TYPE operand = slot (TYPE); \ | 302 | 932k | d_m3PreloadNext (); \ | 303 | 932k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 932k | nextOpPreloaded (); \ | 305 | 932k | } \ |
m3_compile.c:op_f64_CopySign_rs Line | Count | Source | 299 | 176k | d_m3Op(TYPE##_##NAME##_rs) \ | 300 | 176k | { \ | 301 | 176k | TYPE operand = slot (TYPE); \ | 302 | 176k | d_m3PreloadNext (); \ | 303 | 176k | OP((RES), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 304 | 176k | nextOpPreloaded (); \ | 305 | 176k | } \ |
|
306 | 101M | d_m3Op(TYPE##_##NAME##_ss) \ |
307 | 101M | { \ |
308 | 101M | TYPE operand2 = slot (TYPE); \ |
309 | 101M | TYPE operand1 = slot (TYPE); \ |
310 | 101M | d_m3PreloadNext (); \ |
311 | 101M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ |
312 | 101M | nextOpPreloaded (); \ |
313 | 47.3k | } m3_compile.c:op_i32_Equal_ss Line | Count | Source | 306 | 2.19M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.19M | { \ | 308 | 2.19M | TYPE operand2 = slot (TYPE); \ | 309 | 2.19M | TYPE operand1 = slot (TYPE); \ | 310 | 2.19M | d_m3PreloadNext (); \ | 311 | 2.19M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.19M | nextOpPreloaded (); \ | 313 | 2.19M | } |
m3_compile.c:op_i32_NotEqual_ss Line | Count | Source | 306 | 2.06M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.06M | { \ | 308 | 2.06M | TYPE operand2 = slot (TYPE); \ | 309 | 2.06M | TYPE operand1 = slot (TYPE); \ | 310 | 2.06M | d_m3PreloadNext (); \ | 311 | 2.06M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.06M | nextOpPreloaded (); \ | 313 | 2.06M | } |
m3_compile.c:op_i32_LessThan_ss Line | Count | Source | 306 | 2.69M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.69M | { \ | 308 | 2.69M | TYPE operand2 = slot (TYPE); \ | 309 | 2.69M | TYPE operand1 = slot (TYPE); \ | 310 | 2.69M | d_m3PreloadNext (); \ | 311 | 2.69M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.69M | nextOpPreloaded (); \ | 313 | 2.69M | } |
m3_compile.c:op_u32_LessThan_ss Line | Count | Source | 306 | 3.15M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 3.15M | { \ | 308 | 3.15M | TYPE operand2 = slot (TYPE); \ | 309 | 3.15M | TYPE operand1 = slot (TYPE); \ | 310 | 3.15M | d_m3PreloadNext (); \ | 311 | 3.15M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 3.15M | nextOpPreloaded (); \ | 313 | 3.15M | } |
m3_compile.c:op_i32_GreaterThan_ss Line | Count | Source | 306 | 2.19M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.19M | { \ | 308 | 2.19M | TYPE operand2 = slot (TYPE); \ | 309 | 2.19M | TYPE operand1 = slot (TYPE); \ | 310 | 2.19M | d_m3PreloadNext (); \ | 311 | 2.19M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.19M | nextOpPreloaded (); \ | 313 | 2.19M | } |
m3_compile.c:op_u32_GreaterThan_ss Line | Count | Source | 306 | 2.14M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.14M | { \ | 308 | 2.14M | TYPE operand2 = slot (TYPE); \ | 309 | 2.14M | TYPE operand1 = slot (TYPE); \ | 310 | 2.14M | d_m3PreloadNext (); \ | 311 | 2.14M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.14M | nextOpPreloaded (); \ | 313 | 2.14M | } |
m3_compile.c:op_i32_LessThanOrEqual_ss Line | Count | Source | 306 | 3.68M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 3.68M | { \ | 308 | 3.68M | TYPE operand2 = slot (TYPE); \ | 309 | 3.68M | TYPE operand1 = slot (TYPE); \ | 310 | 3.68M | d_m3PreloadNext (); \ | 311 | 3.68M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 3.68M | nextOpPreloaded (); \ | 313 | 3.68M | } |
m3_compile.c:op_u32_LessThanOrEqual_ss Line | Count | Source | 306 | 2.40M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.40M | { \ | 308 | 2.40M | TYPE operand2 = slot (TYPE); \ | 309 | 2.40M | TYPE operand1 = slot (TYPE); \ | 310 | 2.40M | d_m3PreloadNext (); \ | 311 | 2.40M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.40M | nextOpPreloaded (); \ | 313 | 2.40M | } |
m3_compile.c:op_i32_GreaterThanOrEqual_ss Line | Count | Source | 306 | 3.33M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 3.33M | { \ | 308 | 3.33M | TYPE operand2 = slot (TYPE); \ | 309 | 3.33M | TYPE operand1 = slot (TYPE); \ | 310 | 3.33M | d_m3PreloadNext (); \ | 311 | 3.33M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 3.33M | nextOpPreloaded (); \ | 313 | 3.33M | } |
m3_compile.c:op_u32_GreaterThanOrEqual_ss Line | Count | Source | 306 | 1.98M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.98M | { \ | 308 | 1.98M | TYPE operand2 = slot (TYPE); \ | 309 | 1.98M | TYPE operand1 = slot (TYPE); \ | 310 | 1.98M | d_m3PreloadNext (); \ | 311 | 1.98M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.98M | nextOpPreloaded (); \ | 313 | 1.98M | } |
m3_compile.c:op_i64_Equal_ss Line | Count | Source | 306 | 1.36M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.36M | { \ | 308 | 1.36M | TYPE operand2 = slot (TYPE); \ | 309 | 1.36M | TYPE operand1 = slot (TYPE); \ | 310 | 1.36M | d_m3PreloadNext (); \ | 311 | 1.36M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.36M | nextOpPreloaded (); \ | 313 | 1.36M | } |
m3_compile.c:op_i64_NotEqual_ss Line | Count | Source | 306 | 2.10M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.10M | { \ | 308 | 2.10M | TYPE operand2 = slot (TYPE); \ | 309 | 2.10M | TYPE operand1 = slot (TYPE); \ | 310 | 2.10M | d_m3PreloadNext (); \ | 311 | 2.10M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.10M | nextOpPreloaded (); \ | 313 | 2.10M | } |
m3_compile.c:op_i64_LessThan_ss Line | Count | Source | 306 | 1.83M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.83M | { \ | 308 | 1.83M | TYPE operand2 = slot (TYPE); \ | 309 | 1.83M | TYPE operand1 = slot (TYPE); \ | 310 | 1.83M | d_m3PreloadNext (); \ | 311 | 1.83M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.83M | nextOpPreloaded (); \ | 313 | 1.83M | } |
m3_compile.c:op_u64_LessThan_ss Line | Count | Source | 306 | 2.34M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.34M | { \ | 308 | 2.34M | TYPE operand2 = slot (TYPE); \ | 309 | 2.34M | TYPE operand1 = slot (TYPE); \ | 310 | 2.34M | d_m3PreloadNext (); \ | 311 | 2.34M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.34M | nextOpPreloaded (); \ | 313 | 2.34M | } |
m3_compile.c:op_i64_GreaterThan_ss Line | Count | Source | 306 | 2.20M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.20M | { \ | 308 | 2.20M | TYPE operand2 = slot (TYPE); \ | 309 | 2.20M | TYPE operand1 = slot (TYPE); \ | 310 | 2.20M | d_m3PreloadNext (); \ | 311 | 2.20M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.20M | nextOpPreloaded (); \ | 313 | 2.20M | } |
m3_compile.c:op_u64_GreaterThan_ss Line | Count | Source | 306 | 1.70M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.70M | { \ | 308 | 1.70M | TYPE operand2 = slot (TYPE); \ | 309 | 1.70M | TYPE operand1 = slot (TYPE); \ | 310 | 1.70M | d_m3PreloadNext (); \ | 311 | 1.70M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.70M | nextOpPreloaded (); \ | 313 | 1.70M | } |
m3_compile.c:op_i64_LessThanOrEqual_ss Line | Count | Source | 306 | 1.66M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.66M | { \ | 308 | 1.66M | TYPE operand2 = slot (TYPE); \ | 309 | 1.66M | TYPE operand1 = slot (TYPE); \ | 310 | 1.66M | d_m3PreloadNext (); \ | 311 | 1.66M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.66M | nextOpPreloaded (); \ | 313 | 1.66M | } |
m3_compile.c:op_u64_LessThanOrEqual_ss Line | Count | Source | 306 | 2.80M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.80M | { \ | 308 | 2.80M | TYPE operand2 = slot (TYPE); \ | 309 | 2.80M | TYPE operand1 = slot (TYPE); \ | 310 | 2.80M | d_m3PreloadNext (); \ | 311 | 2.80M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.80M | nextOpPreloaded (); \ | 313 | 2.80M | } |
m3_compile.c:op_i64_GreaterThanOrEqual_ss Line | Count | Source | 306 | 1.65M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.65M | { \ | 308 | 1.65M | TYPE operand2 = slot (TYPE); \ | 309 | 1.65M | TYPE operand1 = slot (TYPE); \ | 310 | 1.65M | d_m3PreloadNext (); \ | 311 | 1.65M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.65M | nextOpPreloaded (); \ | 313 | 1.65M | } |
m3_compile.c:op_u64_GreaterThanOrEqual_ss Line | Count | Source | 306 | 2.46M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.46M | { \ | 308 | 2.46M | TYPE operand2 = slot (TYPE); \ | 309 | 2.46M | TYPE operand1 = slot (TYPE); \ | 310 | 2.46M | d_m3PreloadNext (); \ | 311 | 2.46M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.46M | nextOpPreloaded (); \ | 313 | 2.46M | } |
m3_compile.c:op_f32_Equal_ss Line | Count | Source | 306 | 590k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 590k | { \ | 308 | 590k | TYPE operand2 = slot (TYPE); \ | 309 | 590k | TYPE operand1 = slot (TYPE); \ | 310 | 590k | d_m3PreloadNext (); \ | 311 | 590k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 590k | nextOpPreloaded (); \ | 313 | 590k | } |
m3_compile.c:op_f32_NotEqual_ss Line | Count | Source | 306 | 508k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 508k | { \ | 308 | 508k | TYPE operand2 = slot (TYPE); \ | 309 | 508k | TYPE operand1 = slot (TYPE); \ | 310 | 508k | d_m3PreloadNext (); \ | 311 | 508k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 508k | nextOpPreloaded (); \ | 313 | 508k | } |
m3_compile.c:op_f32_LessThan_ss Line | Count | Source | 306 | 723k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 723k | { \ | 308 | 723k | TYPE operand2 = slot (TYPE); \ | 309 | 723k | TYPE operand1 = slot (TYPE); \ | 310 | 723k | d_m3PreloadNext (); \ | 311 | 723k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 723k | nextOpPreloaded (); \ | 313 | 723k | } |
m3_compile.c:op_f32_GreaterThan_ss Line | Count | Source | 306 | 601k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 601k | { \ | 308 | 601k | TYPE operand2 = slot (TYPE); \ | 309 | 601k | TYPE operand1 = slot (TYPE); \ | 310 | 601k | d_m3PreloadNext (); \ | 311 | 601k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 601k | nextOpPreloaded (); \ | 313 | 601k | } |
m3_compile.c:op_f32_LessThanOrEqual_ss Line | Count | Source | 306 | 702k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 702k | { \ | 308 | 702k | TYPE operand2 = slot (TYPE); \ | 309 | 702k | TYPE operand1 = slot (TYPE); \ | 310 | 702k | d_m3PreloadNext (); \ | 311 | 702k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 702k | nextOpPreloaded (); \ | 313 | 702k | } |
m3_compile.c:op_f32_GreaterThanOrEqual_ss Line | Count | Source | 306 | 573k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 573k | { \ | 308 | 573k | TYPE operand2 = slot (TYPE); \ | 309 | 573k | TYPE operand1 = slot (TYPE); \ | 310 | 573k | d_m3PreloadNext (); \ | 311 | 573k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 573k | nextOpPreloaded (); \ | 313 | 573k | } |
m3_compile.c:op_f64_Equal_ss Line | Count | Source | 306 | 398k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 398k | { \ | 308 | 398k | TYPE operand2 = slot (TYPE); \ | 309 | 398k | TYPE operand1 = slot (TYPE); \ | 310 | 398k | d_m3PreloadNext (); \ | 311 | 398k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 398k | nextOpPreloaded (); \ | 313 | 398k | } |
m3_compile.c:op_f64_NotEqual_ss Line | Count | Source | 306 | 535k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 535k | { \ | 308 | 535k | TYPE operand2 = slot (TYPE); \ | 309 | 535k | TYPE operand1 = slot (TYPE); \ | 310 | 535k | d_m3PreloadNext (); \ | 311 | 535k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 535k | nextOpPreloaded (); \ | 313 | 535k | } |
m3_compile.c:op_f64_LessThan_ss Line | Count | Source | 306 | 361k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 361k | { \ | 308 | 361k | TYPE operand2 = slot (TYPE); \ | 309 | 361k | TYPE operand1 = slot (TYPE); \ | 310 | 361k | d_m3PreloadNext (); \ | 311 | 361k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 361k | nextOpPreloaded (); \ | 313 | 361k | } |
m3_compile.c:op_f64_GreaterThan_ss Line | Count | Source | 306 | 433k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 433k | { \ | 308 | 433k | TYPE operand2 = slot (TYPE); \ | 309 | 433k | TYPE operand1 = slot (TYPE); \ | 310 | 433k | d_m3PreloadNext (); \ | 311 | 433k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 433k | nextOpPreloaded (); \ | 313 | 433k | } |
m3_compile.c:op_f64_LessThanOrEqual_ss Line | Count | Source | 306 | 498k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 498k | { \ | 308 | 498k | TYPE operand2 = slot (TYPE); \ | 309 | 498k | TYPE operand1 = slot (TYPE); \ | 310 | 498k | d_m3PreloadNext (); \ | 311 | 498k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 498k | nextOpPreloaded (); \ | 313 | 498k | } |
m3_compile.c:op_f64_GreaterThanOrEqual_ss Line | Count | Source | 306 | 480k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 480k | { \ | 308 | 480k | TYPE operand2 = slot (TYPE); \ | 309 | 480k | TYPE operand1 = slot (TYPE); \ | 310 | 480k | d_m3PreloadNext (); \ | 311 | 480k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 480k | nextOpPreloaded (); \ | 313 | 480k | } |
m3_compile.c:op_i32_Add_ss Line | Count | Source | 306 | 1.89M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.89M | { \ | 308 | 1.89M | TYPE operand2 = slot (TYPE); \ | 309 | 1.89M | TYPE operand1 = slot (TYPE); \ | 310 | 1.89M | d_m3PreloadNext (); \ | 311 | 1.89M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.89M | nextOpPreloaded (); \ | 313 | 1.89M | } |
m3_compile.c:op_i32_Subtract_ss Line | Count | Source | 306 | 1.64M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.64M | { \ | 308 | 1.64M | TYPE operand2 = slot (TYPE); \ | 309 | 1.64M | TYPE operand1 = slot (TYPE); \ | 310 | 1.64M | d_m3PreloadNext (); \ | 311 | 1.64M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.64M | nextOpPreloaded (); \ | 313 | 1.64M | } |
m3_compile.c:op_i32_Multiply_ss Line | Count | Source | 306 | 2.14M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.14M | { \ | 308 | 2.14M | TYPE operand2 = slot (TYPE); \ | 309 | 2.14M | TYPE operand1 = slot (TYPE); \ | 310 | 2.14M | d_m3PreloadNext (); \ | 311 | 2.14M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.14M | nextOpPreloaded (); \ | 313 | 2.14M | } |
m3_compile.c:op_i32_Divide_ss Line | Count | Source | 306 | 20.0k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 20.0k | { \ | 308 | 20.0k | TYPE operand2 = slot (TYPE); \ | 309 | 20.0k | TYPE operand1 = slot (TYPE); \ | 310 | 20.0k | d_m3PreloadNext (); \ | 311 | 20.0k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 20.0k | nextOpPreloaded (); \ | 313 | 20.0k | } |
m3_compile.c:op_u32_Divide_ss Line | Count | Source | 306 | 17.6k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 17.6k | { \ | 308 | 17.6k | TYPE operand2 = slot (TYPE); \ | 309 | 17.6k | TYPE operand1 = slot (TYPE); \ | 310 | 17.6k | d_m3PreloadNext (); \ | 311 | 17.6k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 17.6k | nextOpPreloaded (); \ | 313 | 17.6k | } |
m3_compile.c:op_i32_Remainder_ss Line | Count | Source | 306 | 20.0k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 20.0k | { \ | 308 | 20.0k | TYPE operand2 = slot (TYPE); \ | 309 | 20.0k | TYPE operand1 = slot (TYPE); \ | 310 | 20.0k | d_m3PreloadNext (); \ | 311 | 20.0k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 19.9k | nextOpPreloaded (); \ | 313 | 20.0k | } |
m3_compile.c:op_u32_Remainder_ss Line | Count | Source | 306 | 16.7k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 16.7k | { \ | 308 | 16.7k | TYPE operand2 = slot (TYPE); \ | 309 | 16.7k | TYPE operand1 = slot (TYPE); \ | 310 | 16.7k | d_m3PreloadNext (); \ | 311 | 16.7k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 16.6k | nextOpPreloaded (); \ | 313 | 16.7k | } |
m3_compile.c:op_u32_And_ss Line | Count | Source | 306 | 1.86M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.86M | { \ | 308 | 1.86M | TYPE operand2 = slot (TYPE); \ | 309 | 1.86M | TYPE operand1 = slot (TYPE); \ | 310 | 1.86M | d_m3PreloadNext (); \ | 311 | 1.86M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.86M | nextOpPreloaded (); \ | 313 | 1.86M | } |
m3_compile.c:op_u32_Or_ss Line | Count | Source | 306 | 1.60M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.60M | { \ | 308 | 1.60M | TYPE operand2 = slot (TYPE); \ | 309 | 1.60M | TYPE operand1 = slot (TYPE); \ | 310 | 1.60M | d_m3PreloadNext (); \ | 311 | 1.60M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.60M | nextOpPreloaded (); \ | 313 | 1.60M | } |
m3_compile.c:op_u32_Xor_ss Line | Count | Source | 306 | 2.53M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.53M | { \ | 308 | 2.53M | TYPE operand2 = slot (TYPE); \ | 309 | 2.53M | TYPE operand1 = slot (TYPE); \ | 310 | 2.53M | d_m3PreloadNext (); \ | 311 | 2.53M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.53M | nextOpPreloaded (); \ | 313 | 2.53M | } |
m3_compile.c:op_u32_ShiftLeft_ss Line | Count | Source | 306 | 1.57M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.57M | { \ | 308 | 1.57M | TYPE operand2 = slot (TYPE); \ | 309 | 1.57M | TYPE operand1 = slot (TYPE); \ | 310 | 1.57M | d_m3PreloadNext (); \ | 311 | 1.57M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.57M | nextOpPreloaded (); \ | 313 | 1.57M | } |
m3_compile.c:op_i32_ShiftRight_ss Line | Count | Source | 306 | 1.19M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.19M | { \ | 308 | 1.19M | TYPE operand2 = slot (TYPE); \ | 309 | 1.19M | TYPE operand1 = slot (TYPE); \ | 310 | 1.19M | d_m3PreloadNext (); \ | 311 | 1.19M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.19M | nextOpPreloaded (); \ | 313 | 1.19M | } |
m3_compile.c:op_u32_ShiftRight_ss Line | Count | Source | 306 | 1.12M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.12M | { \ | 308 | 1.12M | TYPE operand2 = slot (TYPE); \ | 309 | 1.12M | TYPE operand1 = slot (TYPE); \ | 310 | 1.12M | d_m3PreloadNext (); \ | 311 | 1.12M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.12M | nextOpPreloaded (); \ | 313 | 1.12M | } |
m3_compile.c:op_u32_Rotl_ss Line | Count | Source | 306 | 1.50M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.50M | { \ | 308 | 1.50M | TYPE operand2 = slot (TYPE); \ | 309 | 1.50M | TYPE operand1 = slot (TYPE); \ | 310 | 1.50M | d_m3PreloadNext (); \ | 311 | 1.50M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.50M | nextOpPreloaded (); \ | 313 | 1.50M | } |
m3_compile.c:op_u32_Rotr_ss Line | Count | Source | 306 | 2.43M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.43M | { \ | 308 | 2.43M | TYPE operand2 = slot (TYPE); \ | 309 | 2.43M | TYPE operand1 = slot (TYPE); \ | 310 | 2.43M | d_m3PreloadNext (); \ | 311 | 2.43M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.43M | nextOpPreloaded (); \ | 313 | 2.43M | } |
m3_compile.c:op_i64_Add_ss Line | Count | Source | 306 | 2.37M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.37M | { \ | 308 | 2.37M | TYPE operand2 = slot (TYPE); \ | 309 | 2.37M | TYPE operand1 = slot (TYPE); \ | 310 | 2.37M | d_m3PreloadNext (); \ | 311 | 2.37M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.37M | nextOpPreloaded (); \ | 313 | 2.37M | } |
m3_compile.c:op_i64_Subtract_ss Line | Count | Source | 306 | 2.02M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.02M | { \ | 308 | 2.02M | TYPE operand2 = slot (TYPE); \ | 309 | 2.02M | TYPE operand1 = slot (TYPE); \ | 310 | 2.02M | d_m3PreloadNext (); \ | 311 | 2.02M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.02M | nextOpPreloaded (); \ | 313 | 2.02M | } |
m3_compile.c:op_i64_Multiply_ss Line | Count | Source | 306 | 3.48M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 3.48M | { \ | 308 | 3.48M | TYPE operand2 = slot (TYPE); \ | 309 | 3.48M | TYPE operand1 = slot (TYPE); \ | 310 | 3.48M | d_m3PreloadNext (); \ | 311 | 3.48M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 3.48M | nextOpPreloaded (); \ | 313 | 3.48M | } |
m3_compile.c:op_i64_Divide_ss Line | Count | Source | 306 | 27.3k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 27.3k | { \ | 308 | 27.3k | TYPE operand2 = slot (TYPE); \ | 309 | 27.3k | TYPE operand1 = slot (TYPE); \ | 310 | 27.3k | d_m3PreloadNext (); \ | 311 | 27.3k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 27.3k | nextOpPreloaded (); \ | 313 | 27.3k | } |
m3_compile.c:op_u64_Divide_ss Line | Count | Source | 306 | 18.5k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 18.5k | { \ | 308 | 18.5k | TYPE operand2 = slot (TYPE); \ | 309 | 18.5k | TYPE operand1 = slot (TYPE); \ | 310 | 18.5k | d_m3PreloadNext (); \ | 311 | 18.5k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 18.5k | nextOpPreloaded (); \ | 313 | 18.5k | } |
m3_compile.c:op_i64_Remainder_ss Line | Count | Source | 306 | 21.0k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 21.0k | { \ | 308 | 21.0k | TYPE operand2 = slot (TYPE); \ | 309 | 21.0k | TYPE operand1 = slot (TYPE); \ | 310 | 21.0k | d_m3PreloadNext (); \ | 311 | 21.0k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 21.0k | nextOpPreloaded (); \ | 313 | 21.0k | } |
m3_compile.c:op_u64_Remainder_ss Line | Count | Source | 306 | 19.3k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 19.3k | { \ | 308 | 19.3k | TYPE operand2 = slot (TYPE); \ | 309 | 19.3k | TYPE operand1 = slot (TYPE); \ | 310 | 19.3k | d_m3PreloadNext (); \ | 311 | 19.3k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 19.3k | nextOpPreloaded (); \ | 313 | 19.3k | } |
m3_compile.c:op_u64_And_ss Line | Count | Source | 306 | 1.47M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.47M | { \ | 308 | 1.47M | TYPE operand2 = slot (TYPE); \ | 309 | 1.47M | TYPE operand1 = slot (TYPE); \ | 310 | 1.47M | d_m3PreloadNext (); \ | 311 | 1.47M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.47M | nextOpPreloaded (); \ | 313 | 1.47M | } |
m3_compile.c:op_u64_Or_ss Line | Count | Source | 306 | 1.75M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.75M | { \ | 308 | 1.75M | TYPE operand2 = slot (TYPE); \ | 309 | 1.75M | TYPE operand1 = slot (TYPE); \ | 310 | 1.75M | d_m3PreloadNext (); \ | 311 | 1.75M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.75M | nextOpPreloaded (); \ | 313 | 1.75M | } |
m3_compile.c:op_u64_Xor_ss Line | Count | Source | 306 | 1.55M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.55M | { \ | 308 | 1.55M | TYPE operand2 = slot (TYPE); \ | 309 | 1.55M | TYPE operand1 = slot (TYPE); \ | 310 | 1.55M | d_m3PreloadNext (); \ | 311 | 1.55M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.55M | nextOpPreloaded (); \ | 313 | 1.55M | } |
m3_compile.c:op_u64_ShiftLeft_ss Line | Count | Source | 306 | 1.23M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.23M | { \ | 308 | 1.23M | TYPE operand2 = slot (TYPE); \ | 309 | 1.23M | TYPE operand1 = slot (TYPE); \ | 310 | 1.23M | d_m3PreloadNext (); \ | 311 | 1.23M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.23M | nextOpPreloaded (); \ | 313 | 1.23M | } |
m3_compile.c:op_i64_ShiftRight_ss Line | Count | Source | 306 | 1.00M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.00M | { \ | 308 | 1.00M | TYPE operand2 = slot (TYPE); \ | 309 | 1.00M | TYPE operand1 = slot (TYPE); \ | 310 | 1.00M | d_m3PreloadNext (); \ | 311 | 1.00M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.00M | nextOpPreloaded (); \ | 313 | 1.00M | } |
m3_compile.c:op_u64_ShiftRight_ss Line | Count | Source | 306 | 936k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 936k | { \ | 308 | 936k | TYPE operand2 = slot (TYPE); \ | 309 | 936k | TYPE operand1 = slot (TYPE); \ | 310 | 936k | d_m3PreloadNext (); \ | 311 | 936k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 936k | nextOpPreloaded (); \ | 313 | 936k | } |
m3_compile.c:op_u64_Rotl_ss Line | Count | Source | 306 | 1.59M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.59M | { \ | 308 | 1.59M | TYPE operand2 = slot (TYPE); \ | 309 | 1.59M | TYPE operand1 = slot (TYPE); \ | 310 | 1.59M | d_m3PreloadNext (); \ | 311 | 1.59M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.59M | nextOpPreloaded (); \ | 313 | 1.59M | } |
m3_compile.c:op_u64_Rotr_ss Line | Count | Source | 306 | 1.07M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.07M | { \ | 308 | 1.07M | TYPE operand2 = slot (TYPE); \ | 309 | 1.07M | TYPE operand1 = slot (TYPE); \ | 310 | 1.07M | d_m3PreloadNext (); \ | 311 | 1.07M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.07M | nextOpPreloaded (); \ | 313 | 1.07M | } |
m3_compile.c:op_f32_Add_ss Line | Count | Source | 306 | 824k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 824k | { \ | 308 | 824k | TYPE operand2 = slot (TYPE); \ | 309 | 824k | TYPE operand1 = slot (TYPE); \ | 310 | 824k | d_m3PreloadNext (); \ | 311 | 824k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 824k | nextOpPreloaded (); \ | 313 | 824k | } |
m3_compile.c:op_f32_Subtract_ss Line | Count | Source | 306 | 762k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 762k | { \ | 308 | 762k | TYPE operand2 = slot (TYPE); \ | 309 | 762k | TYPE operand1 = slot (TYPE); \ | 310 | 762k | d_m3PreloadNext (); \ | 311 | 762k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 762k | nextOpPreloaded (); \ | 313 | 762k | } |
m3_compile.c:op_f32_Multiply_ss Line | Count | Source | 306 | 1.14M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 1.14M | { \ | 308 | 1.14M | TYPE operand2 = slot (TYPE); \ | 309 | 1.14M | TYPE operand1 = slot (TYPE); \ | 310 | 1.14M | d_m3PreloadNext (); \ | 311 | 1.14M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 1.14M | nextOpPreloaded (); \ | 313 | 1.14M | } |
m3_compile.c:op_f32_Divide_ss Line | Count | Source | 306 | 7.10k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 7.10k | { \ | 308 | 7.10k | TYPE operand2 = slot (TYPE); \ | 309 | 7.10k | TYPE operand1 = slot (TYPE); \ | 310 | 7.10k | d_m3PreloadNext (); \ | 311 | 7.10k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 7.10k | nextOpPreloaded (); \ | 313 | 7.10k | } |
m3_compile.c:op_f32_Min_ss Line | Count | Source | 306 | 2.21M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.21M | { \ | 308 | 2.21M | TYPE operand2 = slot (TYPE); \ | 309 | 2.21M | TYPE operand1 = slot (TYPE); \ | 310 | 2.21M | d_m3PreloadNext (); \ | 311 | 2.21M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.21M | nextOpPreloaded (); \ | 313 | 2.21M | } |
m3_compile.c:op_f32_Max_ss Line | Count | Source | 306 | 2.17M | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 2.17M | { \ | 308 | 2.17M | TYPE operand2 = slot (TYPE); \ | 309 | 2.17M | TYPE operand1 = slot (TYPE); \ | 310 | 2.17M | d_m3PreloadNext (); \ | 311 | 2.17M | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 2.17M | nextOpPreloaded (); \ | 313 | 2.17M | } |
m3_compile.c:op_f32_CopySign_ss Line | Count | Source | 306 | 472k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 472k | { \ | 308 | 472k | TYPE operand2 = slot (TYPE); \ | 309 | 472k | TYPE operand1 = slot (TYPE); \ | 310 | 472k | d_m3PreloadNext (); \ | 311 | 472k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 472k | nextOpPreloaded (); \ | 313 | 472k | } |
m3_compile.c:op_f64_Add_ss Line | Count | Source | 306 | 389k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 389k | { \ | 308 | 389k | TYPE operand2 = slot (TYPE); \ | 309 | 389k | TYPE operand1 = slot (TYPE); \ | 310 | 389k | d_m3PreloadNext (); \ | 311 | 389k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 389k | nextOpPreloaded (); \ | 313 | 389k | } |
m3_compile.c:op_f64_Subtract_ss Line | Count | Source | 306 | 245k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 245k | { \ | 308 | 245k | TYPE operand2 = slot (TYPE); \ | 309 | 245k | TYPE operand1 = slot (TYPE); \ | 310 | 245k | d_m3PreloadNext (); \ | 311 | 245k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 245k | nextOpPreloaded (); \ | 313 | 245k | } |
m3_compile.c:op_f64_Multiply_ss Line | Count | Source | 306 | 370k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 370k | { \ | 308 | 370k | TYPE operand2 = slot (TYPE); \ | 309 | 370k | TYPE operand1 = slot (TYPE); \ | 310 | 370k | d_m3PreloadNext (); \ | 311 | 370k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 370k | nextOpPreloaded (); \ | 313 | 370k | } |
m3_compile.c:op_f64_Divide_ss Line | Count | Source | 306 | 8.62k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 8.62k | { \ | 308 | 8.62k | TYPE operand2 = slot (TYPE); \ | 309 | 8.62k | TYPE operand1 = slot (TYPE); \ | 310 | 8.62k | d_m3PreloadNext (); \ | 311 | 8.62k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 8.62k | nextOpPreloaded (); \ | 313 | 8.62k | } |
m3_compile.c:op_f64_Min_ss Line | Count | Source | 306 | 778k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 778k | { \ | 308 | 778k | TYPE operand2 = slot (TYPE); \ | 309 | 778k | TYPE operand1 = slot (TYPE); \ | 310 | 778k | d_m3PreloadNext (); \ | 311 | 778k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 778k | nextOpPreloaded (); \ | 313 | 778k | } |
m3_compile.c:op_f64_Max_ss Line | Count | Source | 306 | 711k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 711k | { \ | 308 | 711k | TYPE operand2 = slot (TYPE); \ | 309 | 711k | TYPE operand1 = slot (TYPE); \ | 310 | 711k | d_m3PreloadNext (); \ | 311 | 711k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 711k | nextOpPreloaded (); \ | 313 | 711k | } |
m3_compile.c:op_f64_CopySign_ss Line | Count | Source | 306 | 310k | d_m3Op(TYPE##_##NAME##_ss) \ | 307 | 310k | { \ | 308 | 310k | TYPE operand2 = slot (TYPE); \ | 309 | 310k | TYPE operand1 = slot (TYPE); \ | 310 | 310k | d_m3PreloadNext (); \ | 311 | 310k | OP((RES), operand1, operand2, ##__VA_ARGS__); \ | 312 | 310k | nextOpPreloaded (); \ | 313 | 310k | } |
|
314 | | |
315 | | #define d_m3OpMacro(RES, REG, TYPE, NAME, OP, ...) \ |
316 | 38.7M | d_m3Op(TYPE##_##NAME##_sr) \ |
317 | 38.7M | { \ |
318 | 38.7M | TYPE operand = slot (TYPE); \ |
319 | 38.7M | d_m3PreloadNext (); \ |
320 | 38.7M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ |
321 | 38.7M | nextOpPreloaded (); \ |
322 | 33.1k | } \ m3_compile.c:op_i32_LessThan_sr Line | Count | Source | 316 | 1.72M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.72M | { \ | 318 | 1.72M | TYPE operand = slot (TYPE); \ | 319 | 1.72M | d_m3PreloadNext (); \ | 320 | 1.72M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.72M | nextOpPreloaded (); \ | 322 | 1.72M | } \ |
m3_compile.c:op_u32_LessThan_sr Line | Count | Source | 316 | 2.31M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 2.31M | { \ | 318 | 2.31M | TYPE operand = slot (TYPE); \ | 319 | 2.31M | d_m3PreloadNext (); \ | 320 | 2.31M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 2.31M | nextOpPreloaded (); \ | 322 | 2.31M | } \ |
m3_compile.c:op_i32_GreaterThan_sr Line | Count | Source | 316 | 2.05M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 2.05M | { \ | 318 | 2.05M | TYPE operand = slot (TYPE); \ | 319 | 2.05M | d_m3PreloadNext (); \ | 320 | 2.05M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 2.05M | nextOpPreloaded (); \ | 322 | 2.05M | } \ |
m3_compile.c:op_u32_GreaterThan_sr Line | Count | Source | 316 | 1.88M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.88M | { \ | 318 | 1.88M | TYPE operand = slot (TYPE); \ | 319 | 1.88M | d_m3PreloadNext (); \ | 320 | 1.88M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.88M | nextOpPreloaded (); \ | 322 | 1.88M | } \ |
m3_compile.c:op_i32_LessThanOrEqual_sr Line | Count | Source | 316 | 1.89M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.89M | { \ | 318 | 1.89M | TYPE operand = slot (TYPE); \ | 319 | 1.89M | d_m3PreloadNext (); \ | 320 | 1.89M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.89M | nextOpPreloaded (); \ | 322 | 1.89M | } \ |
m3_compile.c:op_u32_LessThanOrEqual_sr Line | Count | Source | 316 | 1.62M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.62M | { \ | 318 | 1.62M | TYPE operand = slot (TYPE); \ | 319 | 1.62M | d_m3PreloadNext (); \ | 320 | 1.62M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.62M | nextOpPreloaded (); \ | 322 | 1.62M | } \ |
m3_compile.c:op_i32_GreaterThanOrEqual_sr Line | Count | Source | 316 | 2.38M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 2.38M | { \ | 318 | 2.38M | TYPE operand = slot (TYPE); \ | 319 | 2.38M | d_m3PreloadNext (); \ | 320 | 2.38M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 2.38M | nextOpPreloaded (); \ | 322 | 2.38M | } \ |
m3_compile.c:op_u32_GreaterThanOrEqual_sr Line | Count | Source | 316 | 1.53M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.53M | { \ | 318 | 1.53M | TYPE operand = slot (TYPE); \ | 319 | 1.53M | d_m3PreloadNext (); \ | 320 | 1.53M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.53M | nextOpPreloaded (); \ | 322 | 1.53M | } \ |
m3_compile.c:op_i64_LessThan_sr Line | Count | Source | 316 | 999k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 999k | { \ | 318 | 999k | TYPE operand = slot (TYPE); \ | 319 | 999k | d_m3PreloadNext (); \ | 320 | 999k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 999k | nextOpPreloaded (); \ | 322 | 999k | } \ |
m3_compile.c:op_u64_LessThan_sr Line | Count | Source | 316 | 1.24M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.24M | { \ | 318 | 1.24M | TYPE operand = slot (TYPE); \ | 319 | 1.24M | d_m3PreloadNext (); \ | 320 | 1.24M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.24M | nextOpPreloaded (); \ | 322 | 1.24M | } \ |
m3_compile.c:op_i64_GreaterThan_sr Line | Count | Source | 316 | 1.19M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.19M | { \ | 318 | 1.19M | TYPE operand = slot (TYPE); \ | 319 | 1.19M | d_m3PreloadNext (); \ | 320 | 1.19M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.19M | nextOpPreloaded (); \ | 322 | 1.19M | } \ |
m3_compile.c:op_u64_GreaterThan_sr Line | Count | Source | 316 | 1.07M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.07M | { \ | 318 | 1.07M | TYPE operand = slot (TYPE); \ | 319 | 1.07M | d_m3PreloadNext (); \ | 320 | 1.07M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.07M | nextOpPreloaded (); \ | 322 | 1.07M | } \ |
m3_compile.c:op_i64_LessThanOrEqual_sr Line | Count | Source | 316 | 1.32M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.32M | { \ | 318 | 1.32M | TYPE operand = slot (TYPE); \ | 319 | 1.32M | d_m3PreloadNext (); \ | 320 | 1.32M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.32M | nextOpPreloaded (); \ | 322 | 1.32M | } \ |
m3_compile.c:op_u64_LessThanOrEqual_sr Line | Count | Source | 316 | 992k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 992k | { \ | 318 | 992k | TYPE operand = slot (TYPE); \ | 319 | 992k | d_m3PreloadNext (); \ | 320 | 992k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 992k | nextOpPreloaded (); \ | 322 | 992k | } \ |
m3_compile.c:op_i64_GreaterThanOrEqual_sr Line | Count | Source | 316 | 865k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 865k | { \ | 318 | 865k | TYPE operand = slot (TYPE); \ | 319 | 865k | d_m3PreloadNext (); \ | 320 | 865k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 865k | nextOpPreloaded (); \ | 322 | 865k | } \ |
m3_compile.c:op_u64_GreaterThanOrEqual_sr Line | Count | Source | 316 | 861k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 861k | { \ | 318 | 861k | TYPE operand = slot (TYPE); \ | 319 | 861k | d_m3PreloadNext (); \ | 320 | 861k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 861k | nextOpPreloaded (); \ | 322 | 861k | } \ |
m3_compile.c:op_f32_LessThan_sr Line | Count | Source | 316 | 415k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 415k | { \ | 318 | 415k | TYPE operand = slot (TYPE); \ | 319 | 415k | d_m3PreloadNext (); \ | 320 | 415k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 415k | nextOpPreloaded (); \ | 322 | 415k | } \ |
m3_compile.c:op_f32_GreaterThan_sr Line | Count | Source | 316 | 421k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 421k | { \ | 318 | 421k | TYPE operand = slot (TYPE); \ | 319 | 421k | d_m3PreloadNext (); \ | 320 | 421k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 421k | nextOpPreloaded (); \ | 322 | 421k | } \ |
m3_compile.c:op_f32_LessThanOrEqual_sr Line | Count | Source | 316 | 352k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 352k | { \ | 318 | 352k | TYPE operand = slot (TYPE); \ | 319 | 352k | d_m3PreloadNext (); \ | 320 | 352k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 352k | nextOpPreloaded (); \ | 322 | 352k | } \ |
m3_compile.c:op_f32_GreaterThanOrEqual_sr Line | Count | Source | 316 | 629k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 629k | { \ | 318 | 629k | TYPE operand = slot (TYPE); \ | 319 | 629k | d_m3PreloadNext (); \ | 320 | 629k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 629k | nextOpPreloaded (); \ | 322 | 629k | } \ |
m3_compile.c:op_f64_LessThan_sr Line | Count | Source | 316 | 221k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 221k | { \ | 318 | 221k | TYPE operand = slot (TYPE); \ | 319 | 221k | d_m3PreloadNext (); \ | 320 | 221k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 221k | nextOpPreloaded (); \ | 322 | 221k | } \ |
m3_compile.c:op_f64_GreaterThan_sr Line | Count | Source | 316 | 337k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 337k | { \ | 318 | 337k | TYPE operand = slot (TYPE); \ | 319 | 337k | d_m3PreloadNext (); \ | 320 | 337k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 337k | nextOpPreloaded (); \ | 322 | 337k | } \ |
m3_compile.c:op_f64_LessThanOrEqual_sr Line | Count | Source | 316 | 268k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 268k | { \ | 318 | 268k | TYPE operand = slot (TYPE); \ | 319 | 268k | d_m3PreloadNext (); \ | 320 | 268k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 268k | nextOpPreloaded (); \ | 322 | 268k | } \ |
m3_compile.c:op_f64_GreaterThanOrEqual_sr Line | Count | Source | 316 | 432k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 432k | { \ | 318 | 432k | TYPE operand = slot (TYPE); \ | 319 | 432k | d_m3PreloadNext (); \ | 320 | 432k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 432k | nextOpPreloaded (); \ | 322 | 432k | } \ |
m3_compile.c:op_i32_Subtract_sr Line | Count | Source | 316 | 1.64M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.64M | { \ | 318 | 1.64M | TYPE operand = slot (TYPE); \ | 319 | 1.64M | d_m3PreloadNext (); \ | 320 | 1.64M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.64M | nextOpPreloaded (); \ | 322 | 1.64M | } \ |
m3_compile.c:op_i32_Divide_sr Line | Count | Source | 316 | 15.4k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 15.4k | { \ | 318 | 15.4k | TYPE operand = slot (TYPE); \ | 319 | 15.4k | d_m3PreloadNext (); \ | 320 | 15.4k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 15.4k | nextOpPreloaded (); \ | 322 | 15.4k | } \ |
m3_compile.c:op_u32_Divide_sr Line | Count | Source | 316 | 15.8k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 15.8k | { \ | 318 | 15.8k | TYPE operand = slot (TYPE); \ | 319 | 15.8k | d_m3PreloadNext (); \ | 320 | 15.8k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 15.7k | nextOpPreloaded (); \ | 322 | 15.8k | } \ |
m3_compile.c:op_i32_Remainder_sr Line | Count | Source | 316 | 15.0k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 15.0k | { \ | 318 | 15.0k | TYPE operand = slot (TYPE); \ | 319 | 15.0k | d_m3PreloadNext (); \ | 320 | 15.0k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 15.0k | nextOpPreloaded (); \ | 322 | 15.0k | } \ |
m3_compile.c:op_u32_Remainder_sr Line | Count | Source | 316 | 15.2k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 15.2k | { \ | 318 | 15.2k | TYPE operand = slot (TYPE); \ | 319 | 15.2k | d_m3PreloadNext (); \ | 320 | 15.2k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 15.2k | nextOpPreloaded (); \ | 322 | 15.2k | } \ |
m3_compile.c:op_u32_ShiftLeft_sr Line | Count | Source | 316 | 866k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 866k | { \ | 318 | 866k | TYPE operand = slot (TYPE); \ | 319 | 866k | d_m3PreloadNext (); \ | 320 | 866k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 866k | nextOpPreloaded (); \ | 322 | 866k | } \ |
m3_compile.c:op_i32_ShiftRight_sr Line | Count | Source | 316 | 878k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 878k | { \ | 318 | 878k | TYPE operand = slot (TYPE); \ | 319 | 878k | d_m3PreloadNext (); \ | 320 | 878k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 878k | nextOpPreloaded (); \ | 322 | 878k | } \ |
m3_compile.c:op_u32_ShiftRight_sr Line | Count | Source | 316 | 727k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 727k | { \ | 318 | 727k | TYPE operand = slot (TYPE); \ | 319 | 727k | d_m3PreloadNext (); \ | 320 | 727k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 727k | nextOpPreloaded (); \ | 322 | 727k | } \ |
m3_compile.c:op_u32_Rotl_sr Line | Count | Source | 316 | 725k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 725k | { \ | 318 | 725k | TYPE operand = slot (TYPE); \ | 319 | 725k | d_m3PreloadNext (); \ | 320 | 725k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 725k | nextOpPreloaded (); \ | 322 | 725k | } \ |
m3_compile.c:op_u32_Rotr_sr Line | Count | Source | 316 | 1.53M | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 1.53M | { \ | 318 | 1.53M | TYPE operand = slot (TYPE); \ | 319 | 1.53M | d_m3PreloadNext (); \ | 320 | 1.53M | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 1.53M | nextOpPreloaded (); \ | 322 | 1.53M | } \ |
m3_compile.c:op_i64_Subtract_sr Line | Count | Source | 316 | 473k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 473k | { \ | 318 | 473k | TYPE operand = slot (TYPE); \ | 319 | 473k | d_m3PreloadNext (); \ | 320 | 473k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 473k | nextOpPreloaded (); \ | 322 | 473k | } \ |
m3_compile.c:op_i64_Divide_sr Line | Count | Source | 316 | 17.7k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 17.7k | { \ | 318 | 17.7k | TYPE operand = slot (TYPE); \ | 319 | 17.7k | d_m3PreloadNext (); \ | 320 | 17.7k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 17.7k | nextOpPreloaded (); \ | 322 | 17.7k | } \ |
m3_compile.c:op_u64_Divide_sr Line | Count | Source | 316 | 13.2k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 13.2k | { \ | 318 | 13.2k | TYPE operand = slot (TYPE); \ | 319 | 13.2k | d_m3PreloadNext (); \ | 320 | 13.2k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 13.2k | nextOpPreloaded (); \ | 322 | 13.2k | } \ |
m3_compile.c:op_i64_Remainder_sr Line | Count | Source | 316 | 19.9k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 19.9k | { \ | 318 | 19.9k | TYPE operand = slot (TYPE); \ | 319 | 19.9k | d_m3PreloadNext (); \ | 320 | 19.9k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 19.9k | nextOpPreloaded (); \ | 322 | 19.9k | } \ |
m3_compile.c:op_u64_Remainder_sr Line | Count | Source | 316 | 13.1k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 13.1k | { \ | 318 | 13.1k | TYPE operand = slot (TYPE); \ | 319 | 13.1k | d_m3PreloadNext (); \ | 320 | 13.1k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 13.1k | nextOpPreloaded (); \ | 322 | 13.1k | } \ |
m3_compile.c:op_u64_ShiftLeft_sr Line | Count | Source | 316 | 818k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 818k | { \ | 318 | 818k | TYPE operand = slot (TYPE); \ | 319 | 818k | d_m3PreloadNext (); \ | 320 | 818k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 818k | nextOpPreloaded (); \ | 322 | 818k | } \ |
m3_compile.c:op_i64_ShiftRight_sr Line | Count | Source | 316 | 500k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 500k | { \ | 318 | 500k | TYPE operand = slot (TYPE); \ | 319 | 500k | d_m3PreloadNext (); \ | 320 | 500k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 500k | nextOpPreloaded (); \ | 322 | 500k | } \ |
m3_compile.c:op_u64_ShiftRight_sr Line | Count | Source | 316 | 432k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 432k | { \ | 318 | 432k | TYPE operand = slot (TYPE); \ | 319 | 432k | d_m3PreloadNext (); \ | 320 | 432k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 432k | nextOpPreloaded (); \ | 322 | 432k | } \ |
m3_compile.c:op_u64_Rotl_sr Line | Count | Source | 316 | 783k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 783k | { \ | 318 | 783k | TYPE operand = slot (TYPE); \ | 319 | 783k | d_m3PreloadNext (); \ | 320 | 783k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 783k | nextOpPreloaded (); \ | 322 | 783k | } \ |
m3_compile.c:op_u64_Rotr_sr Line | Count | Source | 316 | 410k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 410k | { \ | 318 | 410k | TYPE operand = slot (TYPE); \ | 319 | 410k | d_m3PreloadNext (); \ | 320 | 410k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 410k | nextOpPreloaded (); \ | 322 | 410k | } \ |
m3_compile.c:op_f32_Subtract_sr Line | Count | Source | 316 | 592k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 592k | { \ | 318 | 592k | TYPE operand = slot (TYPE); \ | 319 | 592k | d_m3PreloadNext (); \ | 320 | 592k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 592k | nextOpPreloaded (); \ | 322 | 592k | } \ |
m3_compile.c:op_f32_Divide_sr Line | Count | Source | 316 | 3.60k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 3.60k | { \ | 318 | 3.60k | TYPE operand = slot (TYPE); \ | 319 | 3.60k | d_m3PreloadNext (); \ | 320 | 3.60k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 3.60k | nextOpPreloaded (); \ | 322 | 3.60k | } \ |
m3_compile.c:op_f32_CopySign_sr Line | Count | Source | 316 | 351k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 351k | { \ | 318 | 351k | TYPE operand = slot (TYPE); \ | 319 | 351k | d_m3PreloadNext (); \ | 320 | 351k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 351k | nextOpPreloaded (); \ | 322 | 351k | } \ |
m3_compile.c:op_f64_Subtract_sr Line | Count | Source | 316 | 472k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 472k | { \ | 318 | 472k | TYPE operand = slot (TYPE); \ | 319 | 472k | d_m3PreloadNext (); \ | 320 | 472k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 472k | nextOpPreloaded (); \ | 322 | 472k | } \ |
m3_compile.c:op_f64_Divide_sr Line | Count | Source | 316 | 3.71k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 3.71k | { \ | 318 | 3.71k | TYPE operand = slot (TYPE); \ | 319 | 3.71k | d_m3PreloadNext (); \ | 320 | 3.71k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 3.71k | nextOpPreloaded (); \ | 322 | 3.71k | } \ |
m3_compile.c:op_f64_CopySign_sr Line | Count | Source | 316 | 315k | d_m3Op(TYPE##_##NAME##_sr) \ | 317 | 315k | { \ | 318 | 315k | TYPE operand = slot (TYPE); \ | 319 | 315k | d_m3PreloadNext (); \ | 320 | 315k | OP((RES), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 321 | 315k | nextOpPreloaded (); \ | 322 | 315k | } \ |
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 |
323 | | d_m3CommutativeOpMacro(RES, REG, TYPE,NAME, OP, ##__VA_ARGS__) |
324 | | |
325 | | // Accept macros |
326 | | #define d_m3CommutativeOpMacro_i(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) |
327 | | #define d_m3OpMacro_i(TYPE, NAME, MACRO, ...) d_m3OpMacro ( _r0, _r0, TYPE, NAME, MACRO, ##__VA_ARGS__) |
328 | | #define d_m3CommutativeOpMacro_f(TYPE, NAME, MACRO, ...) d_m3CommutativeOpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) |
329 | | #define d_m3OpMacro_f(TYPE, NAME, MACRO, ...) d_m3OpMacro (_fp0, _fp0, TYPE, NAME, MACRO, ##__VA_ARGS__) |
330 | | |
331 | 63.7M | #define M3_FUNC(RES, A, B, OP) (RES) = OP((A), (B)) // Accept functions: res = OP(a,b) |
332 | 137M | #define M3_OPER(RES, A, B, OP) (RES) = ((A) OP (B)) // Accept operators: res = a OP b |
333 | | |
334 | | // The same two, for a float operation whose NaN result the spec leaves to the host: |
335 | | // CANON is the canonicalizer for the operation's width (only in effect when d_m3CanonicalNaN is set). |
336 | 11.1M | #define M3_FUNC_A(RES, A, B, OP, CANON) (RES) = CANON(OP((A), (B))) |
337 | 10.4M | #define M3_OPER_A(RES, A, B, OP, CANON) (RES) = CANON((A) OP (B)) |
338 | | |
339 | 16.3M | #define d_m3CommutativeOpFunc_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_FUNC, OP) |
340 | 37.7M | #define d_m3OpFunc_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_FUNC, OP) |
341 | | #define d_m3CommutativeOpFunc_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_FUNC, OP) |
342 | 1.94M | #define d_m3OpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC, OP) |
343 | | |
344 | 33.2M | #define d_m3CommutativeOp_i(TYPE, NAME, OP) d_m3CommutativeOpMacro_i (TYPE, NAME, M3_OPER, OP) |
345 | 87.0M | #define d_m3Op_i(TYPE, NAME, OP) d_m3OpMacro_i (TYPE, NAME, M3_OPER, OP) |
346 | | #define d_m3CommutativeOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER, OP) |
347 | | #define d_m3Op_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER, OP) |
348 | | |
349 | | // ...and the arithmetic ones, which name the canonicalizer for their own width |
350 | 5.15M | #define d_m3CommutativeArithOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro_f (TYPE, NAME, M3_OPER_A, OP, canon_nan_##TYPE) |
351 | 3.25M | #define d_m3ArithOp_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_OPER_A, OP, canon_nan_##TYPE) |
352 | 11.1M | #define d_m3ArithOpFunc_f(TYPE, NAME, OP) d_m3OpMacro_f (TYPE, NAME, M3_FUNC_A, OP, canon_nan_##TYPE) |
353 | | |
354 | | // compare needs to be distinct for fp 'cause the result must be _r0 |
355 | 10.2M | #define d_m3CompareOp_f(TYPE, NAME, OP) d_m3OpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) |
356 | 4.24M | #define d_m3CommutativeCmpOp_f(TYPE, NAME, OP) d_m3CommutativeOpMacro (_r0, _fp0, TYPE, NAME, M3_OPER, OP) |
357 | | |
358 | | |
359 | | //----------------------- |
360 | | // clang-format off |
361 | | |
362 | | // signed |
363 | | d_m3CommutativeOp_i(i32, Equal, ==) d_m3CommutativeOp_i(i64, Equal, ==) |
364 | | d_m3CommutativeOp_i(i32, NotEqual, !=) d_m3CommutativeOp_i(i64, NotEqual, !=) |
365 | | |
366 | | d_m3Op_i(i32, LessThan, < ) d_m3Op_i(i64, LessThan, < ) |
367 | | d_m3Op_i(i32, GreaterThan, > ) d_m3Op_i(i64, GreaterThan, > ) |
368 | | d_m3Op_i(i32, LessThanOrEqual, <=) d_m3Op_i(i64, LessThanOrEqual, <=) |
369 | | d_m3Op_i(i32, GreaterThanOrEqual, >=) d_m3Op_i(i64, GreaterThanOrEqual, >=) |
370 | | |
371 | | // unsigned |
372 | | d_m3Op_i(u32, LessThan, < ) d_m3Op_i(u64, LessThan, < ) |
373 | | d_m3Op_i(u32, GreaterThan, > ) d_m3Op_i(u64, GreaterThan, > ) |
374 | | d_m3Op_i(u32, LessThanOrEqual, <=) d_m3Op_i(u64, LessThanOrEqual, <=) |
375 | | d_m3Op_i(u32, GreaterThanOrEqual, >=) d_m3Op_i(u64, GreaterThanOrEqual, >=) |
376 | | |
377 | | #if d_m3HasFloat |
378 | | d_m3CommutativeCmpOp_f(f32, Equal, ==) d_m3CommutativeCmpOp_f(f64, Equal, ==) |
379 | | d_m3CommutativeCmpOp_f(f32, NotEqual, !=) d_m3CommutativeCmpOp_f(f64, NotEqual, !=) |
380 | | d_m3CompareOp_f(f32, LessThan, < ) d_m3CompareOp_f(f64, LessThan, < ) |
381 | | d_m3CompareOp_f(f32, GreaterThan, > ) d_m3CompareOp_f(f64, GreaterThan, > ) |
382 | | d_m3CompareOp_f(f32, LessThanOrEqual, <=) d_m3CompareOp_f(f64, LessThanOrEqual, <=) |
383 | | d_m3CompareOp_f(f32, GreaterThanOrEqual, >=) d_m3CompareOp_f(f64, GreaterThanOrEqual, >=) |
384 | | #endif |
385 | | |
386 | 4.08M | #define OP_ADD_32(A,B) (i32)((u32)(A) + (u32)(B)) |
387 | 4.35M | #define OP_ADD_64(A,B) (i64)((u64)(A) + (u64)(B)) |
388 | 5.01M | #define OP_SUB_32(A,B) (i32)((u32)(A) - (u32)(B)) |
389 | 4.21M | #define OP_SUB_64(A,B) (i64)((u64)(A) - (u64)(B)) |
390 | 4.18M | #define OP_MUL_32(A,B) (i32)((u32)(A) * (u32)(B)) |
391 | 6.06M | #define OP_MUL_64(A,B) (i64)((u64)(A) * (u64)(B)) |
392 | | |
393 | 3.83M | d_m3CommutativeOpFunc_i (i32, Add, OP_ADD_32) d_m3CommutativeOpFunc_i (i64, Add, OP_ADD_64) |
394 | 5.26M | d_m3CommutativeOpFunc_i (i32, Multiply, OP_MUL_32) d_m3CommutativeOpFunc_i (i64, Multiply, OP_MUL_64) |
395 | | |
396 | 4.41M | d_m3OpFunc_i (i32, Subtract, OP_SUB_32) d_m3OpFunc_i (i64, Subtract, OP_SUB_64) |
397 | | |
398 | 4.32M | #define OP_SHL_32(X,N) ((X) << ((u32)(N) % 32)) |
399 | 3.44M | #define OP_SHL_64(X,N) ((X) << ((u64)(N) % 64)) |
400 | 7.01M | #define OP_SHR_32(X,N) ((X) >> ((u32)(N) % 32)) |
401 | 5.43M | #define OP_SHR_64(X,N) ((X) >> ((u64)(N) % 64)) |
402 | | |
403 | 3.56M | d_m3OpFunc_i (u32, ShiftLeft, OP_SHL_32) d_m3OpFunc_i (u64, ShiftLeft, OP_SHL_64) |
404 | 2.93M | d_m3OpFunc_i (i32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (i64, ShiftRight, OP_SHR_64) |
405 | 2.50M | d_m3OpFunc_i (u32, ShiftRight, OP_SHR_32) d_m3OpFunc_i (u64, ShiftRight, OP_SHR_64) |
406 | | |
407 | | d_m3CommutativeOp_i(u32, And, &) |
408 | | d_m3CommutativeOp_i(u32, Or, |) |
409 | | d_m3CommutativeOp_i(u32, Xor, ^) |
410 | | |
411 | | d_m3CommutativeOp_i(u64, And, &) |
412 | | d_m3CommutativeOp_i(u64, Or, |) |
413 | | d_m3CommutativeOp_i(u64, Xor, ^) |
414 | | |
415 | | #if d_m3FoldSetLocal |
416 | | |
417 | | // destination-folded ("_f") variants: same operand shapes as _rs/_sr/_ss, but the result is |
418 | | // written to a trailing destination slot instead of _r0 - a producer fused with its local.set. |
419 | | // operand immediates keep their normal order; the destination slot is the last immediate. |
420 | | // The destination immediate is taken as a pointer before the operation runs, rather |
421 | | // than written through at the end: that leaves _pc final early enough for the dispatch |
422 | | // load to be issued ahead of the arithmetic instead of after it. |
423 | | // The result is written through to the register as well as to the destination slot. |
424 | | // Destination folding only ever replaces an operation that computed into the register, |
425 | | // so the old value there is already dead and keeping the result costs nothing -- and it |
426 | | // lets a local.tee carry on in the register instead of reloading the slot it just wrote. |
427 | | # define d_m3FoldCommutativeOpMacro(REG, TYPE, NAME, OP, ...) \ |
428 | 5.03M | d_m3Op(TYPE##_##NAME##_rs_f) \ |
429 | 5.03M | { \ |
430 | 5.03M | TYPE operand = slot (TYPE); \ |
431 | 5.03M | TYPE * dest = slot_ptr (TYPE); \ |
432 | 5.03M | d_m3PreloadNext (); \ |
433 | 5.03M | TYPE result; \ |
434 | 5.03M | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ |
435 | 5.03M | * dest = result; REG = result; \ |
436 | 5.03M | nextOpPreloaded (); \ |
437 | 5.03M | } \ m3_compile.c:op_i32_Add_rs_f Line | Count | Source | 428 | 130k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 130k | { \ | 430 | 130k | TYPE operand = slot (TYPE); \ | 431 | 130k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 130k | d_m3PreloadNext (); \ | 433 | 130k | TYPE result; \ | 434 | 130k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 130k | * dest = result; REG = result; \ | 436 | 130k | nextOpPreloaded (); \ | 437 | 130k | } \ |
m3_compile.c:op_i32_Subtract_rs_f Line | Count | Source | 428 | 230k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 230k | { \ | 430 | 230k | TYPE operand = slot (TYPE); \ | 431 | 230k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 230k | d_m3PreloadNext (); \ | 433 | 230k | TYPE result; \ | 434 | 230k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 230k | * dest = result; REG = result; \ | 436 | 230k | nextOpPreloaded (); \ | 437 | 230k | } \ |
m3_compile.c:op_i32_Multiply_rs_f Line | Count | Source | 428 | 347k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 347k | { \ | 430 | 347k | TYPE operand = slot (TYPE); \ | 431 | 347k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 347k | d_m3PreloadNext (); \ | 433 | 347k | TYPE result; \ | 434 | 347k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 347k | * dest = result; REG = result; \ | 436 | 347k | nextOpPreloaded (); \ | 437 | 347k | } \ |
m3_compile.c:op_u32_And_rs_f Line | Count | Source | 428 | 286k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 286k | { \ | 430 | 286k | TYPE operand = slot (TYPE); \ | 431 | 286k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 286k | d_m3PreloadNext (); \ | 433 | 286k | TYPE result; \ | 434 | 286k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 286k | * dest = result; REG = result; \ | 436 | 286k | nextOpPreloaded (); \ | 437 | 286k | } \ |
m3_compile.c:op_u32_Or_rs_f Line | Count | Source | 428 | 115k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 115k | { \ | 430 | 115k | TYPE operand = slot (TYPE); \ | 431 | 115k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 115k | d_m3PreloadNext (); \ | 433 | 115k | TYPE result; \ | 434 | 115k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 115k | * dest = result; REG = result; \ | 436 | 115k | nextOpPreloaded (); \ | 437 | 115k | } \ |
m3_compile.c:op_u32_Xor_rs_f Line | Count | Source | 428 | 272k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 272k | { \ | 430 | 272k | TYPE operand = slot (TYPE); \ | 431 | 272k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 272k | d_m3PreloadNext (); \ | 433 | 272k | TYPE result; \ | 434 | 272k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 272k | * dest = result; REG = result; \ | 436 | 272k | nextOpPreloaded (); \ | 437 | 272k | } \ |
m3_compile.c:op_u32_ShiftLeft_rs_f Line | Count | Source | 428 | 256k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 256k | { \ | 430 | 256k | TYPE operand = slot (TYPE); \ | 431 | 256k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 256k | d_m3PreloadNext (); \ | 433 | 256k | TYPE result; \ | 434 | 256k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 256k | * dest = result; REG = result; \ | 436 | 256k | nextOpPreloaded (); \ | 437 | 256k | } \ |
m3_compile.c:op_i32_ShiftRight_rs_f Line | Count | Source | 428 | 227k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 227k | { \ | 430 | 227k | TYPE operand = slot (TYPE); \ | 431 | 227k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 227k | d_m3PreloadNext (); \ | 433 | 227k | TYPE result; \ | 434 | 227k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 227k | * dest = result; REG = result; \ | 436 | 227k | nextOpPreloaded (); \ | 437 | 227k | } \ |
m3_compile.c:op_u32_ShiftRight_rs_f Line | Count | Source | 428 | 172k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 172k | { \ | 430 | 172k | TYPE operand = slot (TYPE); \ | 431 | 172k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 172k | d_m3PreloadNext (); \ | 433 | 172k | TYPE result; \ | 434 | 172k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 172k | * dest = result; REG = result; \ | 436 | 172k | nextOpPreloaded (); \ | 437 | 172k | } \ |
m3_compile.c:op_i64_Add_rs_f Line | Count | Source | 428 | 332k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 332k | { \ | 430 | 332k | TYPE operand = slot (TYPE); \ | 431 | 332k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 332k | d_m3PreloadNext (); \ | 433 | 332k | TYPE result; \ | 434 | 332k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 332k | * dest = result; REG = result; \ | 436 | 332k | nextOpPreloaded (); \ | 437 | 332k | } \ |
m3_compile.c:op_i64_Subtract_rs_f Line | Count | Source | 428 | 242k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 242k | { \ | 430 | 242k | TYPE operand = slot (TYPE); \ | 431 | 242k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 242k | d_m3PreloadNext (); \ | 433 | 242k | TYPE result; \ | 434 | 242k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 242k | * dest = result; REG = result; \ | 436 | 242k | nextOpPreloaded (); \ | 437 | 242k | } \ |
m3_compile.c:op_i64_Multiply_rs_f Line | Count | Source | 428 | 345k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 345k | { \ | 430 | 345k | TYPE operand = slot (TYPE); \ | 431 | 345k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 345k | d_m3PreloadNext (); \ | 433 | 345k | TYPE result; \ | 434 | 345k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 345k | * dest = result; REG = result; \ | 436 | 345k | nextOpPreloaded (); \ | 437 | 345k | } \ |
m3_compile.c:op_u64_And_rs_f Line | Count | Source | 428 | 325k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 325k | { \ | 430 | 325k | TYPE operand = slot (TYPE); \ | 431 | 325k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 325k | d_m3PreloadNext (); \ | 433 | 325k | TYPE result; \ | 434 | 325k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 325k | * dest = result; REG = result; \ | 436 | 325k | nextOpPreloaded (); \ | 437 | 325k | } \ |
m3_compile.c:op_u64_Or_rs_f Line | Count | Source | 428 | 280k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 280k | { \ | 430 | 280k | TYPE operand = slot (TYPE); \ | 431 | 280k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 280k | d_m3PreloadNext (); \ | 433 | 280k | TYPE result; \ | 434 | 280k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 280k | * dest = result; REG = result; \ | 436 | 280k | nextOpPreloaded (); \ | 437 | 280k | } \ |
m3_compile.c:op_u64_Xor_rs_f Line | Count | Source | 428 | 109k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 109k | { \ | 430 | 109k | TYPE operand = slot (TYPE); \ | 431 | 109k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 109k | d_m3PreloadNext (); \ | 433 | 109k | TYPE result; \ | 434 | 109k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 109k | * dest = result; REG = result; \ | 436 | 109k | nextOpPreloaded (); \ | 437 | 109k | } \ |
m3_compile.c:op_u64_ShiftLeft_rs_f Line | Count | Source | 428 | 149k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 149k | { \ | 430 | 149k | TYPE operand = slot (TYPE); \ | 431 | 149k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 149k | d_m3PreloadNext (); \ | 433 | 149k | TYPE result; \ | 434 | 149k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 149k | * dest = result; REG = result; \ | 436 | 149k | nextOpPreloaded (); \ | 437 | 149k | } \ |
m3_compile.c:op_i64_ShiftRight_rs_f Line | Count | Source | 428 | 96.9k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 96.9k | { \ | 430 | 96.9k | TYPE operand = slot (TYPE); \ | 431 | 96.9k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 96.9k | d_m3PreloadNext (); \ | 433 | 96.9k | TYPE result; \ | 434 | 96.9k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 96.9k | * dest = result; REG = result; \ | 436 | 96.9k | nextOpPreloaded (); \ | 437 | 96.9k | } \ |
m3_compile.c:op_u64_ShiftRight_rs_f Line | Count | Source | 428 | 147k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 147k | { \ | 430 | 147k | TYPE operand = slot (TYPE); \ | 431 | 147k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 147k | d_m3PreloadNext (); \ | 433 | 147k | TYPE result; \ | 434 | 147k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 147k | * dest = result; REG = result; \ | 436 | 147k | nextOpPreloaded (); \ | 437 | 147k | } \ |
m3_compile.c:op_f32_Add_rs_f Line | Count | Source | 428 | 95.9k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 95.9k | { \ | 430 | 95.9k | TYPE operand = slot (TYPE); \ | 431 | 95.9k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 95.9k | d_m3PreloadNext (); \ | 433 | 95.9k | TYPE result; \ | 434 | 95.9k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 95.9k | * dest = result; REG = result; \ | 436 | 95.9k | nextOpPreloaded (); \ | 437 | 95.9k | } \ |
m3_compile.c:op_f32_Subtract_rs_f Line | Count | Source | 428 | 114k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 114k | { \ | 430 | 114k | TYPE operand = slot (TYPE); \ | 431 | 114k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 114k | d_m3PreloadNext (); \ | 433 | 114k | TYPE result; \ | 434 | 114k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 114k | * dest = result; REG = result; \ | 436 | 114k | nextOpPreloaded (); \ | 437 | 114k | } \ |
m3_compile.c:op_f32_Multiply_rs_f Line | Count | Source | 428 | 209k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 209k | { \ | 430 | 209k | TYPE operand = slot (TYPE); \ | 431 | 209k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 209k | d_m3PreloadNext (); \ | 433 | 209k | TYPE result; \ | 434 | 209k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 209k | * dest = result; REG = result; \ | 436 | 209k | nextOpPreloaded (); \ | 437 | 209k | } \ |
m3_compile.c:op_f32_Divide_rs_f Line | Count | Source | 428 | 2.89k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 2.89k | { \ | 430 | 2.89k | TYPE operand = slot (TYPE); \ | 431 | 2.89k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 2.89k | d_m3PreloadNext (); \ | 433 | 2.89k | TYPE result; \ | 434 | 2.89k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 2.89k | * dest = result; REG = result; \ | 436 | 2.89k | nextOpPreloaded (); \ | 437 | 2.89k | } \ |
m3_compile.c:op_f64_Add_rs_f Line | Count | Source | 428 | 192k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 192k | { \ | 430 | 192k | TYPE operand = slot (TYPE); \ | 431 | 192k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 192k | d_m3PreloadNext (); \ | 433 | 192k | TYPE result; \ | 434 | 192k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 192k | * dest = result; REG = result; \ | 436 | 192k | nextOpPreloaded (); \ | 437 | 192k | } \ |
m3_compile.c:op_f64_Subtract_rs_f Line | Count | Source | 428 | 180k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 180k | { \ | 430 | 180k | TYPE operand = slot (TYPE); \ | 431 | 180k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 180k | d_m3PreloadNext (); \ | 433 | 180k | TYPE result; \ | 434 | 180k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 180k | * dest = result; REG = result; \ | 436 | 180k | nextOpPreloaded (); \ | 437 | 180k | } \ |
m3_compile.c:op_f64_Multiply_rs_f Line | Count | Source | 428 | 169k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 169k | { \ | 430 | 169k | TYPE operand = slot (TYPE); \ | 431 | 169k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 169k | d_m3PreloadNext (); \ | 433 | 169k | TYPE result; \ | 434 | 169k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 169k | * dest = result; REG = result; \ | 436 | 169k | nextOpPreloaded (); \ | 437 | 169k | } \ |
m3_compile.c:op_f64_Divide_rs_f Line | Count | Source | 428 | 3.24k | d_m3Op(TYPE##_##NAME##_rs_f) \ | 429 | 3.24k | { \ | 430 | 3.24k | TYPE operand = slot (TYPE); \ | 431 | 3.24k | TYPE * dest = slot_ptr (TYPE); \ | 432 | 3.24k | d_m3PreloadNext (); \ | 433 | 3.24k | TYPE result; \ | 434 | 3.24k | OP((result), operand, ((TYPE) REG), ##__VA_ARGS__); \ | 435 | 3.24k | * dest = result; REG = result; \ | 436 | 3.24k | nextOpPreloaded (); \ | 437 | 3.24k | } \ |
|
438 | 5.68M | d_m3Op(TYPE##_##NAME##_ss_f) \ |
439 | 5.68M | { \ |
440 | 5.68M | TYPE operand2 = slot (TYPE); \ |
441 | 5.68M | TYPE operand1 = slot (TYPE); \ |
442 | 5.68M | TYPE * dest = slot_ptr (TYPE); \ |
443 | 5.68M | d_m3PreloadNext (); \ |
444 | 5.68M | TYPE result; \ |
445 | 5.68M | OP((result), operand1, operand2, ##__VA_ARGS__); \ |
446 | 5.68M | * dest = result; REG = result; \ |
447 | 5.68M | nextOpPreloaded (); \ |
448 | 5.68M | } m3_compile.c:op_i32_Add_ss_f Line | Count | Source | 438 | 245k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 245k | { \ | 440 | 245k | TYPE operand2 = slot (TYPE); \ | 441 | 245k | TYPE operand1 = slot (TYPE); \ | 442 | 245k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 245k | d_m3PreloadNext (); \ | 444 | 245k | TYPE result; \ | 445 | 245k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 245k | * dest = result; REG = result; \ | 447 | 245k | nextOpPreloaded (); \ | 448 | 245k | } |
m3_compile.c:op_i32_Subtract_ss_f Line | Count | Source | 438 | 200k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 200k | { \ | 440 | 200k | TYPE operand2 = slot (TYPE); \ | 441 | 200k | TYPE operand1 = slot (TYPE); \ | 442 | 200k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 200k | d_m3PreloadNext (); \ | 444 | 200k | TYPE result; \ | 445 | 200k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 200k | * dest = result; REG = result; \ | 447 | 200k | nextOpPreloaded (); \ | 448 | 200k | } |
m3_compile.c:op_i32_Multiply_ss_f Line | Count | Source | 438 | 263k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 263k | { \ | 440 | 263k | TYPE operand2 = slot (TYPE); \ | 441 | 263k | TYPE operand1 = slot (TYPE); \ | 442 | 263k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 263k | d_m3PreloadNext (); \ | 444 | 263k | TYPE result; \ | 445 | 263k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 263k | * dest = result; REG = result; \ | 447 | 263k | nextOpPreloaded (); \ | 448 | 263k | } |
m3_compile.c:op_u32_And_ss_f Line | Count | Source | 438 | 259k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 259k | { \ | 440 | 259k | TYPE operand2 = slot (TYPE); \ | 441 | 259k | TYPE operand1 = slot (TYPE); \ | 442 | 259k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 259k | d_m3PreloadNext (); \ | 444 | 259k | TYPE result; \ | 445 | 259k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 259k | * dest = result; REG = result; \ | 447 | 259k | nextOpPreloaded (); \ | 448 | 259k | } |
m3_compile.c:op_u32_Or_ss_f Line | Count | Source | 438 | 272k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 272k | { \ | 440 | 272k | TYPE operand2 = slot (TYPE); \ | 441 | 272k | TYPE operand1 = slot (TYPE); \ | 442 | 272k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 272k | d_m3PreloadNext (); \ | 444 | 272k | TYPE result; \ | 445 | 272k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 272k | * dest = result; REG = result; \ | 447 | 272k | nextOpPreloaded (); \ | 448 | 272k | } |
m3_compile.c:op_u32_Xor_ss_f Line | Count | Source | 438 | 357k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 357k | { \ | 440 | 357k | TYPE operand2 = slot (TYPE); \ | 441 | 357k | TYPE operand1 = slot (TYPE); \ | 442 | 357k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 357k | d_m3PreloadNext (); \ | 444 | 357k | TYPE result; \ | 445 | 357k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 357k | * dest = result; REG = result; \ | 447 | 357k | nextOpPreloaded (); \ | 448 | 357k | } |
m3_compile.c:op_u32_ShiftLeft_ss_f Line | Count | Source | 438 | 251k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 251k | { \ | 440 | 251k | TYPE operand2 = slot (TYPE); \ | 441 | 251k | TYPE operand1 = slot (TYPE); \ | 442 | 251k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 251k | d_m3PreloadNext (); \ | 444 | 251k | TYPE result; \ | 445 | 251k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 251k | * dest = result; REG = result; \ | 447 | 251k | nextOpPreloaded (); \ | 448 | 251k | } |
m3_compile.c:op_i32_ShiftRight_ss_f Line | Count | Source | 438 | 269k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 269k | { \ | 440 | 269k | TYPE operand2 = slot (TYPE); \ | 441 | 269k | TYPE operand1 = slot (TYPE); \ | 442 | 269k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 269k | d_m3PreloadNext (); \ | 444 | 269k | TYPE result; \ | 445 | 269k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 269k | * dest = result; REG = result; \ | 447 | 269k | nextOpPreloaded (); \ | 448 | 269k | } |
m3_compile.c:op_u32_ShiftRight_ss_f Line | Count | Source | 438 | 235k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 235k | { \ | 440 | 235k | TYPE operand2 = slot (TYPE); \ | 441 | 235k | TYPE operand1 = slot (TYPE); \ | 442 | 235k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 235k | d_m3PreloadNext (); \ | 444 | 235k | TYPE result; \ | 445 | 235k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 235k | * dest = result; REG = result; \ | 447 | 235k | nextOpPreloaded (); \ | 448 | 235k | } |
m3_compile.c:op_i64_Add_ss_f Line | Count | Source | 438 | 193k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 193k | { \ | 440 | 193k | TYPE operand2 = slot (TYPE); \ | 441 | 193k | TYPE operand1 = slot (TYPE); \ | 442 | 193k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 193k | d_m3PreloadNext (); \ | 444 | 193k | TYPE result; \ | 445 | 193k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 193k | * dest = result; REG = result; \ | 447 | 193k | nextOpPreloaded (); \ | 448 | 193k | } |
m3_compile.c:op_i64_Subtract_ss_f Line | Count | Source | 438 | 461k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 461k | { \ | 440 | 461k | TYPE operand2 = slot (TYPE); \ | 441 | 461k | TYPE operand1 = slot (TYPE); \ | 442 | 461k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 461k | d_m3PreloadNext (); \ | 444 | 461k | TYPE result; \ | 445 | 461k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 461k | * dest = result; REG = result; \ | 447 | 461k | nextOpPreloaded (); \ | 448 | 461k | } |
m3_compile.c:op_i64_Multiply_ss_f Line | Count | Source | 438 | 448k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 448k | { \ | 440 | 448k | TYPE operand2 = slot (TYPE); \ | 441 | 448k | TYPE operand1 = slot (TYPE); \ | 442 | 448k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 448k | d_m3PreloadNext (); \ | 444 | 448k | TYPE result; \ | 445 | 448k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 448k | * dest = result; REG = result; \ | 447 | 448k | nextOpPreloaded (); \ | 448 | 448k | } |
m3_compile.c:op_u64_And_ss_f Line | Count | Source | 438 | 365k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 365k | { \ | 440 | 365k | TYPE operand2 = slot (TYPE); \ | 441 | 365k | TYPE operand1 = slot (TYPE); \ | 442 | 365k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 365k | d_m3PreloadNext (); \ | 444 | 365k | TYPE result; \ | 445 | 365k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 365k | * dest = result; REG = result; \ | 447 | 365k | nextOpPreloaded (); \ | 448 | 365k | } |
m3_compile.c:op_u64_Or_ss_f Line | Count | Source | 438 | 188k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 188k | { \ | 440 | 188k | TYPE operand2 = slot (TYPE); \ | 441 | 188k | TYPE operand1 = slot (TYPE); \ | 442 | 188k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 188k | d_m3PreloadNext (); \ | 444 | 188k | TYPE result; \ | 445 | 188k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 188k | * dest = result; REG = result; \ | 447 | 188k | nextOpPreloaded (); \ | 448 | 188k | } |
m3_compile.c:op_u64_Xor_ss_f Line | Count | Source | 438 | 139k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 139k | { \ | 440 | 139k | TYPE operand2 = slot (TYPE); \ | 441 | 139k | TYPE operand1 = slot (TYPE); \ | 442 | 139k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 139k | d_m3PreloadNext (); \ | 444 | 139k | TYPE result; \ | 445 | 139k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 139k | * dest = result; REG = result; \ | 447 | 139k | nextOpPreloaded (); \ | 448 | 139k | } |
m3_compile.c:op_u64_ShiftLeft_ss_f Line | Count | Source | 438 | 60.8k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 60.8k | { \ | 440 | 60.8k | TYPE operand2 = slot (TYPE); \ | 441 | 60.8k | TYPE operand1 = slot (TYPE); \ | 442 | 60.8k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 60.8k | d_m3PreloadNext (); \ | 444 | 60.8k | TYPE result; \ | 445 | 60.8k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 60.8k | * dest = result; REG = result; \ | 447 | 60.8k | nextOpPreloaded (); \ | 448 | 60.8k | } |
m3_compile.c:op_i64_ShiftRight_ss_f Line | Count | Source | 438 | 209k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 209k | { \ | 440 | 209k | TYPE operand2 = slot (TYPE); \ | 441 | 209k | TYPE operand1 = slot (TYPE); \ | 442 | 209k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 209k | d_m3PreloadNext (); \ | 444 | 209k | TYPE result; \ | 445 | 209k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 209k | * dest = result; REG = result; \ | 447 | 209k | nextOpPreloaded (); \ | 448 | 209k | } |
m3_compile.c:op_u64_ShiftRight_ss_f Line | Count | Source | 438 | 317k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 317k | { \ | 440 | 317k | TYPE operand2 = slot (TYPE); \ | 441 | 317k | TYPE operand1 = slot (TYPE); \ | 442 | 317k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 317k | d_m3PreloadNext (); \ | 444 | 317k | TYPE result; \ | 445 | 317k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 317k | * dest = result; REG = result; \ | 447 | 317k | nextOpPreloaded (); \ | 448 | 317k | } |
m3_compile.c:op_f32_Add_ss_f Line | Count | Source | 438 | 159k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 159k | { \ | 440 | 159k | TYPE operand2 = slot (TYPE); \ | 441 | 159k | TYPE operand1 = slot (TYPE); \ | 442 | 159k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 159k | d_m3PreloadNext (); \ | 444 | 159k | TYPE result; \ | 445 | 159k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 159k | * dest = result; REG = result; \ | 447 | 159k | nextOpPreloaded (); \ | 448 | 159k | } |
m3_compile.c:op_f32_Subtract_ss_f Line | Count | Source | 438 | 155k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 155k | { \ | 440 | 155k | TYPE operand2 = slot (TYPE); \ | 441 | 155k | TYPE operand1 = slot (TYPE); \ | 442 | 155k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 155k | d_m3PreloadNext (); \ | 444 | 155k | TYPE result; \ | 445 | 155k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 155k | * dest = result; REG = result; \ | 447 | 155k | nextOpPreloaded (); \ | 448 | 155k | } |
m3_compile.c:op_f32_Multiply_ss_f Line | Count | Source | 438 | 125k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 125k | { \ | 440 | 125k | TYPE operand2 = slot (TYPE); \ | 441 | 125k | TYPE operand1 = slot (TYPE); \ | 442 | 125k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 125k | d_m3PreloadNext (); \ | 444 | 125k | TYPE result; \ | 445 | 125k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 125k | * dest = result; REG = result; \ | 447 | 125k | nextOpPreloaded (); \ | 448 | 125k | } |
m3_compile.c:op_f32_Divide_ss_f Line | Count | Source | 438 | 3.42k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 3.42k | { \ | 440 | 3.42k | TYPE operand2 = slot (TYPE); \ | 441 | 3.42k | TYPE operand1 = slot (TYPE); \ | 442 | 3.42k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 3.42k | d_m3PreloadNext (); \ | 444 | 3.42k | TYPE result; \ | 445 | 3.42k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 3.42k | * dest = result; REG = result; \ | 447 | 3.42k | nextOpPreloaded (); \ | 448 | 3.42k | } |
m3_compile.c:op_f64_Add_ss_f Line | Count | Source | 438 | 159k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 159k | { \ | 440 | 159k | TYPE operand2 = slot (TYPE); \ | 441 | 159k | TYPE operand1 = slot (TYPE); \ | 442 | 159k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 159k | d_m3PreloadNext (); \ | 444 | 159k | TYPE result; \ | 445 | 159k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 159k | * dest = result; REG = result; \ | 447 | 159k | nextOpPreloaded (); \ | 448 | 159k | } |
m3_compile.c:op_f64_Subtract_ss_f Line | Count | Source | 438 | 162k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 162k | { \ | 440 | 162k | TYPE operand2 = slot (TYPE); \ | 441 | 162k | TYPE operand1 = slot (TYPE); \ | 442 | 162k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 162k | d_m3PreloadNext (); \ | 444 | 162k | TYPE result; \ | 445 | 162k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 162k | * dest = result; REG = result; \ | 447 | 162k | nextOpPreloaded (); \ | 448 | 162k | } |
m3_compile.c:op_f64_Multiply_ss_f Line | Count | Source | 438 | 168k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 168k | { \ | 440 | 168k | TYPE operand2 = slot (TYPE); \ | 441 | 168k | TYPE operand1 = slot (TYPE); \ | 442 | 168k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 168k | d_m3PreloadNext (); \ | 444 | 168k | TYPE result; \ | 445 | 168k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 168k | * dest = result; REG = result; \ | 447 | 168k | nextOpPreloaded (); \ | 448 | 168k | } |
m3_compile.c:op_f64_Divide_ss_f Line | Count | Source | 438 | 7.01k | d_m3Op(TYPE##_##NAME##_ss_f) \ | 439 | 7.01k | { \ | 440 | 7.01k | TYPE operand2 = slot (TYPE); \ | 441 | 7.01k | TYPE operand1 = slot (TYPE); \ | 442 | 7.01k | TYPE * dest = slot_ptr (TYPE); \ | 443 | 7.01k | d_m3PreloadNext (); \ | 444 | 7.01k | TYPE result; \ | 445 | 7.01k | OP((result), operand1, operand2, ##__VA_ARGS__); \ | 446 | 7.01k | * dest = result; REG = result; \ | 447 | 7.01k | nextOpPreloaded (); \ | 448 | 7.01k | } |
|
449 | | |
450 | | # define d_m3FoldOpMacro(REG, TYPE, NAME, OP, ...) \ |
451 | 2.00M | d_m3Op(TYPE##_##NAME##_sr_f) \ |
452 | 2.00M | { \ |
453 | 2.00M | TYPE operand = slot (TYPE); \ |
454 | 2.00M | TYPE * dest = slot_ptr (TYPE); \ |
455 | 2.00M | d_m3PreloadNext (); \ |
456 | 2.00M | TYPE result; \ |
457 | 2.00M | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ |
458 | 2.00M | * dest = result; REG = result; \ |
459 | 2.00M | nextOpPreloaded (); \ |
460 | 2.00M | } \ m3_compile.c:op_i32_Subtract_sr_f Line | Count | Source | 451 | 170k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 170k | { \ | 453 | 170k | TYPE operand = slot (TYPE); \ | 454 | 170k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 170k | d_m3PreloadNext (); \ | 456 | 170k | TYPE result; \ | 457 | 170k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 170k | * dest = result; REG = result; \ | 459 | 170k | nextOpPreloaded (); \ | 460 | 170k | } \ |
m3_compile.c:op_u32_ShiftLeft_sr_f Line | Count | Source | 451 | 255k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 255k | { \ | 453 | 255k | TYPE operand = slot (TYPE); \ | 454 | 255k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 255k | d_m3PreloadNext (); \ | 456 | 255k | TYPE result; \ | 457 | 255k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 255k | * dest = result; REG = result; \ | 459 | 255k | nextOpPreloaded (); \ | 460 | 255k | } \ |
m3_compile.c:op_i32_ShiftRight_sr_f Line | Count | Source | 451 | 295k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 295k | { \ | 453 | 295k | TYPE operand = slot (TYPE); \ | 454 | 295k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 295k | d_m3PreloadNext (); \ | 456 | 295k | TYPE result; \ | 457 | 295k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 295k | * dest = result; REG = result; \ | 459 | 295k | nextOpPreloaded (); \ | 460 | 295k | } \ |
m3_compile.c:op_u32_ShiftRight_sr_f Line | Count | Source | 451 | 370k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 370k | { \ | 453 | 370k | TYPE operand = slot (TYPE); \ | 454 | 370k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 370k | d_m3PreloadNext (); \ | 456 | 370k | TYPE result; \ | 457 | 370k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 370k | * dest = result; REG = result; \ | 459 | 370k | nextOpPreloaded (); \ | 460 | 370k | } \ |
m3_compile.c:op_i64_Subtract_sr_f Line | Count | Source | 451 | 261k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 261k | { \ | 453 | 261k | TYPE operand = slot (TYPE); \ | 454 | 261k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 261k | d_m3PreloadNext (); \ | 456 | 261k | TYPE result; \ | 457 | 261k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 261k | * dest = result; REG = result; \ | 459 | 261k | nextOpPreloaded (); \ | 460 | 261k | } \ |
m3_compile.c:op_u64_ShiftLeft_sr_f Line | Count | Source | 451 | 129k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 129k | { \ | 453 | 129k | TYPE operand = slot (TYPE); \ | 454 | 129k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 129k | d_m3PreloadNext (); \ | 456 | 129k | TYPE result; \ | 457 | 129k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 129k | * dest = result; REG = result; \ | 459 | 129k | nextOpPreloaded (); \ | 460 | 129k | } \ |
m3_compile.c:op_i64_ShiftRight_sr_f Line | Count | Source | 451 | 201k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 201k | { \ | 453 | 201k | TYPE operand = slot (TYPE); \ | 454 | 201k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 201k | d_m3PreloadNext (); \ | 456 | 201k | TYPE result; \ | 457 | 201k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 201k | * dest = result; REG = result; \ | 459 | 201k | nextOpPreloaded (); \ | 460 | 201k | } \ |
m3_compile.c:op_u64_ShiftRight_sr_f Line | Count | Source | 451 | 157k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 157k | { \ | 453 | 157k | TYPE operand = slot (TYPE); \ | 454 | 157k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 157k | d_m3PreloadNext (); \ | 456 | 157k | TYPE result; \ | 457 | 157k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 157k | * dest = result; REG = result; \ | 459 | 157k | nextOpPreloaded (); \ | 460 | 157k | } \ |
m3_compile.c:op_f32_Subtract_sr_f Line | Count | Source | 451 | 92.0k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 92.0k | { \ | 453 | 92.0k | TYPE operand = slot (TYPE); \ | 454 | 92.0k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 92.0k | d_m3PreloadNext (); \ | 456 | 92.0k | TYPE result; \ | 457 | 92.0k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 92.0k | * dest = result; REG = result; \ | 459 | 92.0k | nextOpPreloaded (); \ | 460 | 92.0k | } \ |
m3_compile.c:op_f32_Divide_sr_f Line | Count | Source | 451 | 1.46k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 1.46k | { \ | 453 | 1.46k | TYPE operand = slot (TYPE); \ | 454 | 1.46k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 1.46k | d_m3PreloadNext (); \ | 456 | 1.46k | TYPE result; \ | 457 | 1.46k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 1.46k | * dest = result; REG = result; \ | 459 | 1.46k | nextOpPreloaded (); \ | 460 | 1.46k | } \ |
m3_compile.c:op_f64_Subtract_sr_f Line | Count | Source | 451 | 70.0k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 70.0k | { \ | 453 | 70.0k | TYPE operand = slot (TYPE); \ | 454 | 70.0k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 70.0k | d_m3PreloadNext (); \ | 456 | 70.0k | TYPE result; \ | 457 | 70.0k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 70.0k | * dest = result; REG = result; \ | 459 | 70.0k | nextOpPreloaded (); \ | 460 | 70.0k | } \ |
m3_compile.c:op_f64_Divide_sr_f Line | Count | Source | 451 | 4.32k | d_m3Op(TYPE##_##NAME##_sr_f) \ | 452 | 4.32k | { \ | 453 | 4.32k | TYPE operand = slot (TYPE); \ | 454 | 4.32k | TYPE * dest = slot_ptr (TYPE); \ | 455 | 4.32k | d_m3PreloadNext (); \ | 456 | 4.32k | TYPE result; \ | 457 | 4.32k | OP((result), ((TYPE) REG), operand, ##__VA_ARGS__); \ | 458 | 4.32k | * dest = result; REG = result; \ | 459 | 4.32k | nextOpPreloaded (); \ | 460 | 4.32k | } \ |
|
461 | | d_m3FoldCommutativeOpMacro(REG, TYPE, NAME, OP, ##__VA_ARGS__) |
462 | | |
463 | | // A commutative operator has no _sr form in its variant table, so the fold set skips |
464 | | // the _sr_f handler it could never be patched to. |
465 | | #define d_m3FoldOp_i(TYPE, NAME, OP, ...) d_m3FoldOpMacro ( _r0, TYPE, NAME, OP, ##__VA_ARGS__) |
466 | | #define d_m3FoldOp_f(TYPE, NAME, OP, ...) d_m3FoldOpMacro (_fp0, TYPE, NAME, OP, ##__VA_ARGS__) |
467 | | #define d_m3FoldCommutativeOp_i(TYPE, NAME, OP, ...) d_m3FoldCommutativeOpMacro ( _r0, TYPE, NAME, OP, ##__VA_ARGS__) |
468 | | #define d_m3FoldCommutativeOp_f(TYPE, NAME, OP, ...) d_m3FoldCommutativeOpMacro (_fp0, TYPE, NAME, OP, ##__VA_ARGS__) |
469 | | |
470 | 376k | d_m3FoldCommutativeOp_i(i32, Add, M3_FUNC, OP_ADD_32) |
471 | 601k | d_m3FoldOp_i (i32, Subtract, M3_FUNC, OP_SUB_32) |
472 | 610k | d_m3FoldCommutativeOp_i(i32, Multiply, M3_FUNC, OP_MUL_32) |
473 | 545k | d_m3FoldCommutativeOp_i(u32, And, M3_OPER, &) |
474 | 387k | d_m3FoldCommutativeOp_i(u32, Or, M3_OPER, |) |
475 | 630k | d_m3FoldCommutativeOp_i(u32, Xor, M3_OPER, ^) |
476 | 763k | d_m3FoldOp_i (u32, ShiftLeft, M3_FUNC, OP_SHL_32) |
477 | 793k | d_m3FoldOp_i (i32, ShiftRight, M3_FUNC, OP_SHR_32) |
478 | 778k | d_m3FoldOp_i (u32, ShiftRight, M3_FUNC, OP_SHR_32) |
479 | | |
480 | 525k | d_m3FoldCommutativeOp_i(i64, Add, M3_FUNC, OP_ADD_64) |
481 | 965k | d_m3FoldOp_i (i64, Subtract, M3_FUNC, OP_SUB_64) |
482 | 794k | d_m3FoldCommutativeOp_i(i64, Multiply, M3_FUNC, OP_MUL_64) |
483 | 690k | d_m3FoldCommutativeOp_i(u64, And, M3_OPER, &) |
484 | 469k | d_m3FoldCommutativeOp_i(u64, Or, M3_OPER, |) |
485 | 248k | d_m3FoldCommutativeOp_i(u64, Xor, M3_OPER, ^) |
486 | 339k | d_m3FoldOp_i (u64, ShiftLeft, M3_FUNC, OP_SHL_64) |
487 | 507k | d_m3FoldOp_i (i64, ShiftRight, M3_FUNC, OP_SHR_64) |
488 | 622k | d_m3FoldOp_i (u64, ShiftRight, M3_FUNC, OP_SHR_64) |
489 | | |
490 | | # if d_m3HasFloat |
491 | | // Without these a float result round-trips through _fp0 and a separate SetSlot, which |
492 | | // on float-heavy code is about one dispatch in five. |
493 | 255k | d_m3FoldCommutativeOp_f(f32, Add, M3_OPER_A, +, canon_nan_f32) |
494 | 362k | d_m3FoldOp_f (f32, Subtract, M3_OPER_A, -, canon_nan_f32) |
495 | 334k | d_m3FoldCommutativeOp_f(f32, Multiply, M3_OPER_A, *, canon_nan_f32) |
496 | 7.77k | d_m3FoldOp_f (f32, Divide, M3_OPER_A, /, canon_nan_f32) |
497 | 351k | d_m3FoldCommutativeOp_f(f64, Add, M3_OPER_A, +, canon_nan_f64) |
498 | 413k | d_m3FoldOp_f (f64, Subtract, M3_OPER_A, -, canon_nan_f64) |
499 | 338k | d_m3FoldCommutativeOp_f(f64, Multiply, M3_OPER_A, *, canon_nan_f64) |
500 | 14.5k | d_m3FoldOp_f (f64, Divide, M3_OPER_A, /, canon_nan_f64) |
501 | | #endif |
502 | | |
503 | | #endif // d_m3FoldSetLocal |
504 | | |
505 | | #if d_m3HasFloat |
506 | | d_m3CommutativeArithOp_f(f32, Add, +) d_m3CommutativeArithOp_f(f64, Add, +) |
507 | | d_m3CommutativeArithOp_f(f32, Multiply, *) d_m3CommutativeArithOp_f(f64, Multiply, *) |
508 | | d_m3ArithOp_f(f32, Subtract, -) d_m3ArithOp_f(f64, Subtract, -) |
509 | | d_m3ArithOp_f(f32, Divide, /) d_m3ArithOp_f(f64, Divide, /) |
510 | | #endif |
511 | | |
512 | | d_m3OpFunc_i(u32, Rotl, rotl32) |
513 | | d_m3OpFunc_i(u32, Rotr, rotr32) |
514 | | d_m3OpFunc_i(u64, Rotl, rotl64) |
515 | | d_m3OpFunc_i(u64, Rotr, rotr64) |
516 | | |
517 | 42.9k | d_m3OpMacro_i(u32, Divide, OP_DIV_U); |
518 | 46.6k | d_m3OpMacro_i(i32, Divide, OP_DIV_S, INT32_MIN); |
519 | 38.0k | d_m3OpMacro_i(u64, Divide, OP_DIV_U); |
520 | 61.4k | d_m3OpMacro_i(i64, Divide, OP_DIV_S, INT64_MIN); |
521 | | |
522 | 41.8k | d_m3OpMacro_i(u32, Remainder, OP_REM_U); |
523 | 50.8k | d_m3OpMacro_i(i32, Remainder, OP_REM_S, INT32_MIN); |
524 | 45.9k | d_m3OpMacro_i(u64, Remainder, OP_REM_U); |
525 | 55.2k | d_m3OpMacro_i(i64, Remainder, OP_REM_S, INT64_MIN); |
526 | | |
527 | | #if d_m3HasFloat |
528 | | d_m3ArithOpFunc_f(f32, Min, min_f32); |
529 | | d_m3ArithOpFunc_f(f32, Max, max_f32); |
530 | | d_m3ArithOpFunc_f(f64, Min, min_f64); |
531 | | d_m3ArithOpFunc_f(f64, Max, max_f64); |
532 | | |
533 | | // copysign is defined bitwise and keeps its operand's payload - see canon_nan_f32 |
534 | | d_m3OpFunc_f(f32, CopySign, copysignf); |
535 | | d_m3OpFunc_f(f64, CopySign, copysign); |
536 | | #endif |
537 | | |
538 | | // Unary operations |
539 | | // Note: This macro follows the principle of d_m3OpMacro |
540 | | |
541 | | #define d_m3UnaryMacro(RES, REG, TYPE, NAME, OP, ...) \ |
542 | 41.3M | d_m3Op(TYPE##_##NAME##_r) \ |
543 | 41.3M | { \ |
544 | 41.3M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ |
545 | 41.3M | nextOp (); \ |
546 | 41.3M | } \ m3_compile.c:op_i64_EqualToZero_r Line | Count | Source | 542 | 1.31M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.31M | { \ | 544 | 1.31M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.31M | nextOp (); \ | 546 | 1.31M | } \ |
m3_compile.c:op_i32_EqualToZero_r Line | Count | Source | 542 | 4.18M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 4.18M | { \ | 544 | 4.18M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 4.18M | nextOp (); \ | 546 | 4.18M | } \ |
m3_compile.c:op_u32_Clz_r Line | Count | Source | 542 | 3.11M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 3.11M | { \ | 544 | 3.11M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 3.11M | nextOp (); \ | 546 | 3.11M | } \ |
m3_compile.c:op_u32_Ctz_r Line | Count | Source | 542 | 2.20M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 2.20M | { \ | 544 | 2.20M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 2.20M | nextOp (); \ | 546 | 2.20M | } \ |
m3_compile.c:op_u32_Popcnt_r Line | Count | Source | 542 | 3.22M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 3.22M | { \ | 544 | 3.22M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 3.22M | nextOp (); \ | 546 | 3.22M | } \ |
m3_compile.c:op_u64_Clz_r Line | Count | Source | 542 | 2.76M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 2.76M | { \ | 544 | 2.76M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 2.76M | nextOp (); \ | 546 | 2.76M | } \ |
m3_compile.c:op_u64_Ctz_r Line | Count | Source | 542 | 2.32M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 2.32M | { \ | 544 | 2.32M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 2.32M | nextOp (); \ | 546 | 2.32M | } \ |
m3_compile.c:op_u64_Popcnt_r Line | Count | Source | 542 | 1.66M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.66M | { \ | 544 | 1.66M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.66M | nextOp (); \ | 546 | 1.66M | } \ |
m3_compile.c:op_f32_Abs_r Line | Count | Source | 542 | 974k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 974k | { \ | 544 | 974k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 974k | nextOp (); \ | 546 | 974k | } \ |
m3_compile.c:op_f32_Negate_r Line | Count | Source | 542 | 1.09M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.09M | { \ | 544 | 1.09M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.09M | nextOp (); \ | 546 | 1.09M | } \ |
m3_compile.c:op_f32_Ceil_r Line | Count | Source | 542 | 1.39M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.39M | { \ | 544 | 1.39M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.39M | nextOp (); \ | 546 | 1.39M | } \ |
m3_compile.c:op_f32_Floor_r Line | Count | Source | 542 | 1.13M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.13M | { \ | 544 | 1.13M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.13M | nextOp (); \ | 546 | 1.13M | } \ |
m3_compile.c:op_f32_Trunc_r Line | Count | Source | 542 | 1.49M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.49M | { \ | 544 | 1.49M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.49M | nextOp (); \ | 546 | 1.49M | } \ |
m3_compile.c:op_f32_Nearest_r Line | Count | Source | 542 | 573k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 573k | { \ | 544 | 573k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 573k | nextOp (); \ | 546 | 573k | } \ |
m3_compile.c:op_f32_Sqrt_r Line | Count | Source | 542 | 13.7k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 13.7k | { \ | 544 | 13.7k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 13.7k | nextOp (); \ | 546 | 13.7k | } \ |
m3_compile.c:op_f64_Abs_r Line | Count | Source | 542 | 396k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 396k | { \ | 544 | 396k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 396k | nextOp (); \ | 546 | 396k | } \ |
m3_compile.c:op_f64_Negate_r Line | Count | Source | 542 | 775k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 775k | { \ | 544 | 775k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 775k | nextOp (); \ | 546 | 775k | } \ |
m3_compile.c:op_f64_Ceil_r Line | Count | Source | 542 | 650k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 650k | { \ | 544 | 650k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 650k | nextOp (); \ | 546 | 650k | } \ |
m3_compile.c:op_f64_Floor_r Line | Count | Source | 542 | 746k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 746k | { \ | 544 | 746k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 746k | nextOp (); \ | 546 | 746k | } \ |
m3_compile.c:op_f64_Trunc_r Line | Count | Source | 542 | 958k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 958k | { \ | 544 | 958k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 958k | nextOp (); \ | 546 | 958k | } \ |
m3_compile.c:op_f64_Nearest_r Line | Count | Source | 542 | 544k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 544k | { \ | 544 | 544k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 544k | nextOp (); \ | 546 | 544k | } \ |
m3_compile.c:op_f64_Sqrt_r Line | Count | Source | 542 | 12.4k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 12.4k | { \ | 544 | 12.4k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 12.4k | nextOp (); \ | 546 | 12.4k | } \ |
m3_compile.c:op_i32_Extend8_s_r Line | Count | Source | 542 | 2.42M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 2.42M | { \ | 544 | 2.42M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 2.42M | nextOp (); \ | 546 | 2.42M | } \ |
m3_compile.c:op_i32_Extend16_s_r Line | Count | Source | 542 | 3.77M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 3.77M | { \ | 544 | 3.77M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 3.77M | nextOp (); \ | 546 | 3.77M | } \ |
m3_compile.c:op_i64_Extend8_s_r Line | Count | Source | 542 | 1.25M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.25M | { \ | 544 | 1.25M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.25M | nextOp (); \ | 546 | 1.25M | } \ |
m3_compile.c:op_i64_Extend16_s_r Line | Count | Source | 542 | 1.44M | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 1.44M | { \ | 544 | 1.44M | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 1.44M | nextOp (); \ | 546 | 1.44M | } \ |
m3_compile.c:op_i64_Extend32_s_r Line | Count | Source | 542 | 921k | d_m3Op(TYPE##_##NAME##_r) \ | 543 | 921k | { \ | 544 | 921k | OP((RES), (TYPE) REG, ##__VA_ARGS__); \ | 545 | 921k | nextOp (); \ | 546 | 921k | } \ |
|
547 | 99.2M | d_m3Op(TYPE##_##NAME##_s) \ |
548 | 99.2M | { \ |
549 | 99.2M | TYPE operand = slot (TYPE); \ |
550 | 99.2M | OP((RES), operand, ##__VA_ARGS__); \ |
551 | 99.2M | nextOp (); \ |
552 | 99.2M | } m3_compile.c:op_i64_EqualToZero_s Line | Count | Source | 547 | 2.76M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 2.76M | { \ | 549 | 2.76M | TYPE operand = slot (TYPE); \ | 550 | 2.76M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 2.76M | nextOp (); \ | 552 | 2.76M | } |
m3_compile.c:op_i32_EqualToZero_s Line | Count | Source | 547 | 10.1M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 10.1M | { \ | 549 | 10.1M | TYPE operand = slot (TYPE); \ | 550 | 10.1M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 10.1M | nextOp (); \ | 552 | 10.1M | } |
m3_compile.c:op_u32_Clz_s Line | Count | Source | 547 | 4.42M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 4.42M | { \ | 549 | 4.42M | TYPE operand = slot (TYPE); \ | 550 | 4.42M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 4.42M | nextOp (); \ | 552 | 4.42M | } |
m3_compile.c:op_u32_Ctz_s Line | Count | Source | 547 | 4.74M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 4.74M | { \ | 549 | 4.74M | TYPE operand = slot (TYPE); \ | 550 | 4.74M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 4.74M | nextOp (); \ | 552 | 4.74M | } |
m3_compile.c:op_u32_Popcnt_s Line | Count | Source | 547 | 5.61M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 5.61M | { \ | 549 | 5.61M | TYPE operand = slot (TYPE); \ | 550 | 5.61M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 5.61M | nextOp (); \ | 552 | 5.61M | } |
m3_compile.c:op_u64_Clz_s Line | Count | Source | 547 | 5.38M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 5.38M | { \ | 549 | 5.38M | TYPE operand = slot (TYPE); \ | 550 | 5.38M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 5.38M | nextOp (); \ | 552 | 5.38M | } |
m3_compile.c:op_u64_Ctz_s Line | Count | Source | 547 | 8.73M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 8.73M | { \ | 549 | 8.73M | TYPE operand = slot (TYPE); \ | 550 | 8.73M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 8.73M | nextOp (); \ | 552 | 8.73M | } |
m3_compile.c:op_u64_Popcnt_s Line | Count | Source | 547 | 5.04M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 5.04M | { \ | 549 | 5.04M | TYPE operand = slot (TYPE); \ | 550 | 5.04M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 5.04M | nextOp (); \ | 552 | 5.04M | } |
m3_compile.c:op_f32_Abs_s Line | Count | Source | 547 | 2.92M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 2.92M | { \ | 549 | 2.92M | TYPE operand = slot (TYPE); \ | 550 | 2.92M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 2.92M | nextOp (); \ | 552 | 2.92M | } |
m3_compile.c:op_f32_Negate_s Line | Count | Source | 547 | 2.34M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 2.34M | { \ | 549 | 2.34M | TYPE operand = slot (TYPE); \ | 550 | 2.34M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 2.34M | nextOp (); \ | 552 | 2.34M | } |
m3_compile.c:op_f32_Ceil_s Line | Count | Source | 547 | 2.56M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 2.56M | { \ | 549 | 2.56M | TYPE operand = slot (TYPE); \ | 550 | 2.56M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 2.56M | nextOp (); \ | 552 | 2.56M | } |
m3_compile.c:op_f32_Floor_s Line | Count | Source | 547 | 3.11M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 3.11M | { \ | 549 | 3.11M | TYPE operand = slot (TYPE); \ | 550 | 3.11M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 3.11M | nextOp (); \ | 552 | 3.11M | } |
m3_compile.c:op_f32_Trunc_s Line | Count | Source | 547 | 3.25M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 3.25M | { \ | 549 | 3.25M | TYPE operand = slot (TYPE); \ | 550 | 3.25M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 3.25M | nextOp (); \ | 552 | 3.25M | } |
m3_compile.c:op_f32_Nearest_s Line | Count | Source | 547 | 1.64M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.64M | { \ | 549 | 1.64M | TYPE operand = slot (TYPE); \ | 550 | 1.64M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.64M | nextOp (); \ | 552 | 1.64M | } |
m3_compile.c:op_f32_Sqrt_s Line | Count | Source | 547 | 16.0k | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 16.0k | { \ | 549 | 16.0k | TYPE operand = slot (TYPE); \ | 550 | 16.0k | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 16.0k | nextOp (); \ | 552 | 16.0k | } |
m3_compile.c:op_f64_Abs_s Line | Count | Source | 547 | 1.69M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.69M | { \ | 549 | 1.69M | TYPE operand = slot (TYPE); \ | 550 | 1.69M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.69M | nextOp (); \ | 552 | 1.69M | } |
m3_compile.c:op_f64_Negate_s Line | Count | Source | 547 | 1.92M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.92M | { \ | 549 | 1.92M | TYPE operand = slot (TYPE); \ | 550 | 1.92M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.92M | nextOp (); \ | 552 | 1.92M | } |
m3_compile.c:op_f64_Ceil_s Line | Count | Source | 547 | 1.87M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.87M | { \ | 549 | 1.87M | TYPE operand = slot (TYPE); \ | 550 | 1.87M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.87M | nextOp (); \ | 552 | 1.87M | } |
m3_compile.c:op_f64_Floor_s Line | Count | Source | 547 | 1.53M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.53M | { \ | 549 | 1.53M | TYPE operand = slot (TYPE); \ | 550 | 1.53M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.53M | nextOp (); \ | 552 | 1.53M | } |
m3_compile.c:op_f64_Trunc_s Line | Count | Source | 547 | 1.36M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.36M | { \ | 549 | 1.36M | TYPE operand = slot (TYPE); \ | 550 | 1.36M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.36M | nextOp (); \ | 552 | 1.36M | } |
m3_compile.c:op_f64_Nearest_s Line | Count | Source | 547 | 1.53M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 1.53M | { \ | 549 | 1.53M | TYPE operand = slot (TYPE); \ | 550 | 1.53M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 1.53M | nextOp (); \ | 552 | 1.53M | } |
m3_compile.c:op_f64_Sqrt_s Line | Count | Source | 547 | 24.9k | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 24.9k | { \ | 549 | 24.9k | TYPE operand = slot (TYPE); \ | 550 | 24.9k | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 24.9k | nextOp (); \ | 552 | 24.9k | } |
m3_compile.c:op_i32_Extend8_s_s Line | Count | Source | 547 | 4.37M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 4.37M | { \ | 549 | 4.37M | TYPE operand = slot (TYPE); \ | 550 | 4.37M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 4.37M | nextOp (); \ | 552 | 4.37M | } |
m3_compile.c:op_i32_Extend16_s_s Line | Count | Source | 547 | 9.37M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 9.37M | { \ | 549 | 9.37M | TYPE operand = slot (TYPE); \ | 550 | 9.37M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 9.37M | nextOp (); \ | 552 | 9.37M | } |
m3_compile.c:op_i64_Extend8_s_s Line | Count | Source | 547 | 5.53M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 5.53M | { \ | 549 | 5.53M | TYPE operand = slot (TYPE); \ | 550 | 5.53M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 5.53M | nextOp (); \ | 552 | 5.53M | } |
m3_compile.c:op_i64_Extend16_s_s Line | Count | Source | 547 | 3.48M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 3.48M | { \ | 549 | 3.48M | TYPE operand = slot (TYPE); \ | 550 | 3.48M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 3.48M | nextOp (); \ | 552 | 3.48M | } |
m3_compile.c:op_i64_Extend32_s_s Line | Count | Source | 547 | 3.76M | d_m3Op(TYPE##_##NAME##_s) \ | 548 | 3.76M | { \ | 549 | 3.76M | TYPE operand = slot (TYPE); \ | 550 | 3.76M | OP((RES), operand, ##__VA_ARGS__); \ | 551 | 3.76M | nextOp (); \ | 552 | 3.76M | } |
|
553 | | |
554 | 116M | #define M3_UNARY(RES, X, OP) (RES) = OP(X) |
555 | 24.4M | #define M3_UNARY_A(RES, X, OP, CANON) (RES) = CANON(OP(X)) |
556 | | |
557 | 104M | #define d_m3UnaryOp_i(TYPE, NAME, OPERATION) d_m3UnaryMacro( _r0, _r0, TYPE, NAME, M3_UNARY, OPERATION) |
558 | 12.1M | #define d_m3UnaryOp_f(TYPE, NAME, OPERATION) d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY, OPERATION) |
559 | 24.4M | #define d_m3UnaryArithOp_f(TYPE, NAME, OPERATION) d_m3UnaryMacro(_fp0, _fp0, TYPE, NAME, M3_UNARY_A, OPERATION, canon_nan_##TYPE) |
560 | | |
561 | | #if d_m3HasFloat |
562 | | // abs and neg are defined bitwise and keep their operand's payload - see canon_nan_f32 |
563 | | d_m3UnaryOp_f(f32, Abs, fabsf); d_m3UnaryOp_f(f64, Abs, fabs); |
564 | | d_m3UnaryArithOp_f(f32, Ceil, ceilf); d_m3UnaryArithOp_f(f64, Ceil, ceil); |
565 | | d_m3UnaryArithOp_f(f32, Floor, floorf); d_m3UnaryArithOp_f(f64, Floor, floor); |
566 | | d_m3UnaryArithOp_f(f32, Trunc, truncf); d_m3UnaryArithOp_f(f64, Trunc, trunc); |
567 | | d_m3UnaryArithOp_f(f32, Sqrt, sqrtf); d_m3UnaryArithOp_f(f64, Sqrt, sqrt); |
568 | | d_m3UnaryArithOp_f(f32, Nearest, rintf); d_m3UnaryArithOp_f(f64, Nearest, rint); |
569 | | # if defined(M3_COMPILER_TCC) |
570 | | d_m3UnaryOp_f(f32, Negate, m3_negf); d_m3UnaryOp_f(f64, Negate, m3_neg); |
571 | | # else |
572 | | d_m3UnaryOp_f(f32, Negate, -); d_m3UnaryOp_f(f64, Negate, -); |
573 | | # endif |
574 | | #endif |
575 | | |
576 | 18.4M | #define OP_EQZ(x) ((x) == 0) |
577 | | |
578 | 14.3M | d_m3UnaryOp_i(i32, EqualToZero, OP_EQZ) |
579 | 4.08M | d_m3UnaryOp_i(i64, EqualToZero, OP_EQZ) |
580 | | |
581 | | // clz(0), ctz(0) results are undefined for rest platforms, fix it |
582 | | #if (defined(__i386__) || defined(__x86_64__)) && !(defined(__AVX2__) || (defined(__ABM__) && defined(__BMI__))) |
583 | | #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) |
584 | | #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) |
585 | | // for 64-bit instructions branchless approach more preferable |
586 | | #define OP_CLZ_64(x) (__builtin_clzll((x) | (1ULL << 0)) + OP_EQZ(x)) |
587 | | #define OP_CTZ_64(x) (__builtin_ctzll((x) | (1ULL << 63)) + OP_EQZ(x)) |
588 | | #elif defined(__ppc__) || defined(__ppc64__) |
589 | | // PowerPC is defined for __builtin_clz(0) and __builtin_ctz(0). |
590 | | // See (https://github.com/aquynh/capstone/blob/master/MathExtras.h#L99) |
591 | | #define OP_CLZ_32(x) __builtin_clz(x) |
592 | | #define OP_CTZ_32(x) __builtin_ctz(x) |
593 | | #define OP_CLZ_64(x) __builtin_clzll(x) |
594 | | #define OP_CTZ_64(x) __builtin_ctzll(x) |
595 | | #else |
596 | 7.54M | #define OP_CLZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_clz(x)) |
597 | 6.94M | #define OP_CTZ_32(x) (M3_UNLIKELY((x) == 0) ? 32 : __builtin_ctz(x)) |
598 | 8.14M | #define OP_CLZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_clzll(x)) |
599 | 11.0M | #define OP_CTZ_64(x) (M3_UNLIKELY((x) == 0) ? 64 : __builtin_ctzll(x)) |
600 | | #endif |
601 | | |
602 | 7.54M | d_m3UnaryOp_i(u32, Clz, OP_CLZ_32) |
603 | 8.14M | d_m3UnaryOp_i(u64, Clz, OP_CLZ_64) |
604 | | |
605 | 6.94M | d_m3UnaryOp_i(u32, Ctz, OP_CTZ_32) |
606 | 11.0M | d_m3UnaryOp_i(u64, Ctz, OP_CTZ_64) |
607 | | |
608 | | d_m3UnaryOp_i(u32, Popcnt, __builtin_popcount) |
609 | | d_m3UnaryOp_i(u64, Popcnt, __builtin_popcountll) |
610 | | |
611 | 2.33M | #define OP_WRAP_I64(X) ((X) & 0x00000000ffffffff) |
612 | | |
613 | | d_m3Op(i32_Wrap_i64_r) |
614 | 1.03M | { |
615 | 1.03M | _r0 = OP_WRAP_I64((i64)_r0); |
616 | 1.03M | nextOp(); |
617 | 1.03M | } |
618 | | |
619 | | d_m3Op(i32_Wrap_i64_s) |
620 | 1.30M | { |
621 | 1.30M | i64 operand = slot(i64); |
622 | 1.30M | _r0 = OP_WRAP_I64(operand); |
623 | 1.30M | nextOp(); |
624 | 1.30M | } |
625 | | |
626 | | // Integer sign extension operations |
627 | 6.79M | #define OP_EXTEND8_S_I32(X) ((int32_t)(int8_t)(X)) |
628 | 13.1M | #define OP_EXTEND16_S_I32(X) ((int32_t)(int16_t)(X)) |
629 | 6.79M | #define OP_EXTEND8_S_I64(X) ((int64_t)(int8_t)(X)) |
630 | 4.93M | #define OP_EXTEND16_S_I64(X) ((int64_t)(int16_t)(X)) |
631 | 4.68M | #define OP_EXTEND32_S_I64(X) ((int64_t)(int32_t)(X)) |
632 | | |
633 | 6.79M | d_m3UnaryOp_i(i32, Extend8_s, OP_EXTEND8_S_I32) |
634 | 13.1M | d_m3UnaryOp_i(i32, Extend16_s, OP_EXTEND16_S_I32) |
635 | 6.79M | d_m3UnaryOp_i(i64, Extend8_s, OP_EXTEND8_S_I64) |
636 | 4.93M | d_m3UnaryOp_i(i64, Extend16_s, OP_EXTEND16_S_I64) |
637 | 4.68M | d_m3UnaryOp_i(i64, Extend32_s, OP_EXTEND32_S_I64) |
638 | | |
639 | | #if d_m3HasWideArithmetic |
640 | | |
641 | | // Wide arithmetic. Every operand is in a slot, the top of the stack first, and |
642 | | // the last immediate is the slot the low half of the result goes to; the high |
643 | | // half goes to _r0. That slot may be one an operand was just read from, so it is |
644 | | // only written once all of them are. |
645 | | d_m3Op(i64_Add128) |
646 | 547k | { |
647 | 547k | u64 rhsHigh = slot (u64); |
648 | 547k | u64 rhsLow = slot (u64); |
649 | 547k | u64 lhsHigh = slot (u64); |
650 | 547k | u64 lhsLow = slot (u64); |
651 | 547k | u64* low = slot_ptr (u64); |
652 | 547k | d_m3PreloadNext(); |
653 | | |
654 | 547k | u64 sum = lhsLow + rhsLow; |
655 | | |
656 | 547k | *low = sum; |
657 | 547k | _r0 = (i64) (lhsHigh + rhsHigh + (sum < lhsLow)); |
658 | | |
659 | 547k | nextOpPreloaded(); |
660 | 547k | } |
661 | | |
662 | | d_m3Op(i64_Sub128) |
663 | 1.63M | { |
664 | 1.63M | u64 rhsHigh = slot (u64); |
665 | 1.63M | u64 rhsLow = slot (u64); |
666 | 1.63M | u64 lhsHigh = slot (u64); |
667 | 1.63M | u64 lhsLow = slot (u64); |
668 | 1.63M | u64* low = slot_ptr (u64); |
669 | 1.63M | d_m3PreloadNext(); |
670 | | |
671 | 1.63M | *low = lhsLow - rhsLow; |
672 | 1.63M | _r0 = (i64) (lhsHigh - rhsHigh - (lhsLow < rhsLow)); |
673 | | |
674 | 1.63M | nextOpPreloaded(); |
675 | 1.63M | } |
676 | | |
677 | | d_m3Op(i64_MultiplyWide) |
678 | 1.67M | { |
679 | 1.67M | i64 b = slot (i64); |
680 | 1.67M | i64 a = slot (i64); |
681 | 1.67M | u64* low = slot_ptr (u64); |
682 | 1.67M | d_m3PreloadNext(); |
683 | | |
684 | 1.67M | u64 high; |
685 | 1.67M | *low = mul_wide_i64 (a, b, &high); |
686 | 1.67M | _r0 = (i64) high; |
687 | | |
688 | 1.67M | nextOpPreloaded(); |
689 | 1.67M | } |
690 | | |
691 | | d_m3Op(u64_MultiplyWide) |
692 | 644k | { |
693 | 644k | u64 b = slot (u64); |
694 | 644k | u64 a = slot (u64); |
695 | 644k | u64* low = slot_ptr (u64); |
696 | 644k | d_m3PreloadNext(); |
697 | | |
698 | 644k | u64 high; |
699 | 644k | *low = mul_wide_u64 (a, b, &high); |
700 | 644k | _r0 = (i64) high; |
701 | | |
702 | 644k | nextOpPreloaded(); |
703 | 644k | } |
704 | | |
705 | | #endif // d_m3HasWideArithmetic |
706 | | |
707 | | #define d_m3TruncMacro(DEST, SRC, TYPE, NAME, FROM, OP, ...) \ |
708 | 14.3M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ |
709 | 14.3M | { \ |
710 | 14.3M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ |
711 | 14.3M | nextOp (); \ |
712 | 5.39M | } \ m3_compile.c:op_i32_Trunc_f32_r_r Line | Count | Source | 708 | 637k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 637k | { \ | 710 | 637k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 637k | nextOp (); \ | 712 | 637k | } \ |
m3_compile.c:op_u32_Trunc_f32_r_r Line | Count | Source | 708 | 805k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 805k | { \ | 710 | 805k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 805k | nextOp (); \ | 712 | 805k | } \ |
m3_compile.c:op_i32_Trunc_f64_r_r Line | Count | Source | 708 | 713k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 713k | { \ | 710 | 713k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 713k | nextOp (); \ | 712 | 713k | } \ |
m3_compile.c:op_u32_Trunc_f64_r_r Line | Count | Source | 708 | 874k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 874k | { \ | 710 | 874k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 874k | nextOp (); \ | 712 | 874k | } \ |
m3_compile.c:op_i64_Trunc_f32_r_r Line | Count | Source | 708 | 465k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 465k | { \ | 710 | 465k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 465k | nextOp (); \ | 712 | 465k | } \ |
m3_compile.c:op_u64_Trunc_f32_r_r Line | Count | Source | 708 | 672k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 672k | { \ | 710 | 672k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 672k | nextOp (); \ | 712 | 672k | } \ |
m3_compile.c:op_i64_Trunc_f64_r_r Line | Count | Source | 708 | 602k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 602k | { \ | 710 | 602k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 602k | nextOp (); \ | 712 | 602k | } \ |
m3_compile.c:op_u64_Trunc_f64_r_r Line | Count | Source | 708 | 621k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 621k | { \ | 710 | 621k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 621k | nextOp (); \ | 712 | 621k | } \ |
m3_compile.c:op_i32_TruncSat_f32_r_r Line | Count | Source | 708 | 1.14M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.14M | { \ | 710 | 1.14M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.14M | nextOp (); \ | 712 | 1.14M | } \ |
m3_compile.c:op_u32_TruncSat_f32_r_r Line | Count | Source | 708 | 1.23M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.23M | { \ | 710 | 1.23M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.23M | nextOp (); \ | 712 | 1.23M | } \ |
m3_compile.c:op_i32_TruncSat_f64_r_r Line | Count | Source | 708 | 1.25M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.25M | { \ | 710 | 1.25M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.25M | nextOp (); \ | 712 | 1.25M | } \ |
m3_compile.c:op_u32_TruncSat_f64_r_r Line | Count | Source | 708 | 1.07M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.07M | { \ | 710 | 1.07M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.07M | nextOp (); \ | 712 | 1.07M | } \ |
m3_compile.c:op_i64_TruncSat_f32_r_r Line | Count | Source | 708 | 1.09M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.09M | { \ | 710 | 1.09M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.09M | nextOp (); \ | 712 | 1.09M | } \ |
m3_compile.c:op_u64_TruncSat_f32_r_r Line | Count | Source | 708 | 820k | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 820k | { \ | 710 | 820k | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 820k | nextOp (); \ | 712 | 820k | } \ |
m3_compile.c:op_i64_TruncSat_f64_r_r Line | Count | Source | 708 | 1.19M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.19M | { \ | 710 | 1.19M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.19M | nextOp (); \ | 712 | 1.19M | } \ |
m3_compile.c:op_u64_TruncSat_f64_r_r Line | Count | Source | 708 | 1.10M | d_m3Op(TYPE##_##NAME##_##FROM##_r_r) \ | 709 | 1.10M | { \ | 710 | 1.10M | OP((DEST), (FROM) SRC, ##__VA_ARGS__); \ | 711 | 1.10M | nextOp (); \ | 712 | 1.10M | } \ |
|
713 | 18.7M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ |
714 | 18.7M | { \ |
715 | 18.7M | FROM * stack = slot_ptr (FROM); \ |
716 | 18.7M | OP((DEST), (* stack), ##__VA_ARGS__); \ |
717 | 18.7M | nextOp (); \ |
718 | 7.04M | } \ m3_compile.c:op_i32_Trunc_f32_r_s Line | Count | Source | 713 | 919k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 919k | { \ | 715 | 919k | FROM * stack = slot_ptr (FROM); \ | 716 | 919k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 919k | nextOp (); \ | 718 | 919k | } \ |
m3_compile.c:op_u32_Trunc_f32_r_s Line | Count | Source | 713 | 1.12M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.12M | { \ | 715 | 1.12M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.12M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.12M | nextOp (); \ | 718 | 1.12M | } \ |
m3_compile.c:op_i32_Trunc_f64_r_s Line | Count | Source | 713 | 530k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 530k | { \ | 715 | 530k | FROM * stack = slot_ptr (FROM); \ | 716 | 530k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 530k | nextOp (); \ | 718 | 530k | } \ |
m3_compile.c:op_u32_Trunc_f64_r_s Line | Count | Source | 713 | 689k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 689k | { \ | 715 | 689k | FROM * stack = slot_ptr (FROM); \ | 716 | 689k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 689k | nextOp (); \ | 718 | 689k | } \ |
m3_compile.c:op_i64_Trunc_f32_r_s Line | Count | Source | 713 | 1.50M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.50M | { \ | 715 | 1.50M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.50M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.50M | nextOp (); \ | 718 | 1.50M | } \ |
m3_compile.c:op_u64_Trunc_f32_r_s Line | Count | Source | 713 | 880k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 880k | { \ | 715 | 880k | FROM * stack = slot_ptr (FROM); \ | 716 | 880k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 880k | nextOp (); \ | 718 | 880k | } \ |
m3_compile.c:op_i64_Trunc_f64_r_s Line | Count | Source | 713 | 769k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 769k | { \ | 715 | 769k | FROM * stack = slot_ptr (FROM); \ | 716 | 769k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 769k | nextOp (); \ | 718 | 769k | } \ |
m3_compile.c:op_u64_Trunc_f64_r_s Line | Count | Source | 713 | 627k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 627k | { \ | 715 | 627k | FROM * stack = slot_ptr (FROM); \ | 716 | 627k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 627k | nextOp (); \ | 718 | 627k | } \ |
m3_compile.c:op_i32_TruncSat_f32_r_s Line | Count | Source | 713 | 2.03M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 2.03M | { \ | 715 | 2.03M | FROM * stack = slot_ptr (FROM); \ | 716 | 2.03M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 2.03M | nextOp (); \ | 718 | 2.03M | } \ |
m3_compile.c:op_u32_TruncSat_f32_r_s Line | Count | Source | 713 | 1.94M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.94M | { \ | 715 | 1.94M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.94M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.94M | nextOp (); \ | 718 | 1.94M | } \ |
m3_compile.c:op_i32_TruncSat_f64_r_s Line | Count | Source | 713 | 1.15M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.15M | { \ | 715 | 1.15M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.15M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.15M | nextOp (); \ | 718 | 1.15M | } \ |
m3_compile.c:op_u32_TruncSat_f64_r_s Line | Count | Source | 713 | 1.46M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.46M | { \ | 715 | 1.46M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.46M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.46M | nextOp (); \ | 718 | 1.46M | } \ |
m3_compile.c:op_i64_TruncSat_f32_r_s Line | Count | Source | 713 | 1.53M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.53M | { \ | 715 | 1.53M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.53M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.53M | nextOp (); \ | 718 | 1.53M | } \ |
m3_compile.c:op_u64_TruncSat_f32_r_s Line | Count | Source | 713 | 1.64M | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 1.64M | { \ | 715 | 1.64M | FROM * stack = slot_ptr (FROM); \ | 716 | 1.64M | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 1.64M | nextOp (); \ | 718 | 1.64M | } \ |
m3_compile.c:op_i64_TruncSat_f64_r_s Line | Count | Source | 713 | 962k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 962k | { \ | 715 | 962k | FROM * stack = slot_ptr (FROM); \ | 716 | 962k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 962k | nextOp (); \ | 718 | 962k | } \ |
m3_compile.c:op_u64_TruncSat_f64_r_s Line | Count | Source | 713 | 925k | d_m3Op(TYPE##_##NAME##_##FROM##_r_s) \ | 714 | 925k | { \ | 715 | 925k | FROM * stack = slot_ptr (FROM); \ | 716 | 925k | OP((DEST), (* stack), ##__VA_ARGS__); \ | 717 | 925k | nextOp (); \ | 718 | 925k | } \ |
|
719 | 11.8M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ |
720 | 11.8M | { \ |
721 | 11.8M | TYPE * dest = slot_ptr (TYPE); \ |
722 | 11.8M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ |
723 | 11.8M | nextOp (); \ |
724 | 3.00M | } \ m3_compile.c:op_i32_Trunc_f32_s_r Line | Count | Source | 719 | 484k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 484k | { \ | 721 | 484k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 484k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 484k | nextOp (); \ | 724 | 484k | } \ |
m3_compile.c:op_u32_Trunc_f32_s_r Line | Count | Source | 719 | 438k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 438k | { \ | 721 | 438k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 438k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 438k | nextOp (); \ | 724 | 438k | } \ |
m3_compile.c:op_i32_Trunc_f64_s_r Line | Count | Source | 719 | 355k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 355k | { \ | 721 | 355k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 355k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 355k | nextOp (); \ | 724 | 355k | } \ |
m3_compile.c:op_u32_Trunc_f64_s_r Line | Count | Source | 719 | 390k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 390k | { \ | 721 | 390k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 390k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 390k | nextOp (); \ | 724 | 390k | } \ |
m3_compile.c:op_i64_Trunc_f32_s_r Line | Count | Source | 719 | 432k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 432k | { \ | 721 | 432k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 432k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 432k | nextOp (); \ | 724 | 432k | } \ |
m3_compile.c:op_u64_Trunc_f32_s_r Line | Count | Source | 719 | 302k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 302k | { \ | 721 | 302k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 302k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 302k | nextOp (); \ | 724 | 302k | } \ |
m3_compile.c:op_i64_Trunc_f64_s_r Line | Count | Source | 719 | 316k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 316k | { \ | 721 | 316k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 316k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 316k | nextOp (); \ | 724 | 316k | } \ |
m3_compile.c:op_u64_Trunc_f64_s_r Line | Count | Source | 719 | 282k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 282k | { \ | 721 | 282k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 282k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 282k | nextOp (); \ | 724 | 282k | } \ |
m3_compile.c:op_i32_TruncSat_f32_s_r Line | Count | Source | 719 | 910k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 910k | { \ | 721 | 910k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 910k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 910k | nextOp (); \ | 724 | 910k | } \ |
m3_compile.c:op_u32_TruncSat_f32_s_r Line | Count | Source | 719 | 1.26M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 1.26M | { \ | 721 | 1.26M | TYPE * dest = slot_ptr (TYPE); \ | 722 | 1.26M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 1.26M | nextOp (); \ | 724 | 1.26M | } \ |
m3_compile.c:op_i32_TruncSat_f64_s_r Line | Count | Source | 719 | 1.28M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 1.28M | { \ | 721 | 1.28M | TYPE * dest = slot_ptr (TYPE); \ | 722 | 1.28M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 1.28M | nextOp (); \ | 724 | 1.28M | } \ |
m3_compile.c:op_u32_TruncSat_f64_s_r Line | Count | Source | 719 | 888k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 888k | { \ | 721 | 888k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 888k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 888k | nextOp (); \ | 724 | 888k | } \ |
m3_compile.c:op_i64_TruncSat_f32_s_r Line | Count | Source | 719 | 1.03M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 1.03M | { \ | 721 | 1.03M | TYPE * dest = slot_ptr (TYPE); \ | 722 | 1.03M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 1.03M | nextOp (); \ | 724 | 1.03M | } \ |
m3_compile.c:op_u64_TruncSat_f32_s_r Line | Count | Source | 719 | 1.28M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 1.28M | { \ | 721 | 1.28M | TYPE * dest = slot_ptr (TYPE); \ | 722 | 1.28M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 1.28M | nextOp (); \ | 724 | 1.28M | } \ |
m3_compile.c:op_i64_TruncSat_f64_s_r Line | Count | Source | 719 | 1.37M | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 1.37M | { \ | 721 | 1.37M | TYPE * dest = slot_ptr (TYPE); \ | 722 | 1.37M | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 1.37M | nextOp (); \ | 724 | 1.37M | } \ |
m3_compile.c:op_u64_TruncSat_f64_s_r Line | Count | Source | 719 | 847k | d_m3Op(TYPE##_##NAME##_##FROM##_s_r) \ | 720 | 847k | { \ | 721 | 847k | TYPE * dest = slot_ptr (TYPE); \ | 722 | 847k | OP((* dest), (FROM) SRC, ##__VA_ARGS__); \ | 723 | 847k | nextOp (); \ | 724 | 847k | } \ |
|
725 | 21.3M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ |
726 | 21.3M | { \ |
727 | 21.3M | FROM * stack = slot_ptr (FROM); \ |
728 | 21.3M | TYPE * dest = slot_ptr (TYPE); \ |
729 | 21.3M | OP((* dest), (* stack), ##__VA_ARGS__); \ |
730 | 21.3M | nextOp (); \ |
731 | 5.49M | } m3_compile.c:op_i32_Trunc_f32_s_s Line | Count | Source | 725 | 972k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 972k | { \ | 727 | 972k | FROM * stack = slot_ptr (FROM); \ | 728 | 972k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 972k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 972k | nextOp (); \ | 731 | 972k | } |
m3_compile.c:op_u32_Trunc_f32_s_s Line | Count | Source | 725 | 824k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 824k | { \ | 727 | 824k | FROM * stack = slot_ptr (FROM); \ | 728 | 824k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 824k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 824k | nextOp (); \ | 731 | 824k | } |
m3_compile.c:op_i32_Trunc_f64_s_s Line | Count | Source | 725 | 520k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 520k | { \ | 727 | 520k | FROM * stack = slot_ptr (FROM); \ | 728 | 520k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 520k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 520k | nextOp (); \ | 731 | 520k | } |
m3_compile.c:op_u32_Trunc_f64_s_s Line | Count | Source | 725 | 449k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 449k | { \ | 727 | 449k | FROM * stack = slot_ptr (FROM); \ | 728 | 449k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 449k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 449k | nextOp (); \ | 731 | 449k | } |
m3_compile.c:op_i64_Trunc_f32_s_s Line | Count | Source | 725 | 1.21M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 1.21M | { \ | 727 | 1.21M | FROM * stack = slot_ptr (FROM); \ | 728 | 1.21M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 1.21M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 1.21M | nextOp (); \ | 731 | 1.21M | } |
m3_compile.c:op_u64_Trunc_f32_s_s Line | Count | Source | 725 | 812k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 812k | { \ | 727 | 812k | FROM * stack = slot_ptr (FROM); \ | 728 | 812k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 812k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 812k | nextOp (); \ | 731 | 812k | } |
m3_compile.c:op_i64_Trunc_f64_s_s Line | Count | Source | 725 | 231k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 231k | { \ | 727 | 231k | FROM * stack = slot_ptr (FROM); \ | 728 | 231k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 231k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 231k | nextOp (); \ | 731 | 231k | } |
m3_compile.c:op_u64_Trunc_f64_s_s Line | Count | Source | 725 | 477k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 477k | { \ | 727 | 477k | FROM * stack = slot_ptr (FROM); \ | 728 | 477k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 477k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 477k | nextOp (); \ | 731 | 477k | } |
m3_compile.c:op_i32_TruncSat_f32_s_s Line | Count | Source | 725 | 2.84M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 2.84M | { \ | 727 | 2.84M | FROM * stack = slot_ptr (FROM); \ | 728 | 2.84M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 2.84M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 2.84M | nextOp (); \ | 731 | 2.84M | } |
m3_compile.c:op_u32_TruncSat_f32_s_s Line | Count | Source | 725 | 2.77M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 2.77M | { \ | 727 | 2.77M | FROM * stack = slot_ptr (FROM); \ | 728 | 2.77M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 2.77M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 2.77M | nextOp (); \ | 731 | 2.77M | } |
m3_compile.c:op_i32_TruncSat_f64_s_s Line | Count | Source | 725 | 793k | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 793k | { \ | 727 | 793k | FROM * stack = slot_ptr (FROM); \ | 728 | 793k | TYPE * dest = slot_ptr (TYPE); \ | 729 | 793k | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 793k | nextOp (); \ | 731 | 793k | } |
m3_compile.c:op_u32_TruncSat_f64_s_s Line | Count | Source | 725 | 1.13M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 1.13M | { \ | 727 | 1.13M | FROM * stack = slot_ptr (FROM); \ | 728 | 1.13M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 1.13M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 1.13M | nextOp (); \ | 731 | 1.13M | } |
m3_compile.c:op_i64_TruncSat_f32_s_s Line | Count | Source | 725 | 2.98M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 2.98M | { \ | 727 | 2.98M | FROM * stack = slot_ptr (FROM); \ | 728 | 2.98M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 2.98M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 2.98M | nextOp (); \ | 731 | 2.98M | } |
m3_compile.c:op_u64_TruncSat_f32_s_s Line | Count | Source | 725 | 2.76M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 2.76M | { \ | 727 | 2.76M | FROM * stack = slot_ptr (FROM); \ | 728 | 2.76M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 2.76M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 2.76M | nextOp (); \ | 731 | 2.76M | } |
m3_compile.c:op_i64_TruncSat_f64_s_s Line | Count | Source | 725 | 1.04M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 1.04M | { \ | 727 | 1.04M | FROM * stack = slot_ptr (FROM); \ | 728 | 1.04M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 1.04M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 1.04M | nextOp (); \ | 731 | 1.04M | } |
m3_compile.c:op_u64_TruncSat_f64_s_s Line | Count | Source | 725 | 1.53M | d_m3Op(TYPE##_##NAME##_##FROM##_s_s) \ | 726 | 1.53M | { \ | 727 | 1.53M | FROM * stack = slot_ptr (FROM); \ | 728 | 1.53M | TYPE * dest = slot_ptr (TYPE); \ | 729 | 1.53M | OP((* dest), (* stack), ##__VA_ARGS__); \ | 730 | 1.53M | nextOp (); \ | 731 | 1.53M | } |
|
732 | | |
733 | | #if d_m3HasFloat |
734 | 3.01M | d_m3TruncMacro(_r0, _fp0, i32, Trunc, f32, OP_I32_TRUNC_F32) |
735 | 3.19M | d_m3TruncMacro(_r0, _fp0, u32, Trunc, f32, OP_U32_TRUNC_F32) |
736 | 2.11M | d_m3TruncMacro(_r0, _fp0, i32, Trunc, f64, OP_I32_TRUNC_F64) |
737 | 2.40M | d_m3TruncMacro(_r0, _fp0, u32, Trunc, f64, OP_U32_TRUNC_F64) |
738 | | |
739 | 3.61M | d_m3TruncMacro(_r0, _fp0, i64, Trunc, f32, OP_I64_TRUNC_F32) |
740 | 2.66M | d_m3TruncMacro(_r0, _fp0, u64, Trunc, f32, OP_U64_TRUNC_F32) |
741 | 1.92M | d_m3TruncMacro(_r0, _fp0, i64, Trunc, f64, OP_I64_TRUNC_F64) |
742 | 2.00M | d_m3TruncMacro(_r0, _fp0, u64, Trunc, f64, OP_U64_TRUNC_F64) |
743 | | |
744 | 6.93M | d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f32, OP_I32_TRUNC_SAT_F32) |
745 | 7.22M | d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f32, OP_U32_TRUNC_SAT_F32) |
746 | 4.49M | d_m3TruncMacro(_r0, _fp0, i32, TruncSat, f64, OP_I32_TRUNC_SAT_F64) |
747 | 4.55M | d_m3TruncMacro(_r0, _fp0, u32, TruncSat, f64, OP_U32_TRUNC_SAT_F64) |
748 | | |
749 | 6.65M | d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f32, OP_I64_TRUNC_SAT_F32) |
750 | 6.51M | d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f32, OP_U64_TRUNC_SAT_F32) |
751 | 4.57M | d_m3TruncMacro(_r0, _fp0, i64, TruncSat, f64, OP_I64_TRUNC_SAT_F64) |
752 | 4.41M | d_m3TruncMacro(_r0, _fp0, u64, TruncSat, f64, OP_U64_TRUNC_SAT_F64) |
753 | | #endif |
754 | | |
755 | | #define d_m3TypeModifyOp(REG_TO, REG_FROM, TO, NAME, FROM) \ |
756 | 3.45M | d_m3Op(TO##_##NAME##_##FROM##_r) \ |
757 | 3.45M | { \ |
758 | 3.45M | REG_TO = (TO) ((FROM) REG_FROM); \ |
759 | 3.45M | nextOp (); \ |
760 | 3.45M | } \ m3_compile.c:op_i64_Extend_i32_r Line | Count | Source | 756 | 1.84M | d_m3Op(TO##_##NAME##_##FROM##_r) \ | 757 | 1.84M | { \ | 758 | 1.84M | REG_TO = (TO) ((FROM) REG_FROM); \ | 759 | 1.84M | nextOp (); \ | 760 | 1.84M | } \ |
m3_compile.c:op_i64_Extend_u32_r Line | Count | Source | 756 | 1.60M | d_m3Op(TO##_##NAME##_##FROM##_r) \ | 757 | 1.60M | { \ | 758 | 1.60M | REG_TO = (TO) ((FROM) REG_FROM); \ | 759 | 1.60M | nextOp (); \ | 760 | 1.60M | } \ |
|
761 | | \ |
762 | 2.54M | d_m3Op(TO##_##NAME##_##FROM##_s) \ |
763 | 2.54M | { \ |
764 | 2.54M | FROM from = slot (FROM); \ |
765 | 2.54M | REG_TO = (TO) (from); \ |
766 | 2.54M | nextOp (); \ |
767 | 2.54M | } m3_compile.c:op_i64_Extend_i32_s Line | Count | Source | 762 | 1.40M | d_m3Op(TO##_##NAME##_##FROM##_s) \ | 763 | 1.40M | { \ | 764 | 1.40M | FROM from = slot (FROM); \ | 765 | 1.40M | REG_TO = (TO) (from); \ | 766 | 1.40M | nextOp (); \ | 767 | 1.40M | } |
m3_compile.c:op_i64_Extend_u32_s Line | Count | Source | 762 | 1.14M | d_m3Op(TO##_##NAME##_##FROM##_s) \ | 763 | 1.14M | { \ | 764 | 1.14M | FROM from = slot (FROM); \ | 765 | 1.14M | REG_TO = (TO) (from); \ | 766 | 1.14M | nextOp (); \ | 767 | 1.14M | } |
|
768 | | |
769 | | // Int to int |
770 | | d_m3TypeModifyOp(_r0, _r0, i64, Extend, i32); |
771 | | d_m3TypeModifyOp(_r0, _r0, i64, Extend, u32); |
772 | | |
773 | | // Float to float. Narrowing or widening a NaN produces an arithmetic one, so these |
774 | | // two go through the canonicalizer where the int conversions have nothing to do. |
775 | | #define d_m3FloatModifyOp(TO, NAME, FROM) \ |
776 | 1.48M | d_m3Op(TO##_##NAME##_##FROM##_r) \ |
777 | 1.48M | { \ |
778 | 1.48M | _fp0 = canon_nan_##TO ((TO) ((FROM) _fp0)); \ |
779 | 1.48M | nextOp (); \ |
780 | 1.48M | } \ m3_compile.c:op_f32_Demote_f64_r Line | Count | Source | 776 | 694k | d_m3Op(TO##_##NAME##_##FROM##_r) \ | 777 | 694k | { \ | 778 | 694k | _fp0 = canon_nan_##TO ((TO) ((FROM) _fp0)); \ | 779 | 694k | nextOp (); \ | 780 | 694k | } \ |
m3_compile.c:op_f64_Promote_f32_r Line | Count | Source | 776 | 787k | d_m3Op(TO##_##NAME##_##FROM##_r) \ | 777 | 787k | { \ | 778 | 787k | _fp0 = canon_nan_##TO ((TO) ((FROM) _fp0)); \ | 779 | 787k | nextOp (); \ | 780 | 787k | } \ |
|
781 | | \ |
782 | 3.08M | d_m3Op(TO##_##NAME##_##FROM##_s) \ |
783 | 3.08M | { \ |
784 | 3.08M | FROM from = slot (FROM); \ |
785 | 3.08M | _fp0 = canon_nan_##TO ((TO) (from)); \ |
786 | 3.08M | nextOp (); \ |
787 | 3.08M | } m3_compile.c:op_f32_Demote_f64_s Line | Count | Source | 782 | 383k | d_m3Op(TO##_##NAME##_##FROM##_s) \ | 783 | 383k | { \ | 784 | 383k | FROM from = slot (FROM); \ | 785 | 383k | _fp0 = canon_nan_##TO ((TO) (from)); \ | 786 | 383k | nextOp (); \ | 787 | 383k | } |
m3_compile.c:op_f64_Promote_f32_s Line | Count | Source | 782 | 2.69M | d_m3Op(TO##_##NAME##_##FROM##_s) \ | 783 | 2.69M | { \ | 784 | 2.69M | FROM from = slot (FROM); \ | 785 | 2.69M | _fp0 = canon_nan_##TO ((TO) (from)); \ | 786 | 2.69M | nextOp (); \ | 787 | 2.69M | } |
|
788 | | |
789 | | #if d_m3HasFloat |
790 | | d_m3FloatModifyOp(f32, Demote, f64); |
791 | | d_m3FloatModifyOp(f64, Promote, f32); |
792 | | #endif |
793 | | |
794 | | #define d_m3TypeConvertOp(REG_TO, REG_FROM, TO, NAME, FROM) \ |
795 | 14.4M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ |
796 | 14.4M | { \ |
797 | 14.4M | REG_TO = (TO) ((FROM) REG_FROM); \ |
798 | 14.4M | nextOp (); \ |
799 | 14.4M | } \ m3_compile.c:op_f32_Convert_i32_r_r Line | Count | Source | 795 | 2.29M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 2.29M | { \ | 797 | 2.29M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 2.29M | nextOp (); \ | 799 | 2.29M | } \ |
m3_compile.c:op_f32_Convert_u32_r_r Line | Count | Source | 795 | 1.80M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 1.80M | { \ | 797 | 1.80M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 1.80M | nextOp (); \ | 799 | 1.80M | } \ |
m3_compile.c:op_f32_Convert_i64_r_r Line | Count | Source | 795 | 1.60M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 1.60M | { \ | 797 | 1.60M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 1.60M | nextOp (); \ | 799 | 1.60M | } \ |
m3_compile.c:op_f32_Convert_u64_r_r Line | Count | Source | 795 | 1.17M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 1.17M | { \ | 797 | 1.17M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 1.17M | nextOp (); \ | 799 | 1.17M | } \ |
m3_compile.c:op_f64_Convert_i32_r_r Line | Count | Source | 795 | 2.83M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 2.83M | { \ | 797 | 2.83M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 2.83M | nextOp (); \ | 799 | 2.83M | } \ |
m3_compile.c:op_f64_Convert_u32_r_r Line | Count | Source | 795 | 1.63M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 1.63M | { \ | 797 | 1.63M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 1.63M | nextOp (); \ | 799 | 1.63M | } \ |
m3_compile.c:op_f64_Convert_i64_r_r Line | Count | Source | 795 | 1.09M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 1.09M | { \ | 797 | 1.09M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 1.09M | nextOp (); \ | 799 | 1.09M | } \ |
m3_compile.c:op_f64_Convert_u64_r_r Line | Count | Source | 795 | 2.00M | d_m3Op(TO##_##NAME##_##FROM##_r_r) \ | 796 | 2.00M | { \ | 797 | 2.00M | REG_TO = (TO) ((FROM) REG_FROM); \ | 798 | 2.00M | nextOp (); \ | 799 | 2.00M | } \ |
|
800 | | \ |
801 | 5.52M | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ |
802 | 5.52M | { \ |
803 | 5.52M | slot (TO) = (TO) ((FROM) REG_FROM); \ |
804 | 5.52M | nextOp (); \ |
805 | 5.52M | } \ m3_compile.c:op_f32_Convert_i32_s_r Line | Count | Source | 801 | 823k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 823k | { \ | 803 | 823k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 823k | nextOp (); \ | 805 | 823k | } \ |
m3_compile.c:op_f32_Convert_u32_s_r Line | Count | Source | 801 | 1.03M | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 1.03M | { \ | 803 | 1.03M | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 1.03M | nextOp (); \ | 805 | 1.03M | } \ |
m3_compile.c:op_f32_Convert_i64_s_r Line | Count | Source | 801 | 477k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 477k | { \ | 803 | 477k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 477k | nextOp (); \ | 805 | 477k | } \ |
m3_compile.c:op_f32_Convert_u64_s_r Line | Count | Source | 801 | 361k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 361k | { \ | 803 | 361k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 361k | nextOp (); \ | 805 | 361k | } \ |
m3_compile.c:op_f64_Convert_i32_s_r Line | Count | Source | 801 | 1.08M | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 1.08M | { \ | 803 | 1.08M | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 1.08M | nextOp (); \ | 805 | 1.08M | } \ |
m3_compile.c:op_f64_Convert_u32_s_r Line | Count | Source | 801 | 759k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 759k | { \ | 803 | 759k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 759k | nextOp (); \ | 805 | 759k | } \ |
m3_compile.c:op_f64_Convert_i64_s_r Line | Count | Source | 801 | 405k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 405k | { \ | 803 | 405k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 405k | nextOp (); \ | 805 | 405k | } \ |
m3_compile.c:op_f64_Convert_u64_s_r Line | Count | Source | 801 | 588k | d_m3Op(TO##_##NAME##_##FROM##_s_r) \ | 802 | 588k | { \ | 803 | 588k | slot (TO) = (TO) ((FROM) REG_FROM); \ | 804 | 588k | nextOp (); \ | 805 | 588k | } \ |
|
806 | | \ |
807 | 25.0M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ |
808 | 25.0M | { \ |
809 | 25.0M | FROM from = slot (FROM); \ |
810 | 25.0M | REG_TO = (TO) (from); \ |
811 | 25.0M | nextOp (); \ |
812 | 25.0M | } \ m3_compile.c:op_f32_Convert_i32_r_s Line | Count | Source | 807 | 2.54M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 2.54M | { \ | 809 | 2.54M | FROM from = slot (FROM); \ | 810 | 2.54M | REG_TO = (TO) (from); \ | 811 | 2.54M | nextOp (); \ | 812 | 2.54M | } \ |
m3_compile.c:op_f32_Convert_u32_r_s Line | Count | Source | 807 | 2.33M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 2.33M | { \ | 809 | 2.33M | FROM from = slot (FROM); \ | 810 | 2.33M | REG_TO = (TO) (from); \ | 811 | 2.33M | nextOp (); \ | 812 | 2.33M | } \ |
m3_compile.c:op_f32_Convert_i64_r_s Line | Count | Source | 807 | 3.23M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 3.23M | { \ | 809 | 3.23M | FROM from = slot (FROM); \ | 810 | 3.23M | REG_TO = (TO) (from); \ | 811 | 3.23M | nextOp (); \ | 812 | 3.23M | } \ |
m3_compile.c:op_f32_Convert_u64_r_s Line | Count | Source | 807 | 3.37M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 3.37M | { \ | 809 | 3.37M | FROM from = slot (FROM); \ | 810 | 3.37M | REG_TO = (TO) (from); \ | 811 | 3.37M | nextOp (); \ | 812 | 3.37M | } \ |
m3_compile.c:op_f64_Convert_i32_r_s Line | Count | Source | 807 | 3.08M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 3.08M | { \ | 809 | 3.08M | FROM from = slot (FROM); \ | 810 | 3.08M | REG_TO = (TO) (from); \ | 811 | 3.08M | nextOp (); \ | 812 | 3.08M | } \ |
m3_compile.c:op_f64_Convert_u32_r_s Line | Count | Source | 807 | 2.98M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 2.98M | { \ | 809 | 2.98M | FROM from = slot (FROM); \ | 810 | 2.98M | REG_TO = (TO) (from); \ | 811 | 2.98M | nextOp (); \ | 812 | 2.98M | } \ |
m3_compile.c:op_f64_Convert_i64_r_s Line | Count | Source | 807 | 3.66M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 3.66M | { \ | 809 | 3.66M | FROM from = slot (FROM); \ | 810 | 3.66M | REG_TO = (TO) (from); \ | 811 | 3.66M | nextOp (); \ | 812 | 3.66M | } \ |
m3_compile.c:op_f64_Convert_u64_r_s Line | Count | Source | 807 | 3.84M | d_m3Op(TO##_##NAME##_##FROM##_r_s) \ | 808 | 3.84M | { \ | 809 | 3.84M | FROM from = slot (FROM); \ | 810 | 3.84M | REG_TO = (TO) (from); \ | 811 | 3.84M | nextOp (); \ | 812 | 3.84M | } \ |
|
813 | | \ |
814 | 9.27M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ |
815 | 9.27M | { \ |
816 | 9.27M | FROM from = slot (FROM); \ |
817 | 9.27M | slot (TO) = (TO) (from); \ |
818 | 9.27M | nextOp (); \ |
819 | 9.27M | } m3_compile.c:op_f32_Convert_i32_s_s Line | Count | Source | 814 | 1.04M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 1.04M | { \ | 816 | 1.04M | FROM from = slot (FROM); \ | 817 | 1.04M | slot (TO) = (TO) (from); \ | 818 | 1.04M | nextOp (); \ | 819 | 1.04M | } |
m3_compile.c:op_f32_Convert_u32_s_s Line | Count | Source | 814 | 865k | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 865k | { \ | 816 | 865k | FROM from = slot (FROM); \ | 817 | 865k | slot (TO) = (TO) (from); \ | 818 | 865k | nextOp (); \ | 819 | 865k | } |
m3_compile.c:op_f32_Convert_i64_s_s Line | Count | Source | 814 | 624k | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 624k | { \ | 816 | 624k | FROM from = slot (FROM); \ | 817 | 624k | slot (TO) = (TO) (from); \ | 818 | 624k | nextOp (); \ | 819 | 624k | } |
m3_compile.c:op_f32_Convert_u64_s_s Line | Count | Source | 814 | 912k | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 912k | { \ | 816 | 912k | FROM from = slot (FROM); \ | 817 | 912k | slot (TO) = (TO) (from); \ | 818 | 912k | nextOp (); \ | 819 | 912k | } |
m3_compile.c:op_f64_Convert_i32_s_s Line | Count | Source | 814 | 1.67M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 1.67M | { \ | 816 | 1.67M | FROM from = slot (FROM); \ | 817 | 1.67M | slot (TO) = (TO) (from); \ | 818 | 1.67M | nextOp (); \ | 819 | 1.67M | } |
m3_compile.c:op_f64_Convert_u32_s_s Line | Count | Source | 814 | 1.04M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 1.04M | { \ | 816 | 1.04M | FROM from = slot (FROM); \ | 817 | 1.04M | slot (TO) = (TO) (from); \ | 818 | 1.04M | nextOp (); \ | 819 | 1.04M | } |
m3_compile.c:op_f64_Convert_i64_s_s Line | Count | Source | 814 | 1.64M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 1.64M | { \ | 816 | 1.64M | FROM from = slot (FROM); \ | 817 | 1.64M | slot (TO) = (TO) (from); \ | 818 | 1.64M | nextOp (); \ | 819 | 1.64M | } |
m3_compile.c:op_f64_Convert_u64_s_s Line | Count | Source | 814 | 1.45M | d_m3Op(TO##_##NAME##_##FROM##_s_s) \ | 815 | 1.45M | { \ | 816 | 1.45M | FROM from = slot (FROM); \ | 817 | 1.45M | slot (TO) = (TO) (from); \ | 818 | 1.45M | nextOp (); \ | 819 | 1.45M | } |
|
820 | | |
821 | | // Int to float |
822 | | #if d_m3HasFloat |
823 | | d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i32); |
824 | | d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u32); |
825 | | d_m3TypeConvertOp(_fp0, _r0, f64, Convert, i64); |
826 | | d_m3TypeConvertOp(_fp0, _r0, f64, Convert, u64); |
827 | | |
828 | | d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i32); |
829 | | d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u32); |
830 | | d_m3TypeConvertOp(_fp0, _r0, f32, Convert, i64); |
831 | | d_m3TypeConvertOp(_fp0, _r0, f32, Convert, u64); |
832 | | #endif |
833 | | |
834 | | #define d_m3ReinterpretOp(REG, TO, SRC, FROM) \ |
835 | 5.16M | d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ |
836 | 5.16M | { \ |
837 | 5.16M | union { FROM c; TO t; } u; \ |
838 | 5.16M | u.c = (FROM) SRC; \ |
839 | 5.16M | REG = u.t; \ |
840 | 5.16M | nextOp (); \ |
841 | 5.16M | } \ m3_compile.c:op_i32_Reinterpret_f32_r_r Line | Count | Source | 835 | 733k | d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ | 836 | 733k | { \ | 837 | 733k | union { FROM c; TO t; } u; \ | 838 | 733k | u.c = (FROM) SRC; \ | 839 | 733k | REG = u.t; \ | 840 | 733k | nextOp (); \ | 841 | 733k | } \ |
m3_compile.c:op_i64_Reinterpret_f64_r_r Line | Count | Source | 835 | 608k | d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ | 836 | 608k | { \ | 837 | 608k | union { FROM c; TO t; } u; \ | 838 | 608k | u.c = (FROM) SRC; \ | 839 | 608k | REG = u.t; \ | 840 | 608k | nextOp (); \ | 841 | 608k | } \ |
m3_compile.c:op_f32_Reinterpret_i32_r_r Line | Count | Source | 835 | 1.80M | d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ | 836 | 1.80M | { \ | 837 | 1.80M | union { FROM c; TO t; } u; \ | 838 | 1.80M | u.c = (FROM) SRC; \ | 839 | 1.80M | REG = u.t; \ | 840 | 1.80M | nextOp (); \ | 841 | 1.80M | } \ |
m3_compile.c:op_f64_Reinterpret_i64_r_r Line | Count | Source | 835 | 2.00M | d_m3Op(TO##_Reinterpret_##FROM##_r_r) \ | 836 | 2.00M | { \ | 837 | 2.00M | union { FROM c; TO t; } u; \ | 838 | 2.00M | u.c = (FROM) SRC; \ | 839 | 2.00M | REG = u.t; \ | 840 | 2.00M | nextOp (); \ | 841 | 2.00M | } \ |
|
842 | | \ |
843 | 9.46M | d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ |
844 | 9.46M | { \ |
845 | 9.46M | union { FROM c; TO t; } u; \ |
846 | 9.46M | u.c = slot (FROM); \ |
847 | 9.46M | REG = u.t; \ |
848 | 9.46M | nextOp (); \ |
849 | 9.46M | } \ m3_compile.c:op_i32_Reinterpret_f32_r_s Line | Count | Source | 843 | 1.17M | d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ | 844 | 1.17M | { \ | 845 | 1.17M | union { FROM c; TO t; } u; \ | 846 | 1.17M | u.c = slot (FROM); \ | 847 | 1.17M | REG = u.t; \ | 848 | 1.17M | nextOp (); \ | 849 | 1.17M | } \ |
m3_compile.c:op_i64_Reinterpret_f64_r_s Line | Count | Source | 843 | 436k | d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ | 844 | 436k | { \ | 845 | 436k | union { FROM c; TO t; } u; \ | 846 | 436k | u.c = slot (FROM); \ | 847 | 436k | REG = u.t; \ | 848 | 436k | nextOp (); \ | 849 | 436k | } \ |
m3_compile.c:op_f32_Reinterpret_i32_r_s Line | Count | Source | 843 | 2.86M | d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ | 844 | 2.86M | { \ | 845 | 2.86M | union { FROM c; TO t; } u; \ | 846 | 2.86M | u.c = slot (FROM); \ | 847 | 2.86M | REG = u.t; \ | 848 | 2.86M | nextOp (); \ | 849 | 2.86M | } \ |
m3_compile.c:op_f64_Reinterpret_i64_r_s Line | Count | Source | 843 | 4.99M | d_m3Op(TO##_Reinterpret_##FROM##_r_s) \ | 844 | 4.99M | { \ | 845 | 4.99M | union { FROM c; TO t; } u; \ | 846 | 4.99M | u.c = slot (FROM); \ | 847 | 4.99M | REG = u.t; \ | 848 | 4.99M | nextOp (); \ | 849 | 4.99M | } \ |
|
850 | | \ |
851 | 2.48M | d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ |
852 | 2.48M | { \ |
853 | 2.48M | union { FROM c; TO t; } u; \ |
854 | 2.48M | u.c = (FROM) SRC; \ |
855 | 2.48M | slot (TO) = u.t; \ |
856 | 2.48M | nextOp (); \ |
857 | 2.48M | } \ m3_compile.c:op_i32_Reinterpret_f32_s_r Line | Count | Source | 851 | 617k | d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ | 852 | 617k | { \ | 853 | 617k | union { FROM c; TO t; } u; \ | 854 | 617k | u.c = (FROM) SRC; \ | 855 | 617k | slot (TO) = u.t; \ | 856 | 617k | nextOp (); \ | 857 | 617k | } \ |
m3_compile.c:op_i64_Reinterpret_f64_s_r Line | Count | Source | 851 | 350k | d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ | 852 | 350k | { \ | 853 | 350k | union { FROM c; TO t; } u; \ | 854 | 350k | u.c = (FROM) SRC; \ | 855 | 350k | slot (TO) = u.t; \ | 856 | 350k | nextOp (); \ | 857 | 350k | } \ |
m3_compile.c:op_f32_Reinterpret_i32_s_r Line | Count | Source | 851 | 908k | d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ | 852 | 908k | { \ | 853 | 908k | union { FROM c; TO t; } u; \ | 854 | 908k | u.c = (FROM) SRC; \ | 855 | 908k | slot (TO) = u.t; \ | 856 | 908k | nextOp (); \ | 857 | 908k | } \ |
m3_compile.c:op_f64_Reinterpret_i64_s_r Line | Count | Source | 851 | 607k | d_m3Op(TO##_Reinterpret_##FROM##_s_r) \ | 852 | 607k | { \ | 853 | 607k | union { FROM c; TO t; } u; \ | 854 | 607k | u.c = (FROM) SRC; \ | 855 | 607k | slot (TO) = u.t; \ | 856 | 607k | nextOp (); \ | 857 | 607k | } \ |
|
858 | | \ |
859 | 4.78M | d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ |
860 | 4.78M | { \ |
861 | 4.78M | union { FROM c; TO t; } u; \ |
862 | 4.78M | u.c = slot (FROM); \ |
863 | 4.78M | slot (TO) = u.t; \ |
864 | 4.78M | nextOp (); \ |
865 | 4.78M | } m3_compile.c:op_i32_Reinterpret_f32_s_s Line | Count | Source | 859 | 1.43M | d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ | 860 | 1.43M | { \ | 861 | 1.43M | union { FROM c; TO t; } u; \ | 862 | 1.43M | u.c = slot (FROM); \ | 863 | 1.43M | slot (TO) = u.t; \ | 864 | 1.43M | nextOp (); \ | 865 | 1.43M | } |
m3_compile.c:op_i64_Reinterpret_f64_s_s Line | Count | Source | 859 | 316k | d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ | 860 | 316k | { \ | 861 | 316k | union { FROM c; TO t; } u; \ | 862 | 316k | u.c = slot (FROM); \ | 863 | 316k | slot (TO) = u.t; \ | 864 | 316k | nextOp (); \ | 865 | 316k | } |
m3_compile.c:op_f32_Reinterpret_i32_s_s Line | Count | Source | 859 | 840k | d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ | 860 | 840k | { \ | 861 | 840k | union { FROM c; TO t; } u; \ | 862 | 840k | u.c = slot (FROM); \ | 863 | 840k | slot (TO) = u.t; \ | 864 | 840k | nextOp (); \ | 865 | 840k | } |
m3_compile.c:op_f64_Reinterpret_i64_s_s Line | Count | Source | 859 | 2.19M | d_m3Op(TO##_Reinterpret_##FROM##_s_s) \ | 860 | 2.19M | { \ | 861 | 2.19M | union { FROM c; TO t; } u; \ | 862 | 2.19M | u.c = slot (FROM); \ | 863 | 2.19M | slot (TO) = u.t; \ | 864 | 2.19M | nextOp (); \ | 865 | 2.19M | } |
|
866 | | |
867 | | #if d_m3HasFloat |
868 | | d_m3ReinterpretOp(_r0, i32, _fp0, f32) |
869 | | d_m3ReinterpretOp(_r0, i64, _fp0, f64) |
870 | | d_m3ReinterpretOp(_fp0, f32, _r0, i32) |
871 | | d_m3ReinterpretOp(_fp0, f64, _r0, i64) |
872 | | #endif |
873 | | |
874 | | // clang-format on |
875 | | |
876 | | d_m3Op(GetGlobal_s32) |
877 | 200k | { |
878 | 200k | u32* global = immediate(u32*); |
879 | 200k | slot(u32) = *global; // printf ("get global: %p %" PRIi64 "\n", global, *global); |
880 | | |
881 | 200k | nextOp(); |
882 | 200k | } |
883 | | |
884 | | |
885 | | d_m3Op(GetGlobal_s64) |
886 | 41.6k | { |
887 | 41.6k | u64* global = immediate(u64*); |
888 | 41.6k | slot(u64) = *global; // printf ("get global: %p %" PRIi64 "\n", global, *global); |
889 | | |
890 | 41.6k | nextOp(); |
891 | 41.6k | } |
892 | | |
893 | | |
894 | | d_m3Op(SetGlobal_i32) |
895 | 90.6k | { |
896 | 90.6k | u32* global = immediate(u32*); |
897 | 90.6k | *global = (u32)_r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); |
898 | | |
899 | 90.6k | nextOp(); |
900 | 90.6k | } |
901 | | |
902 | | |
903 | | d_m3Op(SetGlobal_i64) |
904 | 88.1k | { |
905 | 88.1k | u64* global = immediate(u64*); |
906 | 88.1k | *global = (u64)_r0; // printf ("set global: %p %" PRIi64 "\n", global, _r0); |
907 | | |
908 | 88.1k | nextOp(); |
909 | 88.1k | } |
910 | | |
911 | | |
912 | | #if d_m3HasStackSwitching |
913 | | |
914 | | d_m3Op(Branch); |
915 | | d_m3Op(Entry); |
916 | | # if !d_m3EntryKeepsFrame |
917 | | d_m3Op(Entry_Suspendable); |
918 | | # endif |
919 | | |
920 | | // The function a body of compiled code belongs to. op_Call is handed the code |
921 | | // rather than the function, but every body opens with op_Entry and the function |
922 | | // it enters - past a bridge, where the page ran out before the first op. |
923 | | static M3_NOINLINE |
924 | | IM3Function FunctionOfCompiledCode (pc_t i_pc) |
925 | 0 | { |
926 | 0 | if (not i_pc) { |
927 | 0 | return NULL; |
928 | 0 | } |
929 | | |
930 | 0 | while ((IM3Operation)i_pc[0] == op_Branch) { |
931 | 0 | i_pc = (pc_t)i_pc[1]; |
932 | 0 | } |
933 | |
|
934 | 0 | IM3Operation entry = (IM3Operation)i_pc[0]; |
935 | |
|
936 | 0 | # if !d_m3EntryKeepsFrame |
937 | 0 | if (entry == op_Entry_Suspendable) { |
938 | 0 | return (IM3Function)i_pc[1]; |
939 | 0 | } |
940 | 0 | # endif |
941 | 0 | return (entry == op_Entry) ? (IM3Function)i_pc[1] : NULL; |
942 | 0 | } |
943 | | |
944 | | #endif |
945 | | |
946 | | d_m3Op(Call) |
947 | 132k | { |
948 | 132k | d_m3CheckNativeStack(); |
949 | | |
950 | 132k | pc_t callPC = immediate(pc_t); |
951 | 132k | i32 stackOffset = immediate(i32); |
952 | 132k | IM3Memory memory = m3MemInfo(_mem); |
953 | | |
954 | 132k | m3stack_t sp = _sp + stackOffset; |
955 | | |
956 | | #if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
957 | | m3ret_t r = Call(callPC, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr); |
958 | | #else |
959 | 132k | m3ret_t r = Call(callPC, sp, _mem, d_m3OpDefaultArgs); |
960 | 132k | #endif |
961 | | |
962 | 132k | _mem = memory->mallocated; |
963 | | |
964 | 132k | if (M3_LIKELY(not r)) { |
965 | 583 | nextOp(); |
966 | 132k | } else { |
967 | 132k | d_m3RecordCallFrame(memory, FunctionOfCompiledCode(callPC)); |
968 | 132k | pushBacktraceFrame(); |
969 | 132k | forwardTrap(r); |
970 | 132k | } |
971 | 132k | } |
972 | | |
973 | | |
974 | | // call_ref / return_call_ref: like the indirect calls, except the callee comes |
975 | | // straight off the stack instead of out of a table, so there is no bounds check |
976 | | // and no index. The type still has to match: a (ref null $t) can hold a |
977 | | // reference the validator only knows as $t, and null has to trap. |
978 | | d_m3Op(CallRef) |
979 | 405 | { |
980 | 405 | IM3Function function = slot(IM3Function); |
981 | 405 | IM3FuncType type = immediate(IM3FuncType); |
982 | 405 | i32 stackOffset = immediate(i32); |
983 | 405 | IM3Memory memory = m3MemInfo(_mem); |
984 | | |
985 | 405 | m3stack_t sp = _sp + stackOffset; |
986 | | |
987 | 405 | m3ret_t r = m3Err_none; |
988 | | |
989 | 405 | if (M3_LIKELY(function)) { |
990 | 402 | if (M3_LIKELY(type == function->funcType)) { |
991 | 402 | if (M3_UNLIKELY(not function->compiled)) { |
992 | 0 | r = CompileFunction(function); |
993 | 0 | } |
994 | | |
995 | 402 | if (M3_LIKELY(not r)) { |
996 | | #if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
997 | | r = Call(function->compiled, sp, _mem, d_m3OpDefaultArgs, d_m3BaseCstr); |
998 | | #else |
999 | 402 | r = Call(function->compiled, sp, _mem, d_m3OpDefaultArgs); |
1000 | 402 | #endif |
1001 | | |
1002 | 402 | _mem = memory->mallocated; |
1003 | | |
1004 | 402 | if (M3_LIKELY(not r)) { |
1005 | 0 | nextOpDirect(); |
1006 | 402 | } else { |
1007 | 402 | d_m3RecordCallFrame(memory, function); |
1008 | 402 | pushBacktraceFrame(); |
1009 | 402 | forwardTrap(r); |
1010 | 402 | } |
1011 | 402 | } |
1012 | 402 | } else { |
1013 | 0 | r = m3Err_trapIndirectCallTypeMismatch; |
1014 | 0 | } |
1015 | 402 | } else { |
1016 | 3 | r = m3Err_trapNullFunctionRef; |
1017 | 3 | } |
1018 | | |
1019 | 3 | if (M3_UNLIKELY(r)) { |
1020 | 3 | newTrap(r); |
1021 | 3 | } else { |
1022 | 0 | forwardTrap(r); |
1023 | 0 | } |
1024 | 3 | } |
1025 | | |
1026 | | |
1027 | | // ref.as_non_null is a null check and nothing else: the value stays put, so |
1028 | | // there is no destination slot, only the trap. |
1029 | | d_m3Op(RefAsNonNull) |
1030 | 1.15k | { |
1031 | 1.15k | IM3Function reference = slot(IM3Function); |
1032 | | |
1033 | 1.15k | if (M3_UNLIKELY(not reference)) { |
1034 | 11 | newTrap(m3Err_trapNullReference); |
1035 | 11 | } |
1036 | | |
1037 | 1.15k | nextOp(); |
1038 | 1.15k | } |
1039 | | |
1040 | | |
1041 | | d_m3Op(CallIndirect) |
1042 | 50 | { |
1043 | 50 | d_m3CheckNativeStack(); |
1044 | | |
1045 | 50 | M3Table* table = immediate(M3Table*); |
1046 | 50 | u64 tableIndex = d_m3WideOperand(table->isTable64); |
1047 | 50 | IM3FuncType type = immediate(IM3FuncType); |
1048 | 50 | i32 stackOffset = immediate(i32); |
1049 | 50 | IM3Memory memory = m3MemInfo(_mem); |
1050 | | |
1051 | 50 | m3stack_t sp = _sp + stackOffset; |
1052 | | |
1053 | 50 | m3ret_t r = m3Err_none; |
1054 | | |
1055 | 50 | if (M3_LIKELY(tableIndex < table->size)) { |
1056 | 12 | IM3Function function = (IM3Function)table->elements[tableIndex]; |
1057 | | |
1058 | 12 | if (M3_LIKELY(function)) { |
1059 | 4 | if (M3_LIKELY(type == function->funcType)) { |
1060 | 3 | if (M3_UNLIKELY(not function->compiled)) { |
1061 | 3 | r = CompileFunction(function); |
1062 | 3 | } |
1063 | | |
1064 | 3 | if (M3_LIKELY(not r)) { |
1065 | | // a table may hold functions from another module, and those |
1066 | | // run against their own module's memory |
1067 | 2 | M3MemoryHeader* calleeMem = Module_MemoryHeader(function->module); |
1068 | | |
1069 | | #if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
1070 | | r = Call(function->compiled, sp, calleeMem, d_m3OpDefaultArgs, d_m3BaseCstr); |
1071 | | #else |
1072 | 2 | r = Call(function->compiled, sp, calleeMem, d_m3OpDefaultArgs); |
1073 | 2 | #endif |
1074 | | |
1075 | 2 | _mem = memory->mallocated; |
1076 | | |
1077 | 2 | if (M3_LIKELY(not r)) { |
1078 | 1 | nextOpDirect(); |
1079 | 1 | } else { |
1080 | 1 | d_m3RecordCallFrame(memory, function); |
1081 | 1 | pushBacktraceFrame(); |
1082 | 1 | forwardTrap(r); |
1083 | 1 | } |
1084 | 2 | } |
1085 | 3 | } else { |
1086 | 1 | r = m3Err_trapIndirectCallTypeMismatch; |
1087 | 1 | } |
1088 | 8 | } else { |
1089 | 8 | r = m3Err_trapTableElementIsNull; |
1090 | 8 | } |
1091 | 38 | } else { |
1092 | 38 | r = m3Err_trapTableIndexOutOfRange; |
1093 | 38 | } |
1094 | | |
1095 | 48 | if (M3_UNLIKELY(r)) { |
1096 | 48 | newTrap(r); |
1097 | 48 | } else { |
1098 | 0 | forwardTrap(r); |
1099 | 0 | } |
1100 | 48 | } |
1101 | | |
1102 | | |
1103 | | // return_call / return_call_indirect: the callee takes over this function's stack frame |
1104 | | // instead of getting one of its own. The spec guarantees the callee returns exactly what |
1105 | | // the enclosing function returns, so the two frames share their return slots and only the |
1106 | | // arguments have to be relocated: the compiler stages them above the caller's stack (they |
1107 | | // can still read the args/locals they're about to overwrite) and the op slides them down |
1108 | | // onto the frame base. The jump is a tail call, so neither the m3 stack nor the native |
1109 | | // stack grows. Tail recursion therefore runs in constant space, unless the return_call |
1110 | | // sits inside a loop or a try region: those hold a native frame that the tail call walks |
1111 | | // away from instead of unwinding, and d_m3CheckNativeStack bounds the pile they make. |
1112 | | #define d_m3TailCallArgs(RETURNSLOTS, STACKOFFSET, NUMARGSLOTS) \ |
1113 | 179M | memmove ((void *) (_sp + (RETURNSLOTS)), (const void *) (_sp + (STACKOFFSET)), \ |
1114 | 179M | (size_t) (NUMARGSLOTS) * sizeof (m3slot_t)) |
1115 | | |
1116 | | d_m3Op(ReturnCall) |
1117 | 179M | { |
1118 | 179M | pc_t callPC = immediate(pc_t); |
1119 | 179M | i32 stackOffset = immediate(i32); |
1120 | 179M | i32 returnSlots = immediate(i32); |
1121 | 179M | u32 numArgSlots = immediate(u32); |
1122 | | |
1123 | 179M | m3ret_t possible_trap = m3_Yield(); |
1124 | 179M | if (M3_UNLIKELY(possible_trap)) { |
1125 | 0 | newTrap(possible_trap); |
1126 | 0 | } |
1127 | | |
1128 | 179M | d_m3TailCallArgs(returnSlots, stackOffset, numArgSlots); |
1129 | | |
1130 | 179M | jumpOpDirect(callPC); |
1131 | 179M | } |
1132 | | |
1133 | | |
1134 | | d_m3Op(ReturnCallRef) |
1135 | 1.91k | { |
1136 | 1.91k | IM3Function function = slot(IM3Function); |
1137 | 1.91k | IM3FuncType type = immediate(IM3FuncType); |
1138 | 1.91k | i32 stackOffset = immediate(i32); |
1139 | 1.91k | i32 returnSlots = immediate(i32); |
1140 | 1.91k | u32 numArgSlots = immediate(u32); |
1141 | | |
1142 | 1.91k | m3ret_t r = m3Err_none; |
1143 | | |
1144 | 1.91k | if (M3_LIKELY(function)) { |
1145 | 1.89k | if (M3_LIKELY(type == function->funcType)) { |
1146 | 1.89k | if (M3_UNLIKELY(not function->compiled)) { |
1147 | 0 | r = CompileFunction(function); |
1148 | 0 | } |
1149 | | |
1150 | 1.89k | if (M3_LIKELY(not r)) { |
1151 | 1.89k | r = m3_Yield(); |
1152 | | |
1153 | 1.89k | if (M3_LIKELY(not r)) { |
1154 | 1.89k | d_m3TailCallArgs(returnSlots, stackOffset, numArgSlots); |
1155 | | |
1156 | 1.89k | jumpOpDirect(function->compiled); |
1157 | 1.89k | } |
1158 | 1.89k | } |
1159 | 1.89k | } else { |
1160 | 0 | r = m3Err_trapIndirectCallTypeMismatch; |
1161 | 0 | } |
1162 | 1.89k | } else { |
1163 | 24 | r = m3Err_trapNullFunctionRef; |
1164 | 24 | } |
1165 | | |
1166 | 1.91k | newTrap(r); |
1167 | 1.91k | } |
1168 | | |
1169 | | |
1170 | | d_m3Op(ReturnCallIndirect) |
1171 | 45 | { |
1172 | 45 | M3Table* table = immediate(M3Table*); |
1173 | 45 | u64 tableIndex = d_m3WideOperand(table->isTable64); |
1174 | 45 | IM3FuncType type = immediate(IM3FuncType); |
1175 | 45 | i32 stackOffset = immediate(i32); |
1176 | 45 | i32 returnSlots = immediate(i32); |
1177 | 45 | u32 numArgSlots = immediate(u32); |
1178 | | |
1179 | 45 | m3ret_t r = m3Err_none; |
1180 | | |
1181 | 45 | if (M3_LIKELY(tableIndex < table->size)) { |
1182 | 7 | IM3Function function = (IM3Function)table->elements[tableIndex]; |
1183 | | |
1184 | 7 | if (M3_LIKELY(function)) { |
1185 | 3 | if (M3_LIKELY(type == function->funcType)) { |
1186 | 2 | if (M3_UNLIKELY(not function->compiled)) { |
1187 | 2 | r = CompileFunction(function); |
1188 | 2 | } |
1189 | | |
1190 | 2 | if (M3_LIKELY(not r)) { |
1191 | 1 | r = m3_Yield(); |
1192 | | |
1193 | 1 | if (M3_LIKELY(not r)) { |
1194 | 1 | d_m3TailCallArgs(returnSlots, stackOffset, numArgSlots); |
1195 | | |
1196 | 1 | jumpOpDirect(function->compiled); |
1197 | 1 | } |
1198 | 1 | } |
1199 | 2 | } else { |
1200 | 1 | r = m3Err_trapIndirectCallTypeMismatch; |
1201 | 1 | } |
1202 | 4 | } else { |
1203 | 4 | r = m3Err_trapTableElementIsNull; |
1204 | 4 | } |
1205 | 38 | } else { |
1206 | 38 | r = m3Err_trapTableIndexOutOfRange; |
1207 | 38 | } |
1208 | | |
1209 | 45 | newTrap(r); |
1210 | 45 | } |
1211 | | |
1212 | | |
1213 | | d_m3Op(CallRawFunction) |
1214 | 0 | { |
1215 | 0 | d_m3TracePrepare |
1216 | |
|
1217 | 0 | M3ImportContext ctx; |
1218 | |
|
1219 | 0 | M3RawCall call = (M3RawCall)(*_pc++); |
1220 | 0 | ctx.function = immediate(IM3Function); |
1221 | 0 | ctx.userdata = immediate(void*); |
1222 | 0 | u64* const sp = ((u64*)_sp); |
1223 | 0 | IM3Memory memory = m3MemInfo(_mem); |
1224 | |
|
1225 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
1226 | |
|
1227 | | #if d_m3EnableStrace |
1228 | | IM3FuncType ftype = ctx.function->funcType; |
1229 | | |
1230 | | char outbuff[1024]; |
1231 | | char* outp = outbuff; |
1232 | | char* oute = outbuff + 1024; |
1233 | | |
1234 | | outp += snprintf(outp, oute - outp, "%s!%s(", ctx.function->import.moduleUtf8, ctx.function->import.fieldUtf8); |
1235 | | |
1236 | | const int nArgs = ftype->numArgs; |
1237 | | const int nRets = ftype->numRets; |
1238 | | u64* args = sp + nRets; |
1239 | | for (int i = 0; i < nArgs; i++) { |
1240 | | const int type = ftype->types[nRets + i]; |
1241 | | switch (type) { |
1242 | | case c_m3Type_i32: outp += snprintf(outp, oute - outp, "%" PRIi32, *(i32*)(args + i)); break; |
1243 | | case c_m3Type_i64: outp += snprintf(outp, oute - outp, "%" PRIi64, *(i64*)(args + i)); break; |
1244 | | case c_m3Type_f32: outp += snprintf(outp, oute - outp, "%" PRIf32, *(f32*)(args + i)); break; |
1245 | | case c_m3Type_f64: outp += snprintf(outp, oute - outp, "%" PRIf64, *(f64*)(args + i)); break; |
1246 | | default: outp += snprintf(outp, oute - outp, "<type %d>", type); break; |
1247 | | } |
1248 | | if (i < nArgs - 1) { |
1249 | | outp += snprintf(outp, oute - outp, ", "); |
1250 | | } |
1251 | | } |
1252 | | // closed here rather than after the last argument: an import taking none has |
1253 | | // no last argument to close it |
1254 | | outp += snprintf(outp, oute - outp, ")"); |
1255 | | # if d_m3EnableStrace >= 2 |
1256 | | outp += snprintf(outp, oute - outp, " { <native> }"); |
1257 | | # endif |
1258 | | #endif |
1259 | | |
1260 | | // m3_Call uses runtime->stack to set-up initial exported function stack. |
1261 | | // Reconfigure the stack to enable recursive invocations of m3_Call. |
1262 | | // I.e. exported/table function can be called from an impoted function. |
1263 | 0 | void* stack_backup = runtime->stack; |
1264 | 0 | runtime->stack = sp; |
1265 | | // the memory this import was bound to, which is memory 0 unless the host |
1266 | | // module named another one. _mem itself stays on the caller's memory: |
1267 | | // the trap path below and the backtrace recorder still read it. |
1268 | 0 | m3ret_t possible_trap = call(runtime, &ctx, sp, m3MemData(ctx.function->hostMemory->mallocated)); |
1269 | 0 | runtime->stack = stack_backup; |
1270 | |
|
1271 | | #if d_m3EnableStrace |
1272 | | if (M3_UNLIKELY(possible_trap)) { |
1273 | | d_m3TracePrint("%s -> %s", outbuff, (char*)possible_trap); |
1274 | | } else if (ftype and ftype->numRets) { |
1275 | | d_m3TracePrint("%s = %s", outbuff, SPrintFunctionRetList(ftype, (m3stack_t)sp)); |
1276 | | } else { |
1277 | | d_m3TracePrint("%s", outbuff); |
1278 | | } |
1279 | | #endif |
1280 | |
|
1281 | 0 | if (M3_UNLIKELY(possible_trap)) { |
1282 | 0 | _mem = memory->mallocated; |
1283 | | // an exception the host threw (m3_ThrowException) is not a trap yet, and |
1284 | | // may well be caught: it records no frame, as a Wasm throw doesn't |
1285 | 0 | if (possible_trap != m3Err_pendingException) { |
1286 | 0 | pushBacktraceFrame(); |
1287 | 0 | } |
1288 | 0 | } |
1289 | 0 | forwardTrap(possible_trap); |
1290 | 0 | } |
1291 | | |
1292 | | |
1293 | | d_m3Op(MemSize) |
1294 | 2.55M | { |
1295 | 2.55M | IM3Memory memory = m3MemInfo(_mem); |
1296 | | |
1297 | 2.55M | _r0 = memory->numPages; |
1298 | | |
1299 | 2.55M | nextOp(); |
1300 | 2.55M | } |
1301 | | |
1302 | | |
1303 | | d_m3Op(MemGrow) |
1304 | 52.1k | { |
1305 | 52.1k | IM3Runtime runtime = m3MemRuntime(_mem); |
1306 | 52.1k | IM3Memory memory = m3MemInfo(_mem); |
1307 | | |
1308 | 52.1k | i32 numPagesToGrow = (i32)_r0; |
1309 | 52.1k | if (numPagesToGrow >= 0) { |
1310 | 46.7k | _r0 = (m3reg_t)memory->numPages; |
1311 | | |
1312 | 46.7k | if (M3_LIKELY(numPagesToGrow)) { |
1313 | 29.9k | u64 requiredPages = memory->numPages + (u32)numPagesToGrow; |
1314 | | |
1315 | 29.9k | M3Result r = ResizeMemory(runtime, memory, requiredPages); |
1316 | 29.9k | if (r) { |
1317 | 4.32k | _r0 = -1; |
1318 | 4.32k | } |
1319 | | |
1320 | 29.9k | _mem = memory->mallocated; |
1321 | 29.9k | } |
1322 | 46.7k | } else { |
1323 | 5.35k | _r0 = -1; |
1324 | 5.35k | } |
1325 | | |
1326 | 52.1k | nextOp(); |
1327 | 52.1k | } |
1328 | | |
1329 | | |
1330 | | #if d_m3HasMemory64 |
1331 | | |
1332 | | // memory.grow on a 64-bit memory. The delta is a full u64 rather than a value |
1333 | | // the sign of which can stand in for "too big", and failure answers 2^64-1 |
1334 | | // instead of 2^32-1 - which is the same -1 in the register, sized by the slot |
1335 | | // it is written to. |
1336 | | d_m3Op(MemGrow64) |
1337 | 31.2k | { |
1338 | 31.2k | IM3Runtime runtime = m3MemRuntime(_mem); |
1339 | 31.2k | IM3Memory memory = m3MemInfo(_mem); |
1340 | | |
1341 | 31.2k | u64 numPagesToGrow = (u64)_r0; |
1342 | 31.2k | u64 numPages = memory->numPages; |
1343 | | |
1344 | 31.2k | if (M3_LIKELY(numPagesToGrow)) { |
1345 | | // maxPages is never below the current size, so the difference cannot |
1346 | | // wrap; asking for more than it is a request nothing could satisfy |
1347 | 25.1k | if (numPagesToGrow <= memory->maxPages - numPages and |
1348 | 19.1k | not ResizeMemory(runtime, memory, numPages + numPagesToGrow)) { |
1349 | 13.9k | _r0 = (m3reg_t)numPages; |
1350 | 13.9k | } else { |
1351 | 11.1k | _r0 = -1; |
1352 | 11.1k | } |
1353 | | |
1354 | 25.1k | _mem = memory->mallocated; |
1355 | 25.1k | } else { |
1356 | 6.07k | _r0 = (m3reg_t)numPages; |
1357 | 6.07k | } |
1358 | | |
1359 | 31.2k | nextOp(); |
1360 | 31.2k | } |
1361 | | |
1362 | | #endif // d_m3HasMemory64 |
1363 | | |
1364 | | |
1365 | | d_m3Op(MemCopy) |
1366 | 1.19k | { |
1367 | 1.19k | u64 size = (u32)_r0; |
1368 | 1.19k | u64 source = slot(u32); |
1369 | 1.19k | u64 destination = slot(u32); |
1370 | | |
1371 | 1.19k | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1372 | 1.19k | if (M3_LIKELY(d_m3MemRangeOk(source, size, _mem))) { |
1373 | 1.19k | u8* dst = m3MemData(_mem) + destination; |
1374 | 1.19k | u8* src = m3MemData(_mem) + source; |
1375 | 1.19k | memmove(dst, src, (size_t)size); |
1376 | | |
1377 | 1.19k | nextOp(); |
1378 | 1.19k | } else { |
1379 | 6 | d_outOfBoundsMemOp(source, size); |
1380 | 6 | } |
1381 | 1.19k | } else { |
1382 | 3 | d_outOfBoundsMemOp(destination, size); |
1383 | 3 | } |
1384 | 1.19k | } |
1385 | | |
1386 | | |
1387 | | #if d_m3HasMemory64 |
1388 | | |
1389 | | // memory.copy within a single 64-bit memory: every operand is a full u64. |
1390 | | d_m3Op(MemCopy64) |
1391 | 3.23k | { |
1392 | 3.23k | u64 size = (u64)_r0; |
1393 | 3.23k | u64 source = slot(u64); |
1394 | 3.23k | u64 destination = slot(u64); |
1395 | | |
1396 | 3.23k | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1397 | 3.07k | if (M3_LIKELY(d_m3MemRangeOk(source, size, _mem))) { |
1398 | 2.99k | u8* dst = m3MemData(_mem) + destination; |
1399 | 2.99k | u8* src = m3MemData(_mem) + source; |
1400 | 2.99k | memmove(dst, src, (size_t)size); |
1401 | | |
1402 | 2.99k | nextOp(); |
1403 | 2.99k | } else { |
1404 | 77 | d_outOfBoundsMemOp(source, size); |
1405 | 77 | } |
1406 | 3.07k | } else { |
1407 | 154 | d_outOfBoundsMemOp(destination, size); |
1408 | 154 | } |
1409 | 3.23k | } |
1410 | | |
1411 | | #endif // d_m3HasMemory64 |
1412 | | |
1413 | | |
1414 | | // Points the _mem register at another memory: one of the module's own, or |
1415 | | // memory 0 of a module being called into. The compiler emits these in pairs, |
1416 | | // around a single access or a single cross-module call, so _mem is back where |
1417 | | // it belongs before anything that reads it for another purpose - a backtrace, |
1418 | | // the stack-limit check - can run. |
1419 | | d_m3Op(SetMemory) |
1420 | 72.5k | { |
1421 | 72.5k | IM3Memory memory = immediate(IM3Memory); |
1422 | | |
1423 | 72.5k | _mem = memory->mallocated; |
1424 | | |
1425 | 72.5k | nextOp(); |
1426 | 72.5k | } |
1427 | | |
1428 | | |
1429 | | #if d_m3HasMultiMemory |
1430 | | |
1431 | | // memory.copy between two different memories. The pair-of-SetMemory trick only |
1432 | | // reaches one memory at a time, so this one names both outright. |
1433 | | // |
1434 | | // The two need not be addressed the same way, so each operand's width comes |
1435 | | // from the memory it belongs to: bit 0 of the widths immediate for the |
1436 | | // destination, bit 1 for the source. The length follows the narrower of the |
1437 | | // two, which is 64-bit only when both are. |
1438 | | d_m3Op(MemCopy_x) |
1439 | 2.51k | { |
1440 | 2.51k | IM3Memory destMemory = immediate(IM3Memory); |
1441 | 2.51k | IM3Memory sourceMemory = immediate(IM3Memory); |
1442 | 2.51k | u32 widths = immediate(u32); |
1443 | | |
1444 | 2.51k | M3MemoryHeader* destMem = destMemory->mallocated; |
1445 | 2.51k | M3MemoryHeader* sourceMem = sourceMemory->mallocated; |
1446 | | |
1447 | 2.51k | u64 size = (widths == 0x3) ? (u64)_r0 : (u64)(u32)_r0; |
1448 | 2.51k | u64 source = d_m3WideOperand(widths & 0x2); |
1449 | 2.51k | u64 destination = d_m3WideOperand(widths & 0x1); |
1450 | | |
1451 | 2.51k | if (M3_LIKELY(d_m3MemRangeOk(destination, size, destMem))) { |
1452 | 2.44k | if (M3_LIKELY(d_m3MemRangeOk(source, size, sourceMem))) { |
1453 | 2.41k | memmove(m3MemData(destMem) + destination, m3MemData(sourceMem) + source, (size_t)size); |
1454 | | |
1455 | 2.41k | nextOp(); |
1456 | 2.41k | } else { |
1457 | 23 | d_outOfBoundsMemOp(source, size); |
1458 | 23 | } |
1459 | 2.44k | } else { |
1460 | 77 | d_outOfBoundsMemOp(destination, size); |
1461 | 77 | } |
1462 | 2.51k | } |
1463 | | |
1464 | | #endif // d_m3HasMultiMemory |
1465 | | |
1466 | | |
1467 | | d_m3Op(MemFill) |
1468 | 3.78k | { |
1469 | 3.78k | u32 size = (u32)_r0; |
1470 | 3.78k | u32 byte = slot(u32); |
1471 | 3.78k | u64 destination = slot(u32); |
1472 | | |
1473 | 3.78k | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1474 | 3.75k | u8* mem8 = m3MemData(_mem) + destination; |
1475 | 3.75k | memset(mem8, (u8)byte, size); |
1476 | 3.75k | nextOp(); |
1477 | 3.75k | } else { |
1478 | 27 | d_outOfBoundsMemOp(destination, size); |
1479 | 27 | } |
1480 | 3.78k | } |
1481 | | |
1482 | | |
1483 | | #if d_m3HasMemory64 |
1484 | | |
1485 | | // memory.fill on a 64-bit memory. The byte to write stays an i32 - it is a |
1486 | | // value, not an address - so only the destination and the length widen. |
1487 | | d_m3Op(MemFill64) |
1488 | 1.16k | { |
1489 | 1.16k | u64 size = (u64)_r0; |
1490 | 1.16k | u32 byte = slot(u32); |
1491 | 1.16k | u64 destination = slot(u64); |
1492 | | |
1493 | 1.16k | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1494 | 1.09k | u8* mem8 = m3MemData(_mem) + destination; |
1495 | 1.09k | memset(mem8, (u8)byte, (size_t)size); |
1496 | 1.09k | nextOp(); |
1497 | 1.09k | } else { |
1498 | 73 | d_outOfBoundsMemOp(destination, size); |
1499 | 73 | } |
1500 | 1.16k | } |
1501 | | |
1502 | | #endif // d_m3HasMemory64 |
1503 | | |
1504 | | |
1505 | | d_m3Op(MemInit) |
1506 | 0 | { |
1507 | 0 | M3DataSegment* segment = immediate(M3DataSegment*); |
1508 | |
|
1509 | 0 | u64 size = (u32)_r0; |
1510 | 0 | u64 source = slot(u32); |
1511 | 0 | u64 destination = slot(u32); |
1512 | |
|
1513 | 0 | u64 available = segment->dropped ? 0 : segment->size; |
1514 | |
|
1515 | 0 | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1516 | 0 | if (M3_LIKELY(source <= available and size <= available - source)) { |
1517 | 0 | memcpy(m3MemData(_mem) + destination, segment->data + source, (size_t)size); |
1518 | 0 | nextOp(); |
1519 | 0 | } else { |
1520 | 0 | d_outOfBoundsMemOp(source, size); |
1521 | 0 | } |
1522 | 0 | } else { |
1523 | 0 | d_outOfBoundsMemOp(destination, size); |
1524 | 0 | } |
1525 | 0 | } |
1526 | | |
1527 | | |
1528 | | #if d_m3HasMemory64 |
1529 | | |
1530 | | // memory.init into a 64-bit memory. The segment is indexed as an i32 whatever |
1531 | | // the memory is, so only the destination widens. |
1532 | | d_m3Op(MemInit64) |
1533 | 0 | { |
1534 | 0 | M3DataSegment* segment = immediate(M3DataSegment*); |
1535 | |
|
1536 | 0 | u64 size = (u32)_r0; |
1537 | 0 | u64 source = slot(u32); |
1538 | 0 | u64 destination = slot(u64); |
1539 | |
|
1540 | 0 | u64 available = segment->dropped ? 0 : segment->size; |
1541 | |
|
1542 | 0 | if (M3_LIKELY(d_m3MemRangeOk(destination, size, _mem))) { |
1543 | 0 | if (M3_LIKELY(source <= available and size <= available - source)) { |
1544 | 0 | memcpy(m3MemData(_mem) + destination, segment->data + source, (size_t)size); |
1545 | 0 | nextOp(); |
1546 | 0 | } else { |
1547 | 0 | d_outOfBoundsMemOp(source, size); |
1548 | 0 | } |
1549 | 0 | } else { |
1550 | 0 | d_outOfBoundsMemOp(destination, size); |
1551 | 0 | } |
1552 | 0 | } |
1553 | | |
1554 | | #endif // d_m3HasMemory64 |
1555 | | |
1556 | | |
1557 | | d_m3Op(DataDrop) |
1558 | 0 | { |
1559 | 0 | M3DataSegment* segment = immediate(M3DataSegment*); |
1560 | 0 | segment->dropped = true; |
1561 | |
|
1562 | 0 | nextOp(); |
1563 | 0 | } |
1564 | | |
1565 | | |
1566 | | #if d_m3HasRefTypes |
1567 | | |
1568 | | d_m3Op(TableGet) |
1569 | 140k | { |
1570 | 140k | M3Table* table = immediate(M3Table*); |
1571 | 140k | u64 index = d_m3WideOperand(table->isTable64); |
1572 | | |
1573 | 140k | if (M3_LIKELY(index < table->size)) { |
1574 | 140k | _r0 = (u64)(uintptr_t)table->elements[index]; |
1575 | 140k | nextOp(); |
1576 | 140k | } else { |
1577 | 104 | newTrap(m3Err_trapTableOutOfBounds); |
1578 | 104 | } |
1579 | 140k | } |
1580 | | |
1581 | | |
1582 | | d_m3Op(TableSet) |
1583 | 89.0k | { |
1584 | 89.0k | M3Table* table = immediate(M3Table*); |
1585 | 89.0k | void* value = slot(void*); |
1586 | 89.0k | u64 index = d_m3WideOperand(table->isTable64); |
1587 | | |
1588 | 89.0k | if (M3_LIKELY(index < table->size)) { |
1589 | 89.0k | table->elements[index] = value; |
1590 | 89.0k | nextOp(); |
1591 | 89.0k | } else { |
1592 | 8 | newTrap(m3Err_trapTableOutOfBounds); |
1593 | 8 | } |
1594 | 89.0k | } |
1595 | | |
1596 | | |
1597 | | d_m3Op(TableSize) |
1598 | 90.3k | { |
1599 | 90.3k | M3Table* table = immediate(M3Table*); |
1600 | | |
1601 | 90.3k | _r0 = table->size; |
1602 | | |
1603 | 90.3k | nextOp(); |
1604 | 90.3k | } |
1605 | | |
1606 | | |
1607 | | d_m3Op(TableGrow) |
1608 | 10.5k | { |
1609 | 10.5k | M3Table* table = immediate(M3Table*); |
1610 | 10.5k | u64 delta = d_m3WideOperand(table->isTable64); |
1611 | 10.5k | void* value = slot(void*); |
1612 | | |
1613 | 10.5k | u32 oldSize = table->size; |
1614 | 10.5k | u32 maxSize = table->maxSize ? table->maxSize : d_m3MaxSaneTableSize; |
1615 | | |
1616 | | // a table64 delta is a whole u64, so the sum is formed only once it is |
1617 | | // known to fit |
1618 | 10.5k | u64 newSize = (delta <= maxSize - oldSize) ? (u64)oldSize + delta |
1619 | 10.5k | : (u64)maxSize + 1; |
1620 | | |
1621 | 10.5k | if (newSize == oldSize) // a zero delta never reallocates, and the table may have no storage yet |
1622 | 309 | { |
1623 | 309 | _r0 = oldSize; |
1624 | 309 | nextOp(); |
1625 | 309 | } |
1626 | | |
1627 | 10.2k | IM3Runtime runtime = m3MemRuntime(_mem); |
1628 | 10.2k | if (newSize <= maxSize and (not runtime->tableElementsLimit or |
1629 | 7.44k | delta <= runtime->tableElementsLimit - runtime->tableElementsUsed)) { |
1630 | 5.85k | void** elements = m3_ReallocArray(void*, table->elements, (size_t)newSize, oldSize); |
1631 | | |
1632 | 5.85k | if (elements) { |
1633 | 5.85k | runtime->tableElementsUsed += newSize - oldSize; |
1634 | 5.85k | table->elements = elements; |
1635 | 5.85k | table->size = (u32)newSize; |
1636 | | |
1637 | 17.9M | for (u32 i = oldSize; i < table->size; ++i) { |
1638 | 17.9M | table->elements[i] = value; |
1639 | 17.9M | } |
1640 | | |
1641 | 5.85k | _r0 = oldSize; |
1642 | 5.85k | nextOp(); |
1643 | 5.85k | } |
1644 | 5.85k | } |
1645 | | |
1646 | | // spec: a failed grow returns -1 - which for a table64 is 2^64-1, and the |
1647 | | // slot it is pushed to is what decides how much of the register is seen |
1648 | 4.36k | _r0 = -1; |
1649 | | |
1650 | 4.36k | nextOp(); |
1651 | 10.2k | } |
1652 | | |
1653 | | |
1654 | | d_m3Op(TableInit) |
1655 | 2.12k | { |
1656 | 2.12k | M3Table* table = immediate(M3Table*); |
1657 | 2.12k | M3ElementSegment* segment = immediate(M3ElementSegment*); |
1658 | 2.12k | u32 count = slot(u32); |
1659 | 2.12k | u32 source = slot(u32); |
1660 | | // an element segment is indexed as an i32 whatever the table is; only the |
1661 | | // destination follows the table's index type |
1662 | 2.12k | u64 destination = d_m3WideOperand(table->isTable64); |
1663 | | |
1664 | 2.12k | u64 available = segment->dropped ? 0 : segment->numElements; |
1665 | | |
1666 | 2.12k | if (M3_LIKELY(destination <= table->size and count <= table->size - destination and |
1667 | 2.12k | (u64) source + count <= available)) { |
1668 | 2.11k | for (u32 i = 0; i < count; ++i) { |
1669 | 0 | table->elements[destination + i] = segment->resolved[source + i]; |
1670 | 0 | } |
1671 | | |
1672 | 2.11k | nextOp(); |
1673 | 2.11k | } else { |
1674 | 6 | newTrap(m3Err_trapTableOutOfBounds); |
1675 | 6 | } |
1676 | 2.12k | } |
1677 | | |
1678 | | |
1679 | | d_m3Op(ElemDrop) |
1680 | 232k | { |
1681 | 232k | M3ElementSegment* segment = immediate(M3ElementSegment*); |
1682 | 232k | segment->dropped = true; |
1683 | | |
1684 | 232k | nextOp(); |
1685 | 232k | } |
1686 | | |
1687 | | |
1688 | | d_m3Op(TableCopy) |
1689 | 3.19k | { |
1690 | 3.19k | M3Table* dst = immediate(M3Table*); |
1691 | 3.19k | M3Table* src = immediate(M3Table*); |
1692 | | // the length follows the narrower of the two tables, so it is 64-bit only |
1693 | | // when both are |
1694 | 3.19k | u64 count = d_m3WideOperand(dst->isTable64 and src->isTable64); |
1695 | 3.19k | u64 source = d_m3WideOperand(src->isTable64); |
1696 | 3.19k | u64 destination = d_m3WideOperand(dst->isTable64); |
1697 | | |
1698 | 3.19k | if (M3_LIKELY(destination <= dst->size and count <= dst->size - destination and |
1699 | 3.19k | source <= src->size and count <= src->size - source)) { |
1700 | 2.99k | memmove(dst->elements + destination, src->elements + source, (size_t)count * sizeof(void*)); |
1701 | | |
1702 | 2.99k | nextOp(); |
1703 | 2.99k | } else { |
1704 | 193 | newTrap(m3Err_trapTableOutOfBounds); |
1705 | 193 | } |
1706 | 3.19k | } |
1707 | | |
1708 | | |
1709 | | d_m3Op(TableFill) |
1710 | 4.94k | { |
1711 | 4.94k | M3Table* table = immediate(M3Table*); |
1712 | 4.94k | u64 count = d_m3WideOperand(table->isTable64); |
1713 | 4.94k | void* value = slot(void*); |
1714 | 4.94k | u64 index = d_m3WideOperand(table->isTable64); |
1715 | | |
1716 | 4.94k | if (M3_LIKELY(index <= table->size and count <= table->size - index)) { |
1717 | 107k | for (u64 i = 0; i < count; ++i) { |
1718 | 102k | table->elements[index + i] = value; |
1719 | 102k | } |
1720 | | |
1721 | 4.93k | nextOp(); |
1722 | 4.93k | } else { |
1723 | 9 | newTrap(m3Err_trapTableOutOfBounds); |
1724 | 9 | } |
1725 | 4.94k | } |
1726 | | |
1727 | | #endif // d_m3HasRefTypes |
1728 | | |
1729 | | |
1730 | | // it's a debate: should the compilation be trigger be the caller or callee page. |
1731 | | // it's a much easier to put it in the caller pager. if it's in the callee, either the entire page |
1732 | | // has be left dangling or it's just a stub that jumps to a newly acquired page. In Gestalt, I opted |
1733 | | // for the stub approach. Stubbing makes it easier to dynamically free the compilation. You can also |
1734 | | // do both. |
1735 | | d_m3Op(Compile) |
1736 | 6.39k | { |
1737 | 6.39k | rewrite_op(op_Call); |
1738 | | |
1739 | 6.39k | IM3Function function = immediate(IM3Function); |
1740 | | |
1741 | 6.39k | m3ret_t result = m3Err_none; |
1742 | | |
1743 | 6.39k | if (M3_UNLIKELY(not function->compiled)) { // check to see if function was compiled since this operation was emitted. |
1744 | 103 | result = CompileFunction(function); |
1745 | 103 | } |
1746 | | |
1747 | 6.39k | if (not result) { |
1748 | | // patch up compiled pc and call rewritten op_Call |
1749 | 6.38k | *((void**)--_pc) = (void*)(function->compiled); |
1750 | 6.38k | --_pc; |
1751 | 6.38k | nextOpDirect(); |
1752 | 6.38k | } |
1753 | | |
1754 | 6.39k | newTrap(result); |
1755 | 6.39k | } |
1756 | | |
1757 | | |
1758 | | // same as op_Compile, for a call site that was emitted as a tail call |
1759 | | d_m3Op(CompileReturnCall) |
1760 | 8.65k | { |
1761 | 8.65k | rewrite_op(op_ReturnCall); |
1762 | | |
1763 | 8.65k | IM3Function function = immediate(IM3Function); |
1764 | | |
1765 | 8.65k | m3ret_t result = m3Err_none; |
1766 | | |
1767 | 8.65k | if (M3_UNLIKELY(not function->compiled)) { |
1768 | 21 | result = CompileFunction(function); |
1769 | 21 | } |
1770 | | |
1771 | 8.65k | if (not result) { |
1772 | | // patch up compiled pc and call rewritten op_ReturnCall |
1773 | 8.65k | *((void**)--_pc) = (void*)(function->compiled); |
1774 | 8.65k | --_pc; |
1775 | 8.65k | nextOpDirect(); |
1776 | 8.65k | } |
1777 | | |
1778 | 8.65k | newTrap(result); |
1779 | 8.65k | } |
1780 | | |
1781 | | |
1782 | | #if d_m3HasStackSwitching |
1783 | | // Suspending for a reason that is not a control tag - the host asked, or the |
1784 | | // gas ran out. There is no handler to look for and no payload to carry, and |
1785 | | // clearing the routing a previous suspend left behind is what keeps this from |
1786 | | // being mistaken for one: a resume reads those fields to decide where to send |
1787 | | // the marker, and would otherwise send this one into whatever stub was last |
1788 | | // used, with whatever payload last went with it. |
1789 | | // |
1790 | | // No continuation handles it either. A resume that finds itself named as the |
1791 | | // handler takes the suspend as its own, so naming the suspending continuation |
1792 | | // would stop a suspend from inside a resumed one at that resume, with no stub |
1793 | | // to run. Naming none sends it through every resume up to the host. |
1794 | | static |
1795 | | void SuspendWithoutTag (IM3Runtime io_runtime, IM3Continuation io_cont, M3SafePointKind i_kind, |
1796 | | pc_t i_pc, m3stack_t i_sp, m3reg_t i_r0 |
1797 | | # if d_m3HasFloat |
1798 | | , |
1799 | | f64 i_fp0 |
1800 | | # endif |
1801 | | ) |
1802 | 0 | { |
1803 | 0 | io_runtime->suspendRequested = false; |
1804 | |
|
1805 | 0 | io_runtime->suspendTag = NULL; |
1806 | 0 | io_runtime->suspendHandlerCont = NULL; |
1807 | 0 | io_runtime->suspendStubPC = NULL; |
1808 | 0 | io_runtime->switchTarget = NULL; |
1809 | 0 | io_runtime->numSuspendPayload = 0; |
1810 | |
|
1811 | 0 | io_cont->pc = i_pc; |
1812 | 0 | io_cont->suspendPoint = (u8)i_kind; |
1813 | 0 | io_cont->sp = i_sp; |
1814 | 0 | io_cont->r0 = i_r0; |
1815 | 0 | # if d_m3HasFloat |
1816 | 0 | io_cont->fp0 = i_fp0; |
1817 | 0 | # endif |
1818 | |
|
1819 | 0 | io_cont->numSuspendResults = 0; |
1820 | 0 | } |
1821 | | #endif // d_m3HasStackSwitching |
1822 | | |
1823 | | |
1824 | | #if d_m3HasGasMetering |
1825 | | |
1826 | | // Pays for the straight-line segment of the function body that follows, before |
1827 | | // any of it runs. The compiler adds up the segment's instruction costs while it |
1828 | | // compiles them and leaves the total here as an immediate, so metering costs one |
1829 | | // subtract and one branch however long the segment is. |
1830 | | // |
1831 | | // The counter is allowed to go negative - the segment was charged in full - and |
1832 | | // nothing resets it, so the trap stands until the host arms the runtime again. |
1833 | | d_m3Op(UseGas) |
1834 | 289M | { |
1835 | 289M | IM3Runtime runtime = m3MemRuntime(_mem); |
1836 | 289M | u32 cost = immediate(u32); |
1837 | | |
1838 | 289M | runtime->gasRemaining -= (i64)cost; |
1839 | | |
1840 | 289M | if (M3_UNLIKELY(runtime->gasRemaining < 0)) { |
1841 | 8.64k | # if d_m3HasStackSwitching |
1842 | | // A runtime that can pause does, at the next pause point: running out |
1843 | | // is a request to stop, like the host's, and the segment runs on to |
1844 | | // it. The counter goes below zero by what it takes to get there. |
1845 | 8.64k | if (runtime->isSuspendable and runtime->activeContinuation) { |
1846 | 0 | runtime->suspendRequested = true; |
1847 | 0 | nextOp(); |
1848 | 0 | } |
1849 | 8.64k | # endif |
1850 | 8.64k | newTrap(m3Err_trapOutOfGas); |
1851 | 8.64k | } |
1852 | | |
1853 | 289M | nextOp(); |
1854 | 289M | } |
1855 | | |
1856 | | #endif // d_m3HasGasMetering |
1857 | | |
1858 | | |
1859 | | // Whether a function's frame fits the stack it is about to be entered on |
1860 | | static inline |
1861 | | bool EntryFits (IM3Function i_function, m3stack_t _sp, M3MemoryHeader* _mem) |
1862 | 179M | { |
1863 | | #if d_m3SkipStackCheck |
1864 | | (void)i_function; |
1865 | | (void)_sp; |
1866 | | (void)_mem; |
1867 | | return true; |
1868 | | #elif d_m3HasStackSwitching |
1869 | 179M | IM3Continuation _act = (_mem ? m3MemRuntime(_mem)->activeContinuation : NULL); |
1870 | 179M | void* maxStack = (_act && _act->valStack) |
1871 | 179M | ? (void*)(_act->valStack + _act->numStackSlots) |
1872 | 179M | : (_mem ? _mem->maxStack : (void*)~(uintptr_t)0); |
1873 | 179M | return M3_LIKELY((void*)(_sp + i_function->maxStackSlots) < maxStack); |
1874 | | #else |
1875 | | return M3_LIKELY((void*)(_sp + i_function->maxStackSlots) < _mem->maxStack); |
1876 | | #endif |
1877 | 179M | } |
1878 | | |
1879 | | // Sets up a function's frame: its locals zeroed, and its constants copied in |
1880 | | static inline |
1881 | | void EnterFrame (IM3Function i_function, m3stack_t _sp) |
1882 | 179M | { |
1883 | | #if defined(DEBUG) |
1884 | | i_function->hits++; |
1885 | | #endif |
1886 | 179M | u8* stack = (u8*)((m3slot_t*)_sp + i_function->numRetAndArgSlots); |
1887 | | |
1888 | 179M | memset(stack, 0x0, i_function->numLocalBytes); |
1889 | 179M | stack += i_function->numLocalBytes; |
1890 | | |
1891 | 179M | if (i_function->constants) { |
1892 | 173M | memcpy(stack, i_function->constants, i_function->numConstantBytes); |
1893 | 173M | } |
1894 | 179M | } |
1895 | | |
1896 | | |
1897 | | d_m3Op(Entry) |
1898 | 179M | { |
1899 | 179M | d_m3ClearRegisters |
1900 | | |
1901 | | d_m3TracePrepare |
1902 | | |
1903 | 179M | IM3Function function = immediate(IM3Function); |
1904 | | #if d_m3EntryKeepsFrame |
1905 | | IM3Memory memory = m3MemInfo(_mem); |
1906 | | #endif |
1907 | | |
1908 | 179M | if (EntryFits(function, _sp, _mem)) { |
1909 | 179M | EnterFrame(function, _sp); |
1910 | | |
1911 | 179M | #if !d_m3EntryKeepsFrame |
1912 | | // there's nothing left to do once the body returns, so hand this native frame |
1913 | | // over to it. That's what lets op_ReturnCall tail-call in constant native stack. |
1914 | 179M | nextOpDirect(); |
1915 | | #else |
1916 | | |
1917 | | # if d_m3EnableStrace >= 2 |
1918 | | d_m3TracePrint("%s %s {", m3_GetFunctionName(function), SPrintFunctionArgList(function, _sp + function->numRetSlots)); |
1919 | | trace_rt->callDepth++; |
1920 | | # endif |
1921 | | |
1922 | | m3ret_t r = nextOpImpl(); |
1923 | | |
1924 | | # if d_m3EnableStrace >= 2 |
1925 | | trace_rt->callDepth--; |
1926 | | |
1927 | | if (r) { |
1928 | | d_m3TracePrint("} !trap = %s", (char*)r); |
1929 | | } else if (GetFunctionNumReturns(function)) { |
1930 | | d_m3TracePrint("} = %s", SPrintFunctionRetList(function->funcType, _sp)); |
1931 | | } else { |
1932 | | d_m3TracePrint("}"); |
1933 | | } |
1934 | | # endif |
1935 | | |
1936 | | if (M3_UNLIKELY(r)) { |
1937 | | _mem = memory->mallocated; |
1938 | | # if d_m3HasStackSwitching |
1939 | | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
1940 | | return RecordEntryFrame(m3MemRuntime(_mem), _pc, _sp, memory, function); |
1941 | | } |
1942 | | # endif |
1943 | | fillBacktraceFrame(); |
1944 | | } |
1945 | | forwardTrap(r); |
1946 | | #endif // d_m3EntryKeepsFrame |
1947 | 179M | } else { |
1948 | 6.35k | newTrap(m3Err_trapStackOverflow); |
1949 | 6.35k | } |
1950 | 179M | } |
1951 | | |
1952 | | |
1953 | | d_m3Op(Loop) |
1954 | 6.26M | { |
1955 | 6.26M | d_m3CheckNativeStack(); |
1956 | | |
1957 | | d_m3TracePrepare |
1958 | | |
1959 | | // regs are unused coming into a loop anyway |
1960 | | // this reduces code size & stack usage |
1961 | 6.26M | d_m3ClearRegisters |
1962 | | |
1963 | 6.26M | m3ret_t r; |
1964 | | |
1965 | 6.26M | IM3Memory memory = m3MemInfo(_mem); |
1966 | | |
1967 | 10.9M | do { |
1968 | | #if d_m3EnableStrace >= 3 |
1969 | | d_m3TracePrint("iter {"); |
1970 | | trace_rt->callDepth++; |
1971 | | #endif |
1972 | 10.9M | r = nextOpImpl(); |
1973 | | |
1974 | | #if d_m3EnableStrace >= 3 |
1975 | | trace_rt->callDepth--; |
1976 | | d_m3TracePrint("}"); |
1977 | | #endif |
1978 | | // linear memory pointer needs refreshed here because the block it's looping over |
1979 | | // can potentially invoke the grow operation. |
1980 | 10.9M | _mem = memory->mallocated; |
1981 | 10.9M | } while (r == _pc); |
1982 | | |
1983 | 6.26M | #if d_m3HasStackSwitching |
1984 | | // The loop's identity is its own pc, which is also where its body starts, |
1985 | | // so replaying it needs nothing else. Without this the continue sentinel |
1986 | | // has no frame left to land in after a resume and gets mistaken for a trap. |
1987 | 6.26M | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
1988 | 0 | return RecordLoopFrame(m3MemRuntime(_mem), _pc, _sp, memory); |
1989 | 0 | } |
1990 | 6.26M | #endif |
1991 | | |
1992 | 6.26M | forwardTrap(r); |
1993 | 6.26M | } |
1994 | | |
1995 | | |
1996 | | #if d_m3HasExceptionHandling |
1997 | | |
1998 | | // try_table. Like op_Loop this claims a native frame, and for the same reason: |
1999 | | // a throw unwinds by returning m3Err_pendingException up the native stack, so |
2000 | | // something has to be standing there to catch it. |
2001 | | // |
2002 | | // Immediates: the clause count, then two words per clause - the tag to match |
2003 | | // (NULL for catch_all / catch_all_ref) and the PC of the stub that moves the |
2004 | | // payload into place and branches to the clause's label. The body follows. |
2005 | | // |
2006 | | // The frame stays alive after the body falls through or branches out of the try |
2007 | | // region, but the handler record is popped at those points (op_PopHandlers), so |
2008 | | // a later throw sees this frame is no longer the innermost one and passes it by. |
2009 | | // |
2010 | | // The handler stack is just a depth counter: an unwind stops at whichever frame |
2011 | | // finds the count still standing at the value its own push produced, which is |
2012 | | // the innermost try region that hasn't been popped. |
2013 | | d_m3Op(TryTable) |
2014 | 2.46M | { |
2015 | 2.46M | d_m3CheckNativeStack(); |
2016 | | |
2017 | 2.46M | IM3Memory memory = m3MemInfo(_mem); |
2018 | 2.46M | IM3Runtime runtime = m3MemRuntime(_mem); |
2019 | | |
2020 | 2.46M | u32 numClauses = immediate(u32); |
2021 | | |
2022 | 2.46M | pc_t clauses = _pc; |
2023 | 2.46M | pc_t body = _pc + 2 * numClauses; |
2024 | | |
2025 | 2.46M | u32 depth = ++runtime->tryDepth; |
2026 | | |
2027 | 2.46M | m3ret_t r = jumpOpImpl(body); |
2028 | | |
2029 | | // the body can have grown linear memory out from under us |
2030 | 2.46M | _mem = memory->mallocated; |
2031 | | |
2032 | | // control is leaving this frame for good, so this try is done either way |
2033 | 2.46M | bool isInnermost = (runtime->tryDepth == depth); |
2034 | 2.46M | runtime->tryDepth = depth - 1; |
2035 | | |
2036 | 2.46M | # if d_m3HasStackSwitching |
2037 | 2.46M | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2038 | 0 | return RecordTryFrame(runtime, clauses, _sp, memory, numClauses, isInnermost); |
2039 | 0 | } |
2040 | 2.46M | # endif |
2041 | | |
2042 | 2.46M | if (M3_UNLIKELY(r == m3Err_pendingException) and isInnermost) { |
2043 | 1.05M | const M3Exception* exception = runtime->pendingException; |
2044 | | |
2045 | 1.05M | for (u32 i = 0; i < numClauses; ++i) { |
2046 | 853k | IM3Tag tag = (IM3Tag)clauses[2 * i]; |
2047 | | |
2048 | 853k | if (tag == NULL or tag == exception->tag) { |
2049 | 853k | pc_t handler = (pc_t)clauses[2 * i + 1]; |
2050 | | |
2051 | | // an unwind leaves nothing meaningful in the registers |
2052 | 853k | d_m3ClearRegisters |
2053 | | |
2054 | 853k | jumpOpDirect(handler); |
2055 | 853k | } |
2056 | 853k | } |
2057 | | |
2058 | | // no clause matched: the exception carries on up |
2059 | 1.05M | } |
2060 | | |
2061 | 2.46M | forwardTrap(r); |
2062 | 2.46M | } |
2063 | | |
2064 | | |
2065 | | // Head of a catch clause's stub: copies the caught exception's payload into the |
2066 | | // slots the stub's branch expects, and the exnref itself for a _ref clause. |
2067 | | // |
2068 | | // A clause that takes no exnref is the end of the road for this exception, so |
2069 | | // it is released here rather than waiting for the call to finish - a module |
2070 | | // that throws inside a loop would otherwise pile up one object per lap. Not so |
2071 | | // once an exnref has been handed out: a local, a global or a table may still be |
2072 | | // holding it, ready for throw_ref. |
2073 | | d_m3Op(CatchPayload) |
2074 | 853k | { |
2075 | 853k | IM3Runtime runtime = m3MemRuntime(_mem); |
2076 | 853k | M3Exception* exception = runtime->pendingException; |
2077 | | |
2078 | 853k | u32 numArgs = immediate(u32); |
2079 | | |
2080 | 853k | for (u32 i = 0; i < numArgs; ++i) { |
2081 | 0 | i32 offset = immediate(i32); |
2082 | 0 | u32 is64 = immediate(u32); |
2083 | 0 | u64 value = exception->args[i]; |
2084 | |
|
2085 | 0 | if (is64) { |
2086 | 0 | *(u64*)(_sp + offset) = value; |
2087 | 0 | } else { |
2088 | 0 | *(u32*)(_sp + offset) = (u32)value; |
2089 | 0 | } |
2090 | 0 | } |
2091 | | |
2092 | 853k | i32 refOffset = immediate(i32); |
2093 | | |
2094 | 853k | if (refOffset >= 0) { |
2095 | 0 | *(M3Exception**)(_sp + refOffset) = exception; |
2096 | 0 | exception->reified = true; |
2097 | 853k | } else if (not exception->reified) { |
2098 | 853k | FreeException(runtime, exception); |
2099 | 853k | } |
2100 | | |
2101 | 853k | nextOp(); |
2102 | 853k | } |
2103 | | |
2104 | | |
2105 | | d_m3Op(Throw) |
2106 | 853k | { |
2107 | 853k | IM3Runtime runtime = m3MemRuntime(_mem); |
2108 | | |
2109 | 853k | IM3Tag tag = immediate(IM3Tag); |
2110 | 853k | u32 numArgs = immediate(u32); |
2111 | | |
2112 | 853k | M3Exception* exception = NewException(runtime, tag, numArgs); |
2113 | | |
2114 | 853k | if (M3_UNLIKELY(not exception)) { |
2115 | 0 | newTrap(m3Err_mallocFailed); |
2116 | 0 | } |
2117 | | |
2118 | 853k | for (u32 i = 0; i < numArgs; ++i) { |
2119 | 1 | i32 offset = immediate(i32); |
2120 | 1 | u32 is64 = immediate(u32); |
2121 | | |
2122 | 1 | exception->args[i] = is64 ? *(u64*)(_sp + offset) : *(u32*)(_sp + offset); |
2123 | 1 | } |
2124 | | |
2125 | 853k | runtime->pendingException = exception; |
2126 | | |
2127 | 853k | return m3Err_pendingException; |
2128 | 853k | } |
2129 | | |
2130 | | |
2131 | | d_m3Op(ThrowRef) |
2132 | 13 | { |
2133 | 13 | M3Exception* exception = slot(M3Exception*); |
2134 | | |
2135 | 13 | if (M3_UNLIKELY(not exception)) { |
2136 | 13 | newTrap(m3Err_trapNullReference); |
2137 | 13 | } |
2138 | | |
2139 | 0 | m3MemRuntime(_mem)->pendingException = exception; |
2140 | |
|
2141 | 0 | return m3Err_pendingException; |
2142 | 13 | } |
2143 | | |
2144 | | |
2145 | | // Emitted where control leaves a try region without leaving op_TryTable's native |
2146 | | // frame: falling out of the block's end, or branching past it. The count is how |
2147 | | // many try regions the exit crosses. |
2148 | | d_m3Op(PopHandlers) |
2149 | 1.37M | { |
2150 | 1.37M | IM3Runtime runtime = m3MemRuntime(_mem); |
2151 | | |
2152 | 1.37M | u32 count = immediate(u32); |
2153 | | |
2154 | 1.37M | runtime->tryDepth -= count; |
2155 | | |
2156 | 1.37M | nextOp(); |
2157 | 1.37M | } |
2158 | | |
2159 | | #endif // d_m3HasExceptionHandling |
2160 | | |
2161 | | #if d_m3HasStackSwitching |
2162 | | |
2163 | | d_m3Op(ContNew) |
2164 | 0 | { |
2165 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
2166 | 0 | IM3FuncType funcType = immediate(IM3FuncType); |
2167 | 0 | i32 dstSlot = immediate(i32); |
2168 | 0 | i32 funcSlot = immediate(i32); |
2169 | |
|
2170 | 0 | IM3Function func = *(IM3Function*)(_sp + funcSlot); |
2171 | 0 | if (M3_UNLIKELY(not func)) { |
2172 | 0 | newTrap(m3Err_trapNullFunctionRef); |
2173 | 0 | } |
2174 | | |
2175 | | // refused before a record exists, so a trap here leaves nothing behind |
2176 | 0 | if (M3_UNLIKELY(not Continuation_CanAcquireStack(runtime))) { |
2177 | 0 | newTrap(m3Err_continuationLimitExceeded); |
2178 | 0 | } |
2179 | 0 | IM3Continuation cont = Continuation_New(runtime, funcType, func); |
2180 | 0 | if (M3_UNLIKELY(not cont)) { |
2181 | 0 | newTrap(m3Err_mallocFailed); |
2182 | 0 | } |
2183 | | |
2184 | 0 | M3Result allocation = Continuation_AcquireStack(runtime, cont); |
2185 | 0 | if (M3_UNLIKELY(allocation)) { |
2186 | 0 | cont->state = cont_consumed; |
2187 | 0 | newTrap(allocation); |
2188 | 0 | } |
2189 | 0 | *(IM3Continuation*)(_sp + dstSlot) = cont; |
2190 | 0 | nextOp(); |
2191 | 0 | } |
2192 | | |
2193 | | |
2194 | | static |
2195 | | IM3Continuation InnermostSuspended (IM3Continuation i_cont); |
2196 | | |
2197 | | d_m3Op(ContBind) |
2198 | 0 | { |
2199 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
2200 | 0 | IM3FuncType ct1 = immediate(IM3FuncType); |
2201 | 0 | IM3FuncType ct2 = immediate(IM3FuncType); |
2202 | 0 | i32 dstSlot = immediate(i32); |
2203 | 0 | i32 contSlot = immediate(i32); |
2204 | 0 | u32 numBound = immediate(u32); |
2205 | |
|
2206 | 0 | IM3Continuation srcCont = *(IM3Continuation*)(_sp + contSlot); |
2207 | 0 | if (M3_UNLIKELY(not srcCont)) { |
2208 | 0 | newTrap(m3Err_trapNullContinuationRef); |
2209 | 0 | } |
2210 | 0 | if (M3_UNLIKELY(srcCont->state == cont_consumed || srcCont->state == cont_running)) { |
2211 | 0 | newTrap(m3Err_trapContinuationConsumed); |
2212 | 0 | } |
2213 | | |
2214 | 0 | IM3Continuation dstCont = Continuation_New(runtime, ct2, srcCont->entryFunction); |
2215 | 0 | if (M3_UNLIKELY(not dstCont)) { |
2216 | 0 | newTrap(m3Err_mallocFailed); |
2217 | 0 | } |
2218 | | |
2219 | | // the bound continuation takes over the original's execution state whole, |
2220 | | // recorded native frames included: binding a suspended continuation must |
2221 | | // not cost it the frames it has to be resumed through |
2222 | 0 | dstCont->entryFunction = srcCont->entryFunction; |
2223 | 0 | dstCont->valStack = srcCont->valStack; |
2224 | 0 | dstCont->numStackSlots = srcCont->numStackSlots; |
2225 | 0 | dstCont->frames = srcCont->frames; |
2226 | 0 | dstCont->framesCap = srcCont->framesCap; |
2227 | 0 | dstCont->numFrames = srcCont->numFrames; |
2228 | 0 | dstCont->sp = srcCont->sp; |
2229 | 0 | dstCont->pc = srcCont->pc; |
2230 | 0 | dstCont->suspendPoint = srcCont->suspendPoint; |
2231 | 0 | dstCont->r0 = srcCont->r0; |
2232 | 0 | # if d_m3HasFloat |
2233 | 0 | dstCont->fp0 = srcCont->fp0; |
2234 | 0 | # endif |
2235 | 0 | dstCont->boundArgsCount = srcCont->boundArgsCount; |
2236 | 0 | dstCont->state = srcCont->state; |
2237 | 0 | # if d_m3HasExceptionHandling |
2238 | 0 | dstCont->resumeThrow = srcCont->resumeThrow; |
2239 | 0 | srcCont->resumeThrow = NULL; |
2240 | 0 | # endif |
2241 | |
|
2242 | 0 | dstCont->numSuspendResults = srcCont->numSuspendResults; |
2243 | 0 | for (u32 j = 0; j < srcCont->numSuspendResults; ++j) { |
2244 | 0 | dstCont->suspendResultOffsets[j] = srcCont->suspendResultOffsets[j]; |
2245 | 0 | dstCont->suspendResultIs64[j] = srcCont->suspendResultIs64[j]; |
2246 | 0 | } |
2247 | |
|
2248 | 0 | if (dstCont->state == cont_allocated) { |
2249 | 0 | u16 numRets = ct1->contFuncType ? GetFuncTypeNumResults(ct1->contFuncType) : 0; |
2250 | 0 | for (u32 i = 0; i < numBound; ++i) { |
2251 | 0 | i32 argSlot = immediate(i32); |
2252 | 0 | u32 is64 = immediate(u32); |
2253 | 0 | u32 targetIdx = (numRets + dstCont->boundArgsCount) * c_ioSlotCount; |
2254 | 0 | if (is64) { |
2255 | 0 | *(u64*)(dstCont->valStack + targetIdx) = *(u64*)(_sp + argSlot); |
2256 | 0 | } else { |
2257 | 0 | *(u32*)(dstCont->valStack + targetIdx) = *(u32*)(_sp + argSlot); |
2258 | 0 | } |
2259 | 0 | dstCont->boundArgsCount++; |
2260 | 0 | } |
2261 | 0 | } else { |
2262 | 0 | IM3Continuation inner = InnermostSuspended(dstCont); |
2263 | 0 | for (u32 i = 0; i < numBound; ++i) { |
2264 | 0 | i32 argSlot = immediate(i32); |
2265 | 0 | u32 is64 = immediate(u32); |
2266 | 0 | u32 dstIdx = dstCont->boundArgsCount; |
2267 | 0 | if (dstIdx < inner->numSuspendResults) { |
2268 | 0 | i32 dstOffset = inner->suspendResultOffsets[dstIdx]; |
2269 | 0 | if (is64) { |
2270 | 0 | *(u64*)(inner->sp + dstOffset) = *(u64*)(_sp + argSlot); |
2271 | 0 | } else { |
2272 | 0 | *(u32*)(inner->sp + dstOffset) = *(u32*)(_sp + argSlot); |
2273 | 0 | } |
2274 | 0 | } |
2275 | 0 | dstCont->boundArgsCount++; |
2276 | 0 | } |
2277 | 0 | } |
2278 | |
|
2279 | 0 | srcCont->valStack = NULL; |
2280 | 0 | srcCont->frames = NULL; |
2281 | 0 | srcCont->framesCap = 0; |
2282 | 0 | srcCont->numFrames = 0; |
2283 | 0 | srcCont->state = cont_consumed; |
2284 | |
|
2285 | 0 | *(IM3Continuation*)(_sp + dstSlot) = dstCont; |
2286 | 0 | nextOp(); |
2287 | 0 | } |
2288 | | |
2289 | | |
2290 | | // Finds the resume whose handler answers this tag, walking out through the |
2291 | | // continuations that resumed us. i_kind picks which sort of handler counts - |
2292 | | // 0 for (on $e $l), 1 for (on $e switch). The spec is explicit that the search |
2293 | | // walks past a handler of the wrong sort even when the tag matches, so the |
2294 | | // kind is part of the match rather than something checked afterwards. |
2295 | | static |
2296 | | IM3Continuation FindHandler (IM3Continuation i_cont, IM3Tag i_tag, u8 i_kind, pc_t* o_stubPC) |
2297 | 0 | { |
2298 | 0 | IM3Tag queryTag = (i_tag and i_tag->resolved) ? i_tag->resolved : i_tag; |
2299 | |
|
2300 | 0 | for (IM3Continuation cont = i_cont; cont; cont = cont->parent) { |
2301 | 0 | for (u32 h = 0; h < cont->numHandlers; ++h) { |
2302 | 0 | pc_t entry = cont->handlersPC + (h * 3); |
2303 | 0 | IM3Tag handlerTag = (IM3Tag)(*(entry + 1)); |
2304 | 0 | if (handlerTag and handlerTag->resolved) { |
2305 | 0 | handlerTag = handlerTag->resolved; |
2306 | 0 | } |
2307 | |
|
2308 | 0 | if ((u32)(uintptr_t)(*entry) == i_kind and handlerTag == queryTag) { |
2309 | 0 | if (o_stubPC) { |
2310 | 0 | *o_stubPC = (pc_t)(*(entry + 2)); |
2311 | 0 | } |
2312 | 0 | return cont; |
2313 | 0 | } |
2314 | 0 | } |
2315 | 0 | } |
2316 | | |
2317 | 0 | return NULL; |
2318 | 0 | } |
2319 | | |
2320 | | |
2321 | | // Nulls the slots a suspend or switch leaves waiting for whatever resumes it. |
2322 | | // Until something writes them they are part of the suspended frame holding |
2323 | | // nothing, and a snapshot taken meanwhile reads each one as the type it will |
2324 | | // have: a reference there has to be null rather than whatever the slot held. |
2325 | | static |
2326 | | void ClearSuspendResults (IM3Continuation io_cont, m3stack_t i_sp) |
2327 | 0 | { |
2328 | 0 | for (u32 i = 0; i < io_cont->numSuspendResults; ++i) { |
2329 | 0 | if (io_cont->suspendResultIs64[i]) { |
2330 | 0 | *(u64*)(i_sp + io_cont->suspendResultOffsets[i]) = 0; |
2331 | 0 | } else { |
2332 | 0 | *(m3slot_t*)(i_sp + io_cont->suspendResultOffsets[i]) = 0; |
2333 | 0 | } |
2334 | 0 | } |
2335 | 0 | } |
2336 | | |
2337 | | |
2338 | | d_m3Op(Suspend) |
2339 | 6 | { |
2340 | 6 | IM3Runtime runtime = m3MemRuntime(_mem); |
2341 | 6 | IM3Continuation cont = runtime->activeContinuation; |
2342 | 6 | if (M3_UNLIKELY(not cont)) { |
2343 | 6 | newTrap(m3Err_trapUnhandledControlTag); |
2344 | 6 | } |
2345 | | |
2346 | 0 | IM3Tag tag = immediate(IM3Tag); |
2347 | 0 | u32 numParams = immediate(u32); |
2348 | |
|
2349 | 0 | runtime->numSuspendPayload = numParams; |
2350 | 0 | for (u32 i = 0; i < numParams; ++i) { |
2351 | 0 | i32 paramSlot = immediate(i32); |
2352 | 0 | u32 is64 = immediate(u32); |
2353 | 0 | if (is64) { |
2354 | 0 | runtime->suspendPayload[i] = *(u64*)(_sp + paramSlot); |
2355 | 0 | } else { |
2356 | 0 | runtime->suspendPayload[i] = (u64) * (u32*)(_sp + paramSlot); |
2357 | 0 | } |
2358 | 0 | runtime->suspendPayloadIs64[i] = is64; |
2359 | 0 | } |
2360 | |
|
2361 | 0 | u32 numResults = immediate(u32); |
2362 | 0 | cont->numSuspendResults = numResults; |
2363 | 0 | for (u32 i = 0; i < numResults; ++i) { |
2364 | 0 | cont->suspendResultOffsets[i] = immediate(i32); |
2365 | 0 | cont->suspendResultIs64[i] = immediate(u32); |
2366 | 0 | } |
2367 | |
|
2368 | 0 | ClearSuspendResults(cont, _sp); |
2369 | |
|
2370 | 0 | pc_t matchedStubPC = NULL; |
2371 | 0 | IM3Continuation searchCont = FindHandler(cont, tag, 0, &matchedStubPC); |
2372 | |
|
2373 | 0 | if (M3_UNLIKELY(not searchCont)) { |
2374 | 0 | newTrap(m3Err_trapUnhandledControlTag); |
2375 | 0 | } |
2376 | | |
2377 | 0 | runtime->suspendStubPC = matchedStubPC; |
2378 | 0 | runtime->suspendHandlerCont = searchCont; |
2379 | 0 | runtime->switchTarget = NULL; |
2380 | 0 | runtime->suspendTag = tag; |
2381 | |
|
2382 | 0 | cont->pc = _pc; |
2383 | 0 | cont->suspendPoint = safepoint_suspend; |
2384 | 0 | cont->sp = _sp; |
2385 | 0 | cont->r0 = _r0; |
2386 | 0 | # if d_m3HasFloat |
2387 | 0 | cont->fp0 = _fp0; |
2388 | 0 | # endif |
2389 | 0 | cont->boundArgsCount = 0; |
2390 | |
|
2391 | 0 | return m3Err_continuationSuspended; |
2392 | 0 | } |
2393 | | |
2394 | | |
2395 | | // ReplayFrames and RunUnderHandlers call each other: a captured resume is a |
2396 | | // frame like any other, and what it stands back up is a continuation with |
2397 | | // frames of its own. |
2398 | | static |
2399 | | m3ret_t RunUnderHandlers (IM3Runtime i_runtime, IM3Continuation* io_cont, |
2400 | | pc_t i_handlersPC, u32 i_numHandlers, M3MemoryHeader** io_mem); |
2401 | | static |
2402 | | void TakeContinuationResults (IM3Continuation i_cont, m3stack_t i_sp, |
2403 | | pc_t i_resultsPC, u32 i_numResults); |
2404 | | static |
2405 | | m3ret_t ResumePastCheck (IM3Continuation i_cont, M3MemoryHeader* _mem); |
2406 | | |
2407 | | // Whether the suspension point a replay has come down to is resumed past its |
2408 | | // check. Only the first one reached answers to m3_ResumeRuntime's request: that |
2409 | | // is the one the runtime paused at, and whatever it is, the request is spent. |
2410 | | static inline |
2411 | | bool ResumesPastCheck (IM3Runtime io_runtime, IM3Continuation i_cont) |
2412 | 0 | { |
2413 | 0 | bool pass = io_runtime->resumePastCheck; |
2414 | |
|
2415 | 0 | io_runtime->resumePastCheck = false; |
2416 | |
|
2417 | 0 | return pass and (i_cont->suspendPoint == safepoint_op or i_cont->suspendPoint == safepoint_entry); |
2418 | 0 | } |
2419 | | |
2420 | | |
2421 | | // Rebuilds the native frames the suspend unwound through and lands on the |
2422 | | // suspension point at the bottom of them. |
2423 | | // |
2424 | | // Frames were recorded innermost first, which is the order the unwind met |
2425 | | // them, so this walks down from the outermost and recurses toward the |
2426 | | // suspension point: by the time anything runs again, the native stack looks |
2427 | | // the way it did when the suspend left. |
2428 | | // |
2429 | | // Each case has to stand in for one operation completely - claim the frame it |
2430 | | // claimed, and answer the return value the way it would - including recording |
2431 | | // itself again, because the continuation is free to suspend a second time from |
2432 | | // inside the chain being rebuilt here. That second suspend refills frames[] |
2433 | | // from index 0 while this walk is still in it, which is why every level takes |
2434 | | // its own copy of the frame on the way down, before anything can run. |
2435 | | static |
2436 | | m3ret_t ReplayFrames (IM3Continuation i_cont, i32 i_depth, M3MemoryHeader* _mem) |
2437 | 0 | { |
2438 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
2439 | 0 | m3ret_t r = m3Err_none; |
2440 | |
|
2441 | 0 | # if d_m3MaxNativeStack > 0 |
2442 | 0 | { |
2443 | 0 | void* limit = runtime->stackLimit; |
2444 | |
|
2445 | 0 | if (M3_UNLIKELY(limit and m3_NativeStackPtr() < limit)) { |
2446 | 0 | return m3Err_trapStackOverflow; |
2447 | 0 | } |
2448 | 0 | } |
2449 | 0 | # endif |
2450 | | |
2451 | 0 | if (i_depth < 0) { |
2452 | 0 | bool pastCheck = ResumesPastCheck(runtime, i_cont); |
2453 | |
|
2454 | 0 | # if d_m3HasExceptionHandling |
2455 | | // resume_throw stops here: rather than carrying on from the suspension |
2456 | | // point, the exception is raised at it and travels back out through the |
2457 | | // try regions this walk has just rebuilt above |
2458 | 0 | if (M3_UNLIKELY(i_cont->resumeThrow)) { |
2459 | 0 | runtime->pendingException = i_cont->resumeThrow; |
2460 | 0 | i_cont->resumeThrow = NULL; |
2461 | |
|
2462 | 0 | return m3Err_pendingException; |
2463 | 0 | } |
2464 | 0 | # endif |
2465 | 0 | if (pastCheck) { |
2466 | 0 | return ResumePastCheck(i_cont, _mem); |
2467 | 0 | } |
2468 | | |
2469 | 0 | return d_m3CallWithRegs(i_cont->pc, i_cont->sp, _mem, i_cont->r0, i_cont->fp0); |
2470 | 0 | } |
2471 | | |
2472 | 0 | M3Frame frame = i_cont->frames[i_depth]; |
2473 | | |
2474 | | // frame_try brackets the recursion with its own bookkeeping, and |
2475 | | // frame_resume descends into another continuation entirely, so neither |
2476 | | // shares this one |
2477 | 0 | bool ownDescent = ((M3FrameKind)frame.kind == frame_resume); |
2478 | |
|
2479 | 0 | # if d_m3HasExceptionHandling |
2480 | 0 | ownDescent = ownDescent or ((M3FrameKind)frame.kind == frame_try); |
2481 | 0 | # endif |
2482 | |
|
2483 | 0 | if (not ownDescent) { |
2484 | 0 | r = ReplayFrames(i_cont, i_depth - 1, _mem); |
2485 | 0 | _mem = frame.memory->mallocated; |
2486 | 0 | } |
2487 | |
|
2488 | 0 | switch ((M3FrameKind)frame.kind) { |
2489 | 0 | case frame_call: |
2490 | 0 | if (M3_LIKELY(not r)) { |
2491 | | // the callee returned: carry on in the caller, with the registers |
2492 | | // op_Call's own frame had been holding across the call |
2493 | 0 | return d_m3CallWithRegs(frame.pc, frame.sp, _mem, frame.call.r0, frame.call.fp0); |
2494 | 0 | } |
2495 | | |
2496 | 0 | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2497 | 0 | return Continuation_RecordFrame(runtime, &frame); |
2498 | 0 | } |
2499 | | # if d_m3RecordBacktraces |
2500 | | PushBacktraceFrame(runtime, frame.pc - 1); |
2501 | | # endif |
2502 | 0 | return r; |
2503 | | |
2504 | 0 | case frame_loop: { |
2505 | 0 | m3stack_t _sp = frame.sp; |
2506 | 0 | m3reg_t _r0 = 0; |
2507 | 0 | # if d_m3HasFloat |
2508 | 0 | f64 _fp0 = 0.; |
2509 | 0 | # endif |
2510 | | // op_Loop's protocol: the body hands its own pc back to ask for |
2511 | | // another lap. Dispatched the way op_Loop dispatches it, so a yield |
2512 | | // hook sees the same back edges it always did. |
2513 | 0 | while (r == (m3ret_t)frame.pc) { |
2514 | 0 | r = jumpOpImpl(frame.pc); |
2515 | 0 | _mem = frame.memory->mallocated; |
2516 | 0 | } |
2517 | |
|
2518 | 0 | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2519 | 0 | return Continuation_RecordFrame(runtime, &frame); |
2520 | 0 | } |
2521 | 0 | return r; |
2522 | 0 | } |
2523 | | |
2524 | 0 | # if d_m3HasExceptionHandling |
2525 | 0 | case frame_try: { |
2526 | 0 | m3stack_t _sp = frame.sp; |
2527 | 0 | m3reg_t _r0 = 0; |
2528 | 0 | # if d_m3HasFloat |
2529 | 0 | f64 _fp0 = 0.; |
2530 | 0 | # endif |
2531 | 0 | (void)_sp; |
2532 | 0 | (void)_r0; |
2533 | 0 | # if d_m3HasFloat |
2534 | 0 | (void)_fp0; |
2535 | 0 | # endif |
2536 | | |
2537 | | // this try region is standing again, so it counts towards the depth |
2538 | | // once more - unless op_PopHandlers had already retired it before the |
2539 | | // suspend, in which case it is only here to be walked past |
2540 | 0 | u32 depth = ++runtime->tryDepth; |
2541 | |
|
2542 | 0 | if (not frame.try_.handlersLive) { |
2543 | 0 | runtime->tryDepth = depth - 1; |
2544 | 0 | } |
2545 | |
|
2546 | 0 | r = ReplayFrames(i_cont, i_depth - 1, _mem); |
2547 | 0 | _mem = frame.memory->mallocated; |
2548 | |
|
2549 | 0 | bool isInnermost = (runtime->tryDepth == depth); |
2550 | 0 | runtime->tryDepth = depth - 1; |
2551 | |
|
2552 | 0 | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2553 | 0 | frame.try_.handlersLive = isInnermost; |
2554 | 0 | return Continuation_RecordFrame(runtime, &frame); |
2555 | 0 | } |
2556 | | |
2557 | 0 | if (M3_UNLIKELY(r == m3Err_pendingException) and isInnermost) { |
2558 | 0 | const M3Exception* exception = runtime->pendingException; |
2559 | |
|
2560 | 0 | for (u32 i = 0; i < frame.try_.numClauses; ++i) { |
2561 | 0 | IM3Tag tag = (IM3Tag)frame.pc[2 * i]; |
2562 | |
|
2563 | 0 | if (tag == NULL or tag == exception->tag) { |
2564 | 0 | pc_t handler = (pc_t)frame.pc[2 * i + 1]; |
2565 | |
|
2566 | 0 | d_m3ClearRegisters |
2567 | | |
2568 | | // op_TryTable hands its frame to the handler, but this is |
2569 | | // not an operation and cannot: the replay stands in for |
2570 | | // that frame, so it keeps it and passes the answer on. |
2571 | 0 | return jumpOpImpl(handler); |
2572 | 0 | } |
2573 | 0 | } |
2574 | 0 | } |
2575 | 0 | return r; |
2576 | 0 | } |
2577 | 0 | # endif |
2578 | | |
2579 | 0 | case frame_resume: { |
2580 | | // A resume that the suspend passed straight through. Standing it up |
2581 | | // again means running the continuation it had under it, under the same |
2582 | | // handlers - and that continuation carries the suspension point, so it |
2583 | | // is where the rest of the replay happens. |
2584 | 0 | IM3Continuation inner = frame.resume.cont; |
2585 | |
|
2586 | 0 | r = RunUnderHandlers(runtime, &inner, frame.resume.handlersPC, |
2587 | 0 | frame.resume.numHandlers, &_mem); |
2588 | |
|
2589 | 0 | if (r == m3Err_none) { |
2590 | 0 | inner->state = cont_consumed; |
2591 | |
|
2592 | 0 | TakeContinuationResults(inner, frame.sp, frame.resume.resultsPC, |
2593 | 0 | frame.resume.numResults); |
2594 | 0 | Continuation_RecycleStack(runtime, inner); |
2595 | |
|
2596 | 0 | return d_m3CallWithRegs(frame.pc, frame.sp, _mem, 0, 0.); |
2597 | 0 | } |
2598 | | |
2599 | 0 | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2600 | 0 | if (runtime->suspendHandlerCont != inner) { |
2601 | 0 | frame.resume.cont = inner; |
2602 | 0 | return Continuation_RecordFrame(runtime, &frame); |
2603 | 0 | } |
2604 | | |
2605 | 0 | IM3Continuation suspended = Continuation_ForkSuspended(runtime, inner); |
2606 | 0 | if (M3_UNLIKELY(not suspended)) { |
2607 | 0 | return m3Err_mallocFailed; |
2608 | 0 | } |
2609 | 0 | runtime->suspendedContinuation = suspended; |
2610 | 0 | if (runtime->suspendStubPC) { |
2611 | 0 | return d_m3CallWithRegs(runtime->suspendStubPC, frame.sp, _mem, 0, 0.); |
2612 | 0 | } else { |
2613 | 0 | return m3Err_trapUnhandledControlTag; |
2614 | 0 | } |
2615 | 0 | } else { |
2616 | 0 | inner->state = cont_consumed; |
2617 | 0 | Continuation_RecycleStack(runtime, inner); |
2618 | 0 | } |
2619 | | |
2620 | 0 | return r; |
2621 | 0 | } |
2622 | |
|
2623 | | # if d_m3EntryKeepsFrame |
2624 | | case frame_entry: |
2625 | | if (M3_UNLIKELY(r)) { |
2626 | | if (M3_UNLIKELY(r == m3Err_continuationSuspended)) { |
2627 | | return Continuation_RecordFrame(runtime, &frame); |
2628 | | } |
2629 | | # if d_m3RecordBacktraces |
2630 | | FillBacktraceFunctionInfo(runtime, frame.entry.function); |
2631 | | # else |
2632 | | (void)frame.entry.function; |
2633 | | # endif |
2634 | | } |
2635 | | return r; |
2636 | | # endif |
2637 | 0 | } |
2638 | | |
2639 | 0 | return r; |
2640 | 0 | } |
2641 | | |
2642 | | |
2643 | | // Where a continuation's i-th incoming value goes. A continuation that has not |
2644 | | // started yet takes them as the arguments of its entry frame, laid out above |
2645 | | // its return slots; one that is suspended takes them in the slots its own |
2646 | | // suspend or switch left waiting. |
2647 | | static |
2648 | | void* ContinuationArgDest (IM3Continuation i_cont, u32 i_index) |
2649 | 0 | { |
2650 | 0 | if (i_cont->state == cont_allocated) { |
2651 | 0 | IM3FuncType inner = i_cont->type ? i_cont->type->contFuncType : NULL; |
2652 | 0 | u16 numRets = inner ? GetFuncTypeNumResults(inner) : 0; |
2653 | |
|
2654 | 0 | return i_cont->valStack + (numRets + i_index) * c_ioSlotCount; |
2655 | 0 | } |
2656 | | |
2657 | 0 | if (i_index < i_cont->numSuspendResults) { |
2658 | 0 | return i_cont->sp + i_cont->suspendResultOffsets[i_index]; |
2659 | 0 | } |
2660 | | |
2661 | 0 | return NULL; |
2662 | 0 | } |
2663 | | |
2664 | | |
2665 | | // Hands a switch's payload to the peer, and after it the continuation that |
2666 | | // switched away - the reference that lets the peer come back this way. |
2667 | | static |
2668 | | void HandOverToPeer (IM3Runtime i_runtime, IM3Continuation io_peer, IM3Continuation i_from) |
2669 | 0 | { |
2670 | 0 | u32 numArgs = i_runtime->numSuspendPayload; |
2671 | 0 | u32 base = (io_peer->state == cont_allocated) ? io_peer->boundArgsCount : 0; |
2672 | |
|
2673 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
2674 | 0 | void* dest = ContinuationArgDest(io_peer, base + i); |
2675 | |
|
2676 | 0 | if (dest) { |
2677 | 0 | if (i_runtime->suspendPayloadIs64[i]) { |
2678 | 0 | *(u64*)dest = i_runtime->suspendPayload[i]; |
2679 | 0 | } else { |
2680 | 0 | *(u32*)dest = (u32)i_runtime->suspendPayload[i]; |
2681 | 0 | } |
2682 | 0 | } |
2683 | 0 | } |
2684 | |
|
2685 | 0 | void* refDest = ContinuationArgDest(io_peer, base + numArgs); |
2686 | |
|
2687 | 0 | if (refDest) { |
2688 | 0 | *(IM3Continuation*)refDest = i_from; |
2689 | 0 | } |
2690 | |
|
2691 | 0 | if (io_peer->state == cont_allocated) { |
2692 | 0 | io_peer->boundArgsCount += numArgs + 1; |
2693 | 0 | } |
2694 | 0 | } |
2695 | | |
2696 | | |
2697 | | // resume, resume_throw and resume_throw_ref. The three differ only in what the |
2698 | | // continuation is handed to start with, which is what the mode immediate says, |
2699 | | // so everything after that - the handler table, the switch loop, the results - |
2700 | | // is written once. |
2701 | | // The innermost continuation of a capture: the one whose suspension point is |
2702 | | // at the bottom of it, and so the one whose waiting slots any values handed to |
2703 | | // the capture belong in. A resume the suspend travelled through leaves its |
2704 | | // record at the foot of the frame list, which is the link to follow. |
2705 | | static |
2706 | | IM3Continuation InnermostSuspended (IM3Continuation i_cont) |
2707 | 0 | { |
2708 | 0 | while (i_cont->numFrames and (M3FrameKind) i_cont->frames[0].kind == frame_resume) { |
2709 | 0 | i_cont = i_cont->frames[0].resume.cont; |
2710 | 0 | } |
2711 | |
|
2712 | 0 | return i_cont; |
2713 | 0 | } |
2714 | | |
2715 | | |
2716 | | // Runs a continuation under one handler table until something comes back that |
2717 | | // is not a switch, and reports which continuation was running when it did: a |
2718 | | // switch under this table takes the place of the one that switched away, and |
2719 | | // whatever is running is what the handler table belongs to. |
2720 | | static |
2721 | | m3ret_t RunUnderHandlers (IM3Runtime i_runtime, IM3Continuation* io_cont, |
2722 | | pc_t i_handlersPC, u32 i_numHandlers, M3MemoryHeader** io_mem) |
2723 | 0 | { |
2724 | 0 | IM3Continuation cont = *io_cont; |
2725 | 0 | IM3Continuation parent = i_runtime->activeContinuation; |
2726 | 0 | IM3Memory memory = m3MemInfo(*io_mem); |
2727 | 0 | m3ret_t r; |
2728 | |
|
2729 | 0 | for (;;) { |
2730 | 0 | # if d_m3HasExceptionHandling |
2731 | | // aborting a continuation that never started: there is no suspension |
2732 | | // point to raise at, so the exception simply comes straight back out |
2733 | 0 | if (M3_UNLIKELY(cont->resumeThrow and cont->numFrames == 0)) { |
2734 | 0 | i_runtime->pendingException = cont->resumeThrow; |
2735 | 0 | cont->resumeThrow = NULL; |
2736 | 0 | cont->state = cont_consumed; |
2737 | 0 | r = m3Err_pendingException; |
2738 | 0 | break; |
2739 | 0 | } |
2740 | 0 | # endif |
2741 | 0 | bool isStarting = (cont->state == cont_allocated); |
2742 | |
|
2743 | 0 | if (isStarting) { |
2744 | 0 | if (M3_UNLIKELY(not cont->entryFunction->compiled)) { |
2745 | 0 | r = CompileFunction(cont->entryFunction); |
2746 | |
|
2747 | 0 | if (M3_UNLIKELY(r)) { |
2748 | 0 | break; |
2749 | 0 | } |
2750 | 0 | } |
2751 | 0 | cont->pc = cont->entryFunction->compiled; |
2752 | 0 | cont->sp = cont->valStack; |
2753 | 0 | cont->numFrames = 0; |
2754 | 0 | } |
2755 | | |
2756 | 0 | cont->handlersPC = i_handlersPC; |
2757 | 0 | cont->numHandlers = i_numHandlers; |
2758 | 0 | cont->parent = parent; |
2759 | 0 | cont->state = cont_running; |
2760 | 0 | cont->boundArgsCount = 0; |
2761 | |
|
2762 | 0 | i_runtime->activeContinuation = cont; |
2763 | |
|
2764 | 0 | if (cont->numFrames) { |
2765 | | // a suspended continuation: put back the native frames it unwound |
2766 | | // through before landing on the suspension point. The count is |
2767 | | // cleared first because a second suspend records into the same |
2768 | | // array, starting over at index 0. |
2769 | 0 | i32 outermost = (i32)cont->numFrames - 1; |
2770 | 0 | cont->numFrames = 0; |
2771 | |
|
2772 | 0 | r = ReplayFrames(cont, outermost, *io_mem); |
2773 | 0 | } else if (not isStarting and ResumesPastCheck(i_runtime, cont)) { |
2774 | 0 | r = ResumePastCheck(cont, *io_mem); |
2775 | 0 | } else { |
2776 | 0 | r = d_m3CallWithRegs(cont->pc, cont->sp, *io_mem, 0, 0.); |
2777 | 0 | } |
2778 | |
|
2779 | 0 | *io_mem = memory->mallocated; |
2780 | 0 | i_runtime->activeContinuation = parent; |
2781 | |
|
2782 | 0 | if (r != m3Err_continuationSuspended) { |
2783 | 0 | break; |
2784 | 0 | } |
2785 | | |
2786 | 0 | cont->state = cont_suspended; |
2787 | | |
2788 | | // not a switch, so it is a suspend and this is as far as we take it |
2789 | 0 | if (not i_runtime->switchTarget or i_runtime->suspendHandlerCont != cont) { |
2790 | 0 | break; |
2791 | 0 | } |
2792 | | |
2793 | 0 | IM3Continuation peer = i_runtime->switchTarget; |
2794 | 0 | i_runtime->switchTarget = NULL; |
2795 | |
|
2796 | 0 | IM3Continuation suspended = Continuation_ForkSuspended(i_runtime, cont); |
2797 | 0 | if (M3_UNLIKELY(not suspended)) { |
2798 | 0 | r = m3Err_mallocFailed; |
2799 | 0 | break; |
2800 | 0 | } |
2801 | 0 | IM3FuncType peerType = peer->type->contFuncType; |
2802 | 0 | suspended->type = Module_ContTypeOfRef(peer->entryFunction->module, |
2803 | 0 | GetFuncTypeParamType(peerType, (u16)(GetFuncTypeNumParams(peerType) - 1))); |
2804 | 0 | HandOverToPeer(i_runtime, peer, suspended); |
2805 | |
|
2806 | 0 | cont = peer; |
2807 | 0 | } |
2808 | |
|
2809 | 0 | *io_cont = cont; |
2810 | |
|
2811 | 0 | return r; |
2812 | 0 | } |
2813 | | |
2814 | | |
2815 | | // Copies what a finished continuation left in its return slots into the slots |
2816 | | // the resume site set aside for them. |
2817 | | static |
2818 | | void TakeContinuationResults (IM3Continuation i_cont, m3stack_t i_sp, pc_t i_resultsPC, u32 i_numResults) |
2819 | 0 | { |
2820 | 0 | for (u32 i = 0; i < i_numResults; ++i) { |
2821 | 0 | i32 resSlot = *(i32*)(i_resultsPC + 2 * i); |
2822 | 0 | u32 is64 = *(u32*)(i_resultsPC + 2 * i + 1); |
2823 | 0 | u32 srcIdx = i * c_ioSlotCount; |
2824 | |
|
2825 | 0 | if (is64) { |
2826 | 0 | *(u64*)(i_sp + resSlot) = *(u64*)(i_cont->valStack + srcIdx); |
2827 | 0 | } else { |
2828 | 0 | *(u32*)(i_sp + resSlot) = *(u32*)(i_cont->valStack + srcIdx); |
2829 | 0 | } |
2830 | 0 | } |
2831 | 0 | } |
2832 | | |
2833 | | |
2834 | | // resume, resume_throw and resume_throw_ref. The three differ only in what the |
2835 | | // continuation is handed to start with, which is what the mode immediate says, |
2836 | | // so everything after that - the handler table, the switch loop, the results - |
2837 | | // is written once. |
2838 | | d_m3Op(Resume) |
2839 | 0 | { |
2840 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
2841 | 0 | IM3FuncType contFuncType = immediate(IM3FuncType); |
2842 | 0 | i32 contSlot = immediate(i32); |
2843 | 0 | u32 mode = immediate(u32); |
2844 | |
|
2845 | 0 | IM3Continuation cont = *(IM3Continuation*)(_sp + contSlot); |
2846 | 0 | if (M3_UNLIKELY(not cont)) { |
2847 | 0 | newTrap(m3Err_trapNullContinuationRef); |
2848 | 0 | } |
2849 | 0 | if (M3_UNLIKELY(cont->state == cont_consumed or cont->state == cont_running)) { |
2850 | 0 | newTrap(m3Err_trapContinuationConsumed); |
2851 | 0 | } |
2852 | | |
2853 | 0 | IM3FuncType innerType = contFuncType->contFuncType ? contFuncType->contFuncType : contFuncType; |
2854 | 0 | u16 numRets = GetFuncTypeNumResults(innerType); |
2855 | |
|
2856 | 0 | if (mode == d_m3ResumeThrowRef) { |
2857 | 0 | i32 exnSlot = immediate(i32); |
2858 | |
|
2859 | 0 | # if d_m3HasExceptionHandling |
2860 | 0 | M3Exception* exception = *(M3Exception**)(_sp + exnSlot); |
2861 | |
|
2862 | 0 | if (M3_UNLIKELY(not exception)) { |
2863 | 0 | newTrap(m3Err_trapNullReference); |
2864 | 0 | } |
2865 | | |
2866 | 0 | InnermostSuspended(cont)->resumeThrow = exception; |
2867 | | # else |
2868 | | (void)exnSlot; |
2869 | | newTrap(m3Err_trapUnsupportedInstruction); |
2870 | | # endif |
2871 | 0 | } else if (mode == d_m3ResumeThrow) { |
2872 | 0 | IM3Tag exnTag = immediate(IM3Tag); |
2873 | 0 | u32 numArgs = immediate(u32); |
2874 | |
|
2875 | 0 | # if d_m3HasExceptionHandling |
2876 | 0 | M3Exception* exception = NewException(runtime, exnTag, numArgs); |
2877 | |
|
2878 | 0 | if (M3_UNLIKELY(not exception)) { |
2879 | 0 | newTrap(m3Err_mallocFailed); |
2880 | 0 | } |
2881 | | |
2882 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
2883 | 0 | i32 offset = immediate(i32); |
2884 | 0 | u32 is64 = immediate(u32); |
2885 | |
|
2886 | 0 | exception->args[i] = is64 ? *(u64*)(_sp + offset) : *(u32*)(_sp + offset); |
2887 | 0 | } |
2888 | |
|
2889 | 0 | InnermostSuspended(cont)->resumeThrow = exception; |
2890 | | # else |
2891 | | (void)exnTag; |
2892 | | (void)numArgs; |
2893 | | newTrap(m3Err_trapUnsupportedInstruction); |
2894 | | # endif |
2895 | 0 | } else { |
2896 | 0 | u32 numArgs = immediate(u32); |
2897 | |
|
2898 | 0 | if (cont->state == cont_allocated) { |
2899 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
2900 | 0 | i32 argSlot = immediate(i32); |
2901 | 0 | u32 is64 = immediate(u32); |
2902 | 0 | u32 targetIdx = (numRets + cont->boundArgsCount + i) * c_ioSlotCount; |
2903 | 0 | if (is64) { |
2904 | 0 | *(u64*)(cont->valStack + targetIdx) = *(u64*)(_sp + argSlot); |
2905 | 0 | } else { |
2906 | 0 | *(u32*)(cont->valStack + targetIdx) = *(u32*)(_sp + argSlot); |
2907 | 0 | } |
2908 | 0 | } |
2909 | 0 | cont->boundArgsCount = 0; |
2910 | 0 | } else { |
2911 | | // the waiting slots belong to whichever continuation holds the |
2912 | | // suspension point, which is not this one if a resume was captured |
2913 | | // along with it |
2914 | 0 | IM3Continuation inner = InnermostSuspended(cont); |
2915 | |
|
2916 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
2917 | 0 | i32 argSlot = immediate(i32); |
2918 | 0 | u32 is64 = immediate(u32); |
2919 | 0 | u32 dstIdx = cont->boundArgsCount + i; |
2920 | 0 | if (dstIdx < inner->numSuspendResults) { |
2921 | 0 | i32 dstOffset = inner->suspendResultOffsets[dstIdx]; |
2922 | 0 | if (is64) { |
2923 | 0 | *(u64*)(inner->sp + dstOffset) = *(u64*)(_sp + argSlot); |
2924 | 0 | } else { |
2925 | 0 | *(u32*)(inner->sp + dstOffset) = *(u32*)(_sp + argSlot); |
2926 | 0 | } |
2927 | 0 | } |
2928 | 0 | } |
2929 | 0 | } |
2930 | 0 | } |
2931 | | |
2932 | 0 | u32 numHandlers = immediate(u32); |
2933 | 0 | pc_t handlersPC = _pc; |
2934 | 0 | _pc += numHandlers * 3; |
2935 | |
|
2936 | 0 | u32 numResults = immediate(u32); |
2937 | 0 | pc_t resultsPC = _pc; |
2938 | |
|
2939 | 0 | IM3Memory memory = m3MemInfo(_mem); |
2940 | |
|
2941 | 0 | m3ret_t r = RunUnderHandlers(runtime, &cont, handlersPC, numHandlers, &_mem); |
2942 | |
|
2943 | 0 | if (r == m3Err_none) { |
2944 | 0 | cont->state = cont_consumed; |
2945 | |
|
2946 | 0 | TakeContinuationResults(cont, _sp, resultsPC, numResults); |
2947 | 0 | Continuation_RecycleStack(runtime, cont); |
2948 | |
|
2949 | 0 | _pc += numResults * 2; |
2950 | 0 | nextOp(); |
2951 | 0 | } else if (r == m3Err_continuationSuspended) { |
2952 | 0 | if (M3_UNLIKELY(runtime->suspendHandlerCont != cont)) { |
2953 | 0 | if (M3_UNLIKELY(not runtime->activeContinuation)) { |
2954 | 0 | newTrap(m3Err_trapUnhandledControlTag); |
2955 | 0 | } |
2956 | 0 | M3Frame frame; |
2957 | 0 | frame.kind = frame_resume; |
2958 | 0 | frame.pc = resultsPC + numResults * 2; |
2959 | 0 | frame.sp = _sp; |
2960 | 0 | frame.memory = memory; |
2961 | 0 | frame.resume.cont = cont; |
2962 | 0 | frame.resume.handlersPC = handlersPC; |
2963 | 0 | frame.resume.numHandlers = numHandlers; |
2964 | 0 | frame.resume.resultsPC = resultsPC; |
2965 | 0 | frame.resume.numResults = numResults; |
2966 | |
|
2967 | 0 | return Continuation_RecordFrame(runtime, &frame); |
2968 | 0 | } |
2969 | | |
2970 | 0 | IM3Continuation suspended = Continuation_ForkSuspended(runtime, cont); |
2971 | 0 | if (M3_UNLIKELY(not suspended)) { |
2972 | 0 | newTrap(m3Err_mallocFailed); |
2973 | 0 | } |
2974 | 0 | runtime->suspendedContinuation = suspended; |
2975 | |
|
2976 | 0 | if (runtime->suspendStubPC) { |
2977 | 0 | jumpOpDirect(runtime->suspendStubPC); |
2978 | 0 | } else { |
2979 | 0 | newTrap(m3Err_trapUnhandledControlTag); |
2980 | 0 | } |
2981 | 0 | } else { |
2982 | 0 | cont->state = cont_consumed; |
2983 | 0 | Continuation_RecycleStack(runtime, cont); |
2984 | 0 | pushBacktraceFrame(); |
2985 | 0 | forwardTrap(r); |
2986 | 0 | } |
2987 | 0 | } |
2988 | | |
2989 | | |
2990 | | d_m3Op(ResumePayload) |
2991 | 0 | { |
2992 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
2993 | | |
2994 | | // The payload comes from the suspend; the reference is to the whole of what |
2995 | | // was captured, which is not the same continuation once the suspend has |
2996 | | // travelled out through a resume that had nothing to say about its tag. |
2997 | 0 | IM3Continuation cont = runtime->suspendedContinuation; |
2998 | 0 | cont->type = immediate(IM3FuncType); |
2999 | |
|
3000 | 0 | u32 numArgs = immediate(u32); |
3001 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
3002 | 0 | i32 offset = immediate(i32); |
3003 | 0 | u32 is64 = immediate(u32); |
3004 | 0 | u64 val = (i < runtime->numSuspendPayload) ? runtime->suspendPayload[i] : 0; |
3005 | 0 | if (is64) { |
3006 | 0 | *(u64*)(_sp + offset) = val; |
3007 | 0 | } else { |
3008 | 0 | *(u32*)(_sp + offset) = (u32)val; |
3009 | 0 | } |
3010 | 0 | } |
3011 | |
|
3012 | 0 | i32 contOffset = immediate(i32); |
3013 | 0 | if (contOffset >= 0) { |
3014 | 0 | *(IM3Continuation*)(_sp + contOffset) = cont; |
3015 | 0 | } |
3016 | |
|
3017 | 0 | nextOp(); |
3018 | 0 | } |
3019 | | |
3020 | | |
3021 | | // switch is a suspend that names its own replacement. Rather than run the |
3022 | | // peer here - which would leave this native frame owning a continuation it is |
3023 | | // no longer running - it suspends the current continuation the ordinary way and |
3024 | | // hands the peer to the resume that installed the matching (on $e switch) |
3025 | | // handler. That resume is the delimiter the proposal asks for, and it is the |
3026 | | // frame that should be tracking whatever is running under it. |
3027 | | d_m3Op(Switch) |
3028 | 0 | { |
3029 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
3030 | 0 | IM3Continuation cont = runtime->activeContinuation; |
3031 | |
|
3032 | 0 | if (M3_UNLIKELY(not cont)) { |
3033 | 0 | newTrap(m3Err_trapUnhandledControlTag); |
3034 | 0 | } |
3035 | | |
3036 | 0 | skip_immediate(IM3FuncType); |
3037 | |
|
3038 | 0 | IM3Tag tag = immediate(IM3Tag); |
3039 | 0 | i32 targetSlot = immediate(i32); |
3040 | |
|
3041 | 0 | IM3Continuation target = *(IM3Continuation*)(_sp + targetSlot); |
3042 | |
|
3043 | 0 | if (M3_UNLIKELY(not target)) { |
3044 | 0 | newTrap(m3Err_trapNullContinuationRef); |
3045 | 0 | } |
3046 | 0 | if (M3_UNLIKELY(target->state == cont_consumed or target->state == cont_running)) { |
3047 | 0 | newTrap(m3Err_trapContinuationConsumed); |
3048 | 0 | } |
3049 | | |
3050 | 0 | IM3Continuation handlerCont = FindHandler(cont, tag, 1, NULL); |
3051 | |
|
3052 | 0 | if (M3_UNLIKELY(not handlerCont)) { |
3053 | 0 | newTrap(m3Err_trapUnhandledControlTag); |
3054 | 0 | } |
3055 | | |
3056 | | // the peer's arguments, and after them the room for the continuation |
3057 | | // reference the resume will write once this one is safely suspended |
3058 | 0 | u32 numArgs = immediate(u32); |
3059 | |
|
3060 | 0 | runtime->numSuspendPayload = numArgs; |
3061 | |
|
3062 | 0 | for (u32 i = 0; i < numArgs; ++i) { |
3063 | 0 | i32 argSlot = immediate(i32); |
3064 | 0 | u32 is64 = immediate(u32); |
3065 | |
|
3066 | 0 | runtime->suspendPayload[i] = is64 ? *(u64*)(_sp + argSlot) : (u64) * (u32*)(_sp + argSlot); |
3067 | 0 | runtime->suspendPayloadIs64[i] = is64; |
3068 | 0 | } |
3069 | | |
3070 | | // where the values come back to, when something switches into this one |
3071 | 0 | u32 numResults = immediate(u32); |
3072 | |
|
3073 | 0 | cont->numSuspendResults = numResults; |
3074 | |
|
3075 | 0 | for (u32 i = 0; i < numResults; ++i) { |
3076 | 0 | cont->suspendResultOffsets[i] = immediate(i32); |
3077 | 0 | cont->suspendResultIs64[i] = immediate(u32); |
3078 | 0 | } |
3079 | |
|
3080 | 0 | ClearSuspendResults(cont, _sp); |
3081 | |
|
3082 | 0 | runtime->suspendStubPC = NULL; |
3083 | 0 | runtime->suspendHandlerCont = handlerCont; |
3084 | 0 | runtime->switchTarget = target; |
3085 | 0 | runtime->suspendTag = tag; |
3086 | |
|
3087 | 0 | cont->pc = _pc; |
3088 | 0 | cont->suspendPoint = safepoint_suspend; |
3089 | 0 | cont->sp = _sp; |
3090 | 0 | cont->r0 = _r0; |
3091 | 0 | # if d_m3HasFloat |
3092 | 0 | cont->fp0 = _fp0; |
3093 | 0 | # endif |
3094 | |
|
3095 | 0 | return m3Err_continuationSuspended; |
3096 | 0 | } |
3097 | | |
3098 | | |
3099 | | #endif // d_m3HasStackSwitching |
3100 | | |
3101 | | |
3102 | | d_m3Op(Branch) |
3103 | 1.43M | { |
3104 | 1.43M | jumpOp(*_pc); |
3105 | 1.43M | } |
3106 | | |
3107 | | |
3108 | | d_m3Op(If_r) |
3109 | 8.85M | { |
3110 | 8.85M | i32 condition = (i32)_r0; |
3111 | | |
3112 | 8.85M | pc_t elsePC = immediate(pc_t); |
3113 | | |
3114 | 8.85M | if (condition) { |
3115 | 5.78M | nextOp(); |
3116 | 5.78M | } else { |
3117 | 3.07M | jumpOp(elsePC); |
3118 | 3.07M | } |
3119 | 8.85M | } |
3120 | | |
3121 | | |
3122 | | d_m3Op(If_s) |
3123 | 9.99M | { |
3124 | 9.99M | i32 condition = slot(i32); |
3125 | | |
3126 | 9.99M | pc_t elsePC = immediate(pc_t); |
3127 | | |
3128 | 9.99M | if (condition) { |
3129 | 9.38M | nextOp(); |
3130 | 9.38M | } else { |
3131 | 604k | jumpOp(elsePC); |
3132 | 604k | } |
3133 | 9.99M | } |
3134 | | |
3135 | | |
3136 | | d_m3Op(BranchTable) |
3137 | 344k | { |
3138 | 344k | u32 branchIndex = slot(u32); // branch index is always in a slot |
3139 | 344k | u32 numTargets = immediate(u32); |
3140 | | |
3141 | 344k | pc_t* branches = (pc_t*)_pc; |
3142 | | |
3143 | 344k | if (branchIndex > numTargets) { |
3144 | 224k | branchIndex = numTargets; // the default index |
3145 | 224k | } |
3146 | | |
3147 | 344k | jumpOp(branches[branchIndex]); |
3148 | 344k | } |
3149 | | |
3150 | | |
3151 | | #define d_m3SetRegisterSetSlot(TYPE, REG) \ |
3152 | 2.33M | d_m3Op (SetRegister_##TYPE) \ |
3153 | 2.33M | { \ |
3154 | 2.33M | TYPE * src = slot_ptr (TYPE); \ |
3155 | 2.33M | d_m3PreloadNext (); \ |
3156 | 2.33M | REG = * src; \ |
3157 | 2.33M | nextOpPreloaded (); \ |
3158 | 2.33M | } \ m3_compile.c:op_SetRegister_i32 Line | Count | Source | 3152 | 1.58M | d_m3Op (SetRegister_##TYPE) \ | 3153 | 1.58M | { \ | 3154 | 1.58M | TYPE * src = slot_ptr (TYPE); \ | 3155 | 1.58M | d_m3PreloadNext (); \ | 3156 | 1.58M | REG = * src; \ | 3157 | 1.58M | nextOpPreloaded (); \ | 3158 | 1.58M | } \ |
m3_compile.c:op_SetRegister_i64 Line | Count | Source | 3152 | 677k | d_m3Op (SetRegister_##TYPE) \ | 3153 | 677k | { \ | 3154 | 677k | TYPE * src = slot_ptr (TYPE); \ | 3155 | 677k | d_m3PreloadNext (); \ | 3156 | 677k | REG = * src; \ | 3157 | 677k | nextOpPreloaded (); \ | 3158 | 677k | } \ |
m3_compile.c:op_SetRegister_f32 Line | Count | Source | 3152 | 70.5k | d_m3Op (SetRegister_##TYPE) \ | 3153 | 70.5k | { \ | 3154 | 70.5k | TYPE * src = slot_ptr (TYPE); \ | 3155 | 70.5k | d_m3PreloadNext (); \ | 3156 | 70.5k | REG = * src; \ | 3157 | 70.5k | nextOpPreloaded (); \ | 3158 | 70.5k | } \ |
m3_compile.c:op_SetRegister_f64 Line | Count | Source | 3152 | 401 | d_m3Op (SetRegister_##TYPE) \ | 3153 | 401 | { \ | 3154 | 401 | TYPE * src = slot_ptr (TYPE); \ | 3155 | 401 | d_m3PreloadNext (); \ | 3156 | 401 | REG = * src; \ | 3157 | 401 | nextOpPreloaded (); \ | 3158 | 401 | } \ |
|
3159 | | \ |
3160 | 71.6M | d_m3Op (SetSlot_##TYPE) \ |
3161 | 71.6M | { \ |
3162 | 71.6M | TYPE * dst = slot_ptr (TYPE); \ |
3163 | 71.6M | d_m3PreloadNext (); \ |
3164 | 71.6M | * dst = (TYPE) REG; \ |
3165 | 71.6M | nextOpPreloaded (); \ |
3166 | 71.6M | } \ m3_compile.c:op_SetSlot_i32 Line | Count | Source | 3160 | 38.6M | d_m3Op (SetSlot_##TYPE) \ | 3161 | 38.6M | { \ | 3162 | 38.6M | TYPE * dst = slot_ptr (TYPE); \ | 3163 | 38.6M | d_m3PreloadNext (); \ | 3164 | 38.6M | * dst = (TYPE) REG; \ | 3165 | 38.6M | nextOpPreloaded (); \ | 3166 | 38.6M | } \ |
m3_compile.c:op_SetSlot_i64 Line | Count | Source | 3160 | 18.1M | d_m3Op (SetSlot_##TYPE) \ | 3161 | 18.1M | { \ | 3162 | 18.1M | TYPE * dst = slot_ptr (TYPE); \ | 3163 | 18.1M | d_m3PreloadNext (); \ | 3164 | 18.1M | * dst = (TYPE) REG; \ | 3165 | 18.1M | nextOpPreloaded (); \ | 3166 | 18.1M | } \ |
m3_compile.c:op_SetSlot_f32 Line | Count | Source | 3160 | 6.48M | d_m3Op (SetSlot_##TYPE) \ | 3161 | 6.48M | { \ | 3162 | 6.48M | TYPE * dst = slot_ptr (TYPE); \ | 3163 | 6.48M | d_m3PreloadNext (); \ | 3164 | 6.48M | * dst = (TYPE) REG; \ | 3165 | 6.48M | nextOpPreloaded (); \ | 3166 | 6.48M | } \ |
m3_compile.c:op_SetSlot_f64 Line | Count | Source | 3160 | 8.33M | d_m3Op (SetSlot_##TYPE) \ | 3161 | 8.33M | { \ | 3162 | 8.33M | TYPE * dst = slot_ptr (TYPE); \ | 3163 | 8.33M | d_m3PreloadNext (); \ | 3164 | 8.33M | * dst = (TYPE) REG; \ | 3165 | 8.33M | nextOpPreloaded (); \ | 3166 | 8.33M | } \ |
|
3167 | | \ |
3168 | 1.00M | d_m3Op (PreserveSetSlot_##TYPE) \ |
3169 | 1.00M | { \ |
3170 | 1.00M | TYPE * stack = slot_ptr (TYPE); \ |
3171 | 1.00M | TYPE * preserve = slot_ptr (TYPE); \ |
3172 | 1.00M | d_m3PreloadNext (); \ |
3173 | 1.00M | \ |
3174 | 1.00M | * preserve = * stack; \ |
3175 | 1.00M | * stack = (TYPE) REG; \ |
3176 | 1.00M | \ |
3177 | 1.00M | nextOpPreloaded (); \ |
3178 | 1.00M | } m3_compile.c:op_PreserveSetSlot_i32 Line | Count | Source | 3168 | 318k | d_m3Op (PreserveSetSlot_##TYPE) \ | 3169 | 318k | { \ | 3170 | 318k | TYPE * stack = slot_ptr (TYPE); \ | 3171 | 318k | TYPE * preserve = slot_ptr (TYPE); \ | 3172 | 318k | d_m3PreloadNext (); \ | 3173 | 318k | \ | 3174 | 318k | * preserve = * stack; \ | 3175 | 318k | * stack = (TYPE) REG; \ | 3176 | 318k | \ | 3177 | 318k | nextOpPreloaded (); \ | 3178 | 318k | } |
m3_compile.c:op_PreserveSetSlot_i64 Line | Count | Source | 3168 | 90.1k | d_m3Op (PreserveSetSlot_##TYPE) \ | 3169 | 90.1k | { \ | 3170 | 90.1k | TYPE * stack = slot_ptr (TYPE); \ | 3171 | 90.1k | TYPE * preserve = slot_ptr (TYPE); \ | 3172 | 90.1k | d_m3PreloadNext (); \ | 3173 | 90.1k | \ | 3174 | 90.1k | * preserve = * stack; \ | 3175 | 90.1k | * stack = (TYPE) REG; \ | 3176 | 90.1k | \ | 3177 | 90.1k | nextOpPreloaded (); \ | 3178 | 90.1k | } |
m3_compile.c:op_PreserveSetSlot_f32 Line | Count | Source | 3168 | 264k | d_m3Op (PreserveSetSlot_##TYPE) \ | 3169 | 264k | { \ | 3170 | 264k | TYPE * stack = slot_ptr (TYPE); \ | 3171 | 264k | TYPE * preserve = slot_ptr (TYPE); \ | 3172 | 264k | d_m3PreloadNext (); \ | 3173 | 264k | \ | 3174 | 264k | * preserve = * stack; \ | 3175 | 264k | * stack = (TYPE) REG; \ | 3176 | 264k | \ | 3177 | 264k | nextOpPreloaded (); \ | 3178 | 264k | } |
m3_compile.c:op_PreserveSetSlot_f64 Line | Count | Source | 3168 | 328k | d_m3Op (PreserveSetSlot_##TYPE) \ | 3169 | 328k | { \ | 3170 | 328k | TYPE * stack = slot_ptr (TYPE); \ | 3171 | 328k | TYPE * preserve = slot_ptr (TYPE); \ | 3172 | 328k | d_m3PreloadNext (); \ | 3173 | 328k | \ | 3174 | 328k | * preserve = * stack; \ | 3175 | 328k | * stack = (TYPE) REG; \ | 3176 | 328k | \ | 3177 | 328k | nextOpPreloaded (); \ | 3178 | 328k | } |
|
3179 | | |
3180 | | d_m3SetRegisterSetSlot(i32, _r0) |
3181 | | d_m3SetRegisterSetSlot(i64, _r0) |
3182 | | #if d_m3HasFloat |
3183 | | d_m3SetRegisterSetSlot(f32, _fp0) |
3184 | | d_m3SetRegisterSetSlot(f64, _fp0) |
3185 | | #endif |
3186 | | |
3187 | | d_m3Op(CopySlot_32) |
3188 | 4.07M | { |
3189 | 4.07M | u32* dst = slot_ptr(u32); |
3190 | 4.07M | u32* src = slot_ptr(u32); |
3191 | 4.07M | d_m3PreloadNext(); |
3192 | | |
3193 | 4.07M | *dst = *src; |
3194 | | |
3195 | 4.07M | nextOpPreloaded(); |
3196 | 4.07M | } |
3197 | | |
3198 | | |
3199 | | d_m3Op(PreserveCopySlot_32) |
3200 | 617k | { |
3201 | 617k | u32* dest = slot_ptr(u32); |
3202 | 617k | u32* src = slot_ptr(u32); |
3203 | 617k | u32* preserve = slot_ptr(u32); |
3204 | 617k | d_m3PreloadNext(); |
3205 | | |
3206 | 617k | *preserve = *dest; |
3207 | 617k | *dest = *src; |
3208 | | |
3209 | 617k | nextOpPreloaded(); |
3210 | 617k | } |
3211 | | |
3212 | | |
3213 | | d_m3Op(CopySlot_64) |
3214 | 3.22M | { |
3215 | 3.22M | u64* dst = slot_ptr(u64); |
3216 | 3.22M | u64* src = slot_ptr(u64); |
3217 | 3.22M | d_m3PreloadNext(); |
3218 | | |
3219 | 3.22M | *dst = *src; // printf ("copy: %p <- %" PRIi64 " <- %p\n", dst, * dst, src); |
3220 | | |
3221 | 3.22M | nextOpPreloaded(); |
3222 | 3.22M | } |
3223 | | |
3224 | | |
3225 | | d_m3Op(PreserveCopySlot_64) |
3226 | 1.01M | { |
3227 | 1.01M | u64* dest = slot_ptr(u64); |
3228 | 1.01M | u64* src = slot_ptr(u64); |
3229 | 1.01M | u64* preserve = slot_ptr(u64); |
3230 | 1.01M | d_m3PreloadNext(); |
3231 | | |
3232 | 1.01M | *preserve = *dest; |
3233 | 1.01M | *dest = *src; |
3234 | | |
3235 | 1.01M | nextOpPreloaded(); |
3236 | 1.01M | } |
3237 | | |
3238 | | |
3239 | | #if d_m3EnableOpTracing |
3240 | | //-------------------------------------------------------------------------------------------------------- |
3241 | | d_m3Op(DumpStack) |
3242 | | { |
3243 | | u32 opcodeIndex = immediate(u32); |
3244 | | u32 stackHeight = immediate(u32); |
3245 | | IM3Function function = immediate(IM3Function); |
3246 | | |
3247 | | cstr_t funcName = (function) ? m3_GetFunctionName(function) : ""; |
3248 | | |
3249 | | printf(" %4d ", opcodeIndex); |
3250 | | printf(" %-25s r0: 0x%016" PRIx64 " i:%" PRIi64 " u:%" PRIu64 "\n", funcName, _r0, _r0, _r0); |
3251 | | # if d_m3HasFloat |
3252 | | printf(" fp0: %" PRIf64 "\n", _fp0); |
3253 | | # endif |
3254 | | m3stack_t sp = _sp; |
3255 | | |
3256 | | for (u32 i = 0; i < stackHeight; ++i) { |
3257 | | cstr_t kind = ""; |
3258 | | |
3259 | | printf("%p %5s %2d: 0x%" PRIx64 " i:%" PRIi64 "\n", sp, kind, i, (u64) * (sp), (i64) * (sp)); |
3260 | | |
3261 | | ++sp; |
3262 | | } |
3263 | | printf("---------------------------------------------------------------------------------------------------------\n"); |
3264 | | |
3265 | | nextOpDirect(); |
3266 | | } |
3267 | | #endif |
3268 | | |
3269 | | |
3270 | | #define d_m3Select_i(TYPE, REG) \ |
3271 | 1.25M | d_m3Op (Select_##TYPE##_rss) \ |
3272 | 1.25M | { \ |
3273 | 1.25M | i32 condition = (i32) _r0; \ |
3274 | 1.25M | \ |
3275 | 1.25M | TYPE operand2 = slot (TYPE); \ |
3276 | 1.25M | TYPE operand1 = slot (TYPE); \ |
3277 | 1.25M | \ |
3278 | 1.25M | REG = (condition) ? operand1 : operand2; \ |
3279 | 1.25M | \ |
3280 | 1.25M | nextOp (); \ |
3281 | 1.25M | } \ m3_compile.c:op_Select_i32_rss Line | Count | Source | 3271 | 793k | d_m3Op (Select_##TYPE##_rss) \ | 3272 | 793k | { \ | 3273 | 793k | i32 condition = (i32) _r0; \ | 3274 | 793k | \ | 3275 | 793k | TYPE operand2 = slot (TYPE); \ | 3276 | 793k | TYPE operand1 = slot (TYPE); \ | 3277 | 793k | \ | 3278 | 793k | REG = (condition) ? operand1 : operand2; \ | 3279 | 793k | \ | 3280 | 793k | nextOp (); \ | 3281 | 793k | } \ |
m3_compile.c:op_Select_i64_rss Line | Count | Source | 3271 | 464k | d_m3Op (Select_##TYPE##_rss) \ | 3272 | 464k | { \ | 3273 | 464k | i32 condition = (i32) _r0; \ | 3274 | 464k | \ | 3275 | 464k | TYPE operand2 = slot (TYPE); \ | 3276 | 464k | TYPE operand1 = slot (TYPE); \ | 3277 | 464k | \ | 3278 | 464k | REG = (condition) ? operand1 : operand2; \ | 3279 | 464k | \ | 3280 | 464k | nextOp (); \ | 3281 | 464k | } \ |
|
3282 | | \ |
3283 | 877k | d_m3Op (Select_##TYPE##_srs) \ |
3284 | 877k | { \ |
3285 | 877k | i32 condition = slot (i32); \ |
3286 | 877k | \ |
3287 | 877k | TYPE operand2 = (TYPE) REG; \ |
3288 | 877k | TYPE operand1 = slot (TYPE); \ |
3289 | 877k | \ |
3290 | 877k | REG = (condition) ? operand1 : operand2; \ |
3291 | 877k | \ |
3292 | 877k | nextOp (); \ |
3293 | 877k | } \ m3_compile.c:op_Select_i32_srs Line | Count | Source | 3283 | 680k | d_m3Op (Select_##TYPE##_srs) \ | 3284 | 680k | { \ | 3285 | 680k | i32 condition = slot (i32); \ | 3286 | 680k | \ | 3287 | 680k | TYPE operand2 = (TYPE) REG; \ | 3288 | 680k | TYPE operand1 = slot (TYPE); \ | 3289 | 680k | \ | 3290 | 680k | REG = (condition) ? operand1 : operand2; \ | 3291 | 680k | \ | 3292 | 680k | nextOp (); \ | 3293 | 680k | } \ |
m3_compile.c:op_Select_i64_srs Line | Count | Source | 3283 | 196k | d_m3Op (Select_##TYPE##_srs) \ | 3284 | 196k | { \ | 3285 | 196k | i32 condition = slot (i32); \ | 3286 | 196k | \ | 3287 | 196k | TYPE operand2 = (TYPE) REG; \ | 3288 | 196k | TYPE operand1 = slot (TYPE); \ | 3289 | 196k | \ | 3290 | 196k | REG = (condition) ? operand1 : operand2; \ | 3291 | 196k | \ | 3292 | 196k | nextOp (); \ | 3293 | 196k | } \ |
|
3294 | | \ |
3295 | 1.02M | d_m3Op (Select_##TYPE##_ssr) \ |
3296 | 1.02M | { \ |
3297 | 1.02M | i32 condition = slot (i32); \ |
3298 | 1.02M | \ |
3299 | 1.02M | TYPE operand2 = slot (TYPE); \ |
3300 | 1.02M | TYPE operand1 = (TYPE) REG; \ |
3301 | 1.02M | \ |
3302 | 1.02M | REG = (condition) ? operand1 : operand2; \ |
3303 | 1.02M | \ |
3304 | 1.02M | nextOp (); \ |
3305 | 1.02M | } \ m3_compile.c:op_Select_i32_ssr Line | Count | Source | 3295 | 621k | d_m3Op (Select_##TYPE##_ssr) \ | 3296 | 621k | { \ | 3297 | 621k | i32 condition = slot (i32); \ | 3298 | 621k | \ | 3299 | 621k | TYPE operand2 = slot (TYPE); \ | 3300 | 621k | TYPE operand1 = (TYPE) REG; \ | 3301 | 621k | \ | 3302 | 621k | REG = (condition) ? operand1 : operand2; \ | 3303 | 621k | \ | 3304 | 621k | nextOp (); \ | 3305 | 621k | } \ |
m3_compile.c:op_Select_i64_ssr Line | Count | Source | 3295 | 405k | d_m3Op (Select_##TYPE##_ssr) \ | 3296 | 405k | { \ | 3297 | 405k | i32 condition = slot (i32); \ | 3298 | 405k | \ | 3299 | 405k | TYPE operand2 = slot (TYPE); \ | 3300 | 405k | TYPE operand1 = (TYPE) REG; \ | 3301 | 405k | \ | 3302 | 405k | REG = (condition) ? operand1 : operand2; \ | 3303 | 405k | \ | 3304 | 405k | nextOp (); \ | 3305 | 405k | } \ |
|
3306 | | \ |
3307 | 1.53M | d_m3Op (Select_##TYPE##_sss) \ |
3308 | 1.53M | { \ |
3309 | 1.53M | i32 condition = slot (i32); \ |
3310 | 1.53M | \ |
3311 | 1.53M | TYPE operand2 = slot (TYPE); \ |
3312 | 1.53M | TYPE operand1 = slot (TYPE); \ |
3313 | 1.53M | \ |
3314 | 1.53M | REG = (condition) ? operand1 : operand2; \ |
3315 | 1.53M | \ |
3316 | 1.53M | nextOp (); \ |
3317 | 1.53M | } m3_compile.c:op_Select_i32_sss Line | Count | Source | 3307 | 1.10M | d_m3Op (Select_##TYPE##_sss) \ | 3308 | 1.10M | { \ | 3309 | 1.10M | i32 condition = slot (i32); \ | 3310 | 1.10M | \ | 3311 | 1.10M | TYPE operand2 = slot (TYPE); \ | 3312 | 1.10M | TYPE operand1 = slot (TYPE); \ | 3313 | 1.10M | \ | 3314 | 1.10M | REG = (condition) ? operand1 : operand2; \ | 3315 | 1.10M | \ | 3316 | 1.10M | nextOp (); \ | 3317 | 1.10M | } |
m3_compile.c:op_Select_i64_sss Line | Count | Source | 3307 | 434k | d_m3Op (Select_##TYPE##_sss) \ | 3308 | 434k | { \ | 3309 | 434k | i32 condition = slot (i32); \ | 3310 | 434k | \ | 3311 | 434k | TYPE operand2 = slot (TYPE); \ | 3312 | 434k | TYPE operand1 = slot (TYPE); \ | 3313 | 434k | \ | 3314 | 434k | REG = (condition) ? operand1 : operand2; \ | 3315 | 434k | \ | 3316 | 434k | nextOp (); \ | 3317 | 434k | } |
|
3318 | | |
3319 | | |
3320 | | d_m3Select_i(i32, _r0) |
3321 | | d_m3Select_i(i64, _r0) |
3322 | | |
3323 | | |
3324 | | #define d_m3Select_f(TYPE, REG, LABEL, SELECTOR) \ |
3325 | 1.50M | d_m3Op (Select_##TYPE##_##LABEL##ss) \ |
3326 | 1.50M | { \ |
3327 | 1.50M | i32 condition = (i32) SELECTOR; \ |
3328 | 1.50M | \ |
3329 | 1.50M | TYPE operand2 = slot (TYPE); \ |
3330 | 1.50M | TYPE operand1 = slot (TYPE); \ |
3331 | 1.50M | \ |
3332 | 1.50M | REG = (condition) ? operand1 : operand2; \ |
3333 | 1.50M | \ |
3334 | 1.50M | nextOp (); \ |
3335 | 1.50M | } \ m3_compile.c:op_Select_f32_sss Line | Count | Source | 3325 | 511k | d_m3Op (Select_##TYPE##_##LABEL##ss) \ | 3326 | 511k | { \ | 3327 | 511k | i32 condition = (i32) SELECTOR; \ | 3328 | 511k | \ | 3329 | 511k | TYPE operand2 = slot (TYPE); \ | 3330 | 511k | TYPE operand1 = slot (TYPE); \ | 3331 | 511k | \ | 3332 | 511k | REG = (condition) ? operand1 : operand2; \ | 3333 | 511k | \ | 3334 | 511k | nextOp (); \ | 3335 | 511k | } \ |
m3_compile.c:op_Select_f32_rss Line | Count | Source | 3325 | 415k | d_m3Op (Select_##TYPE##_##LABEL##ss) \ | 3326 | 415k | { \ | 3327 | 415k | i32 condition = (i32) SELECTOR; \ | 3328 | 415k | \ | 3329 | 415k | TYPE operand2 = slot (TYPE); \ | 3330 | 415k | TYPE operand1 = slot (TYPE); \ | 3331 | 415k | \ | 3332 | 415k | REG = (condition) ? operand1 : operand2; \ | 3333 | 415k | \ | 3334 | 415k | nextOp (); \ | 3335 | 415k | } \ |
m3_compile.c:op_Select_f64_sss Line | Count | Source | 3325 | 252k | d_m3Op (Select_##TYPE##_##LABEL##ss) \ | 3326 | 252k | { \ | 3327 | 252k | i32 condition = (i32) SELECTOR; \ | 3328 | 252k | \ | 3329 | 252k | TYPE operand2 = slot (TYPE); \ | 3330 | 252k | TYPE operand1 = slot (TYPE); \ | 3331 | 252k | \ | 3332 | 252k | REG = (condition) ? operand1 : operand2; \ | 3333 | 252k | \ | 3334 | 252k | nextOp (); \ | 3335 | 252k | } \ |
m3_compile.c:op_Select_f64_rss Line | Count | Source | 3325 | 321k | d_m3Op (Select_##TYPE##_##LABEL##ss) \ | 3326 | 321k | { \ | 3327 | 321k | i32 condition = (i32) SELECTOR; \ | 3328 | 321k | \ | 3329 | 321k | TYPE operand2 = slot (TYPE); \ | 3330 | 321k | TYPE operand1 = slot (TYPE); \ | 3331 | 321k | \ | 3332 | 321k | REG = (condition) ? operand1 : operand2; \ | 3333 | 321k | \ | 3334 | 321k | nextOp (); \ | 3335 | 321k | } \ |
|
3336 | | \ |
3337 | 908k | d_m3Op (Select_##TYPE##_##LABEL##rs) \ |
3338 | 908k | { \ |
3339 | 908k | i32 condition = (i32) SELECTOR; \ |
3340 | 908k | \ |
3341 | 908k | TYPE operand2 = (TYPE) REG; \ |
3342 | 908k | TYPE operand1 = slot (TYPE); \ |
3343 | 908k | \ |
3344 | 908k | REG = (condition) ? operand1 : operand2; \ |
3345 | 908k | \ |
3346 | 908k | nextOp (); \ |
3347 | 908k | } \ m3_compile.c:op_Select_f32_srs Line | Count | Source | 3337 | 243k | d_m3Op (Select_##TYPE##_##LABEL##rs) \ | 3338 | 243k | { \ | 3339 | 243k | i32 condition = (i32) SELECTOR; \ | 3340 | 243k | \ | 3341 | 243k | TYPE operand2 = (TYPE) REG; \ | 3342 | 243k | TYPE operand1 = slot (TYPE); \ | 3343 | 243k | \ | 3344 | 243k | REG = (condition) ? operand1 : operand2; \ | 3345 | 243k | \ | 3346 | 243k | nextOp (); \ | 3347 | 243k | } \ |
m3_compile.c:op_Select_f32_rrs Line | Count | Source | 3337 | 315k | d_m3Op (Select_##TYPE##_##LABEL##rs) \ | 3338 | 315k | { \ | 3339 | 315k | i32 condition = (i32) SELECTOR; \ | 3340 | 315k | \ | 3341 | 315k | TYPE operand2 = (TYPE) REG; \ | 3342 | 315k | TYPE operand1 = slot (TYPE); \ | 3343 | 315k | \ | 3344 | 315k | REG = (condition) ? operand1 : operand2; \ | 3345 | 315k | \ | 3346 | 315k | nextOp (); \ | 3347 | 315k | } \ |
m3_compile.c:op_Select_f64_srs Line | Count | Source | 3337 | 133k | d_m3Op (Select_##TYPE##_##LABEL##rs) \ | 3338 | 133k | { \ | 3339 | 133k | i32 condition = (i32) SELECTOR; \ | 3340 | 133k | \ | 3341 | 133k | TYPE operand2 = (TYPE) REG; \ | 3342 | 133k | TYPE operand1 = slot (TYPE); \ | 3343 | 133k | \ | 3344 | 133k | REG = (condition) ? operand1 : operand2; \ | 3345 | 133k | \ | 3346 | 133k | nextOp (); \ | 3347 | 133k | } \ |
m3_compile.c:op_Select_f64_rrs Line | Count | Source | 3337 | 215k | d_m3Op (Select_##TYPE##_##LABEL##rs) \ | 3338 | 215k | { \ | 3339 | 215k | i32 condition = (i32) SELECTOR; \ | 3340 | 215k | \ | 3341 | 215k | TYPE operand2 = (TYPE) REG; \ | 3342 | 215k | TYPE operand1 = slot (TYPE); \ | 3343 | 215k | \ | 3344 | 215k | REG = (condition) ? operand1 : operand2; \ | 3345 | 215k | \ | 3346 | 215k | nextOp (); \ | 3347 | 215k | } \ |
|
3348 | | \ |
3349 | 968k | d_m3Op (Select_##TYPE##_##LABEL##sr) \ |
3350 | 968k | { \ |
3351 | 968k | i32 condition = (i32) SELECTOR; \ |
3352 | 968k | \ |
3353 | 968k | TYPE operand2 = slot (TYPE); \ |
3354 | 968k | TYPE operand1 = (TYPE) REG; \ |
3355 | 968k | \ |
3356 | 968k | REG = (condition) ? operand1 : operand2; \ |
3357 | 968k | \ |
3358 | 968k | nextOp (); \ |
3359 | 968k | } m3_compile.c:op_Select_f32_ssr Line | Count | Source | 3349 | 189k | d_m3Op (Select_##TYPE##_##LABEL##sr) \ | 3350 | 189k | { \ | 3351 | 189k | i32 condition = (i32) SELECTOR; \ | 3352 | 189k | \ | 3353 | 189k | TYPE operand2 = slot (TYPE); \ | 3354 | 189k | TYPE operand1 = (TYPE) REG; \ | 3355 | 189k | \ | 3356 | 189k | REG = (condition) ? operand1 : operand2; \ | 3357 | 189k | \ | 3358 | 189k | nextOp (); \ | 3359 | 189k | } |
m3_compile.c:op_Select_f32_rsr Line | Count | Source | 3349 | 392k | d_m3Op (Select_##TYPE##_##LABEL##sr) \ | 3350 | 392k | { \ | 3351 | 392k | i32 condition = (i32) SELECTOR; \ | 3352 | 392k | \ | 3353 | 392k | TYPE operand2 = slot (TYPE); \ | 3354 | 392k | TYPE operand1 = (TYPE) REG; \ | 3355 | 392k | \ | 3356 | 392k | REG = (condition) ? operand1 : operand2; \ | 3357 | 392k | \ | 3358 | 392k | nextOp (); \ | 3359 | 392k | } |
m3_compile.c:op_Select_f64_ssr Line | Count | Source | 3349 | 214k | d_m3Op (Select_##TYPE##_##LABEL##sr) \ | 3350 | 214k | { \ | 3351 | 214k | i32 condition = (i32) SELECTOR; \ | 3352 | 214k | \ | 3353 | 214k | TYPE operand2 = slot (TYPE); \ | 3354 | 214k | TYPE operand1 = (TYPE) REG; \ | 3355 | 214k | \ | 3356 | 214k | REG = (condition) ? operand1 : operand2; \ | 3357 | 214k | \ | 3358 | 214k | nextOp (); \ | 3359 | 214k | } |
m3_compile.c:op_Select_f64_rsr Line | Count | Source | 3349 | 172k | d_m3Op (Select_##TYPE##_##LABEL##sr) \ | 3350 | 172k | { \ | 3351 | 172k | i32 condition = (i32) SELECTOR; \ | 3352 | 172k | \ | 3353 | 172k | TYPE operand2 = slot (TYPE); \ | 3354 | 172k | TYPE operand1 = (TYPE) REG; \ | 3355 | 172k | \ | 3356 | 172k | REG = (condition) ? operand1 : operand2; \ | 3357 | 172k | \ | 3358 | 172k | nextOp (); \ | 3359 | 172k | } |
|
3360 | | |
3361 | | #if d_m3HasFloat |
3362 | | d_m3Select_f(f32, _fp0, r, _r0) |
3363 | | d_m3Select_f(f32, _fp0, s, slot(i32)) |
3364 | | |
3365 | | d_m3Select_f(f64, _fp0, r, _r0) |
3366 | | d_m3Select_f(f64, _fp0, s, slot(i32)) |
3367 | | #endif |
3368 | | |
3369 | | d_m3Op(Return) |
3370 | 2.61k | { |
3371 | 2.61k | m3StackCheck(); |
3372 | 2.61k | return m3Err_none; |
3373 | 2.61k | } |
3374 | | |
3375 | | |
3376 | | d_m3Op(BranchIf_r) |
3377 | 455k | { |
3378 | 455k | i32 condition = (i32)_r0; |
3379 | 455k | pc_t branch = immediate(pc_t); |
3380 | | |
3381 | 455k | if (condition) { |
3382 | 364k | jumpOp(branch); |
3383 | 364k | } else { |
3384 | 90.1k | nextOp(); |
3385 | 90.1k | } |
3386 | 455k | } |
3387 | | |
3388 | | |
3389 | | d_m3Op(BranchIf_s) |
3390 | 522k | { |
3391 | 522k | i32 condition = slot(i32); |
3392 | 522k | pc_t branch = immediate(pc_t); |
3393 | | |
3394 | 522k | if (condition) { |
3395 | 138k | jumpOp(branch); |
3396 | 383k | } else { |
3397 | 383k | nextOp(); |
3398 | 383k | } |
3399 | 522k | } |
3400 | | |
3401 | | #if d_m3FuseBranch |
3402 | | |
3403 | | // fused compare+branch and compare+if: a compare retro-patched by the compiler when a br_if or if |
3404 | | // immediately consumes its result. operand shapes and immediate order match the plain compare |
3405 | | // (_rs/_sr/_ss); the branch/else target pointer is the last immediate. |
3406 | | # define d_m3FusedCmpBranch(TYPE, NAME, OPER) \ |
3407 | | d_m3Op(TYPE##_BranchIf_##NAME##_rs) \ |
3408 | 1.61M | { \ |
3409 | 1.61M | TYPE operand = slot (TYPE); \ |
3410 | 1.61M | pc_t branch = immediate (pc_t); \ |
3411 | 1.61M | if (operand OPER ((TYPE) _r0)) \ |
3412 | 1.61M | jumpOp (branch); \ |
3413 | 1.61M | else nextOp (); \ |
3414 | 1.61M | } \ m3_compile.c:op_i32_BranchIf_Equal_rs Line | Count | Source | 3408 | 176k | { \ | 3409 | 176k | TYPE operand = slot (TYPE); \ | 3410 | 176k | pc_t branch = immediate (pc_t); \ | 3411 | 176k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 176k | jumpOp (branch); \ | 3413 | 176k | else nextOp (); \ | 3414 | 176k | } \ |
m3_compile.c:op_i32_BranchIf_NotEqual_rs Line | Count | Source | 3408 | 228k | { \ | 3409 | 228k | TYPE operand = slot (TYPE); \ | 3410 | 228k | pc_t branch = immediate (pc_t); \ | 3411 | 228k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 228k | jumpOp (branch); \ | 3413 | 228k | else nextOp (); \ | 3414 | 228k | } \ |
m3_compile.c:op_i32_BranchIf_LessThan_rs Line | Count | Source | 3408 | 78.6k | { \ | 3409 | 78.6k | TYPE operand = slot (TYPE); \ | 3410 | 78.6k | pc_t branch = immediate (pc_t); \ | 3411 | 78.6k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 78.6k | jumpOp (branch); \ | 3413 | 78.6k | else nextOp (); \ | 3414 | 78.6k | } \ |
m3_compile.c:op_u32_BranchIf_LessThan_rs Line | Count | Source | 3408 | 102k | { \ | 3409 | 102k | TYPE operand = slot (TYPE); \ | 3410 | 102k | pc_t branch = immediate (pc_t); \ | 3411 | 102k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 102k | jumpOp (branch); \ | 3413 | 102k | else nextOp (); \ | 3414 | 102k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThan_rs Line | Count | Source | 3408 | 146k | { \ | 3409 | 146k | TYPE operand = slot (TYPE); \ | 3410 | 146k | pc_t branch = immediate (pc_t); \ | 3411 | 146k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 146k | jumpOp (branch); \ | 3413 | 146k | else nextOp (); \ | 3414 | 146k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThan_rs Line | Count | Source | 3408 | 107k | { \ | 3409 | 107k | TYPE operand = slot (TYPE); \ | 3410 | 107k | pc_t branch = immediate (pc_t); \ | 3411 | 107k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 107k | jumpOp (branch); \ | 3413 | 107k | else nextOp (); \ | 3414 | 107k | } \ |
m3_compile.c:op_i32_BranchIf_LessThanOrEqual_rs Line | Count | Source | 3408 | 201k | { \ | 3409 | 201k | TYPE operand = slot (TYPE); \ | 3410 | 201k | pc_t branch = immediate (pc_t); \ | 3411 | 201k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 201k | jumpOp (branch); \ | 3413 | 201k | else nextOp (); \ | 3414 | 201k | } \ |
m3_compile.c:op_u32_BranchIf_LessThanOrEqual_rs Line | Count | Source | 3408 | 116k | { \ | 3409 | 116k | TYPE operand = slot (TYPE); \ | 3410 | 116k | pc_t branch = immediate (pc_t); \ | 3411 | 116k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 116k | jumpOp (branch); \ | 3413 | 116k | else nextOp (); \ | 3414 | 116k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThanOrEqual_rs Line | Count | Source | 3408 | 305k | { \ | 3409 | 305k | TYPE operand = slot (TYPE); \ | 3410 | 305k | pc_t branch = immediate (pc_t); \ | 3411 | 305k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 305k | jumpOp (branch); \ | 3413 | 305k | else nextOp (); \ | 3414 | 305k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThanOrEqual_rs Line | Count | Source | 3408 | 153k | { \ | 3409 | 153k | TYPE operand = slot (TYPE); \ | 3410 | 153k | pc_t branch = immediate (pc_t); \ | 3411 | 153k | if (operand OPER ((TYPE) _r0)) \ | 3412 | 153k | jumpOp (branch); \ | 3413 | 153k | else nextOp (); \ | 3414 | 153k | } \ |
|
3415 | | d_m3Op(TYPE##_BranchIf_##NAME##_sr) \ |
3416 | 1.92M | { \ |
3417 | 1.92M | TYPE operand = slot (TYPE); \ |
3418 | 1.92M | pc_t branch = immediate (pc_t); \ |
3419 | 1.92M | if (((TYPE) _r0) OPER operand) \ |
3420 | 1.92M | jumpOp (branch); \ |
3421 | 1.92M | else nextOp (); \ |
3422 | 1.92M | } \ m3_compile.c:op_i32_BranchIf_LessThan_sr Line | Count | Source | 3416 | 180k | { \ | 3417 | 180k | TYPE operand = slot (TYPE); \ | 3418 | 180k | pc_t branch = immediate (pc_t); \ | 3419 | 180k | if (((TYPE) _r0) OPER operand) \ | 3420 | 180k | jumpOp (branch); \ | 3421 | 180k | else nextOp (); \ | 3422 | 180k | } \ |
m3_compile.c:op_u32_BranchIf_LessThan_sr Line | Count | Source | 3416 | 281k | { \ | 3417 | 281k | TYPE operand = slot (TYPE); \ | 3418 | 281k | pc_t branch = immediate (pc_t); \ | 3419 | 281k | if (((TYPE) _r0) OPER operand) \ | 3420 | 281k | jumpOp (branch); \ | 3421 | 281k | else nextOp (); \ | 3422 | 281k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThan_sr Line | Count | Source | 3416 | 265k | { \ | 3417 | 265k | TYPE operand = slot (TYPE); \ | 3418 | 265k | pc_t branch = immediate (pc_t); \ | 3419 | 265k | if (((TYPE) _r0) OPER operand) \ | 3420 | 265k | jumpOp (branch); \ | 3421 | 265k | else nextOp (); \ | 3422 | 265k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThan_sr Line | Count | Source | 3416 | 314k | { \ | 3417 | 314k | TYPE operand = slot (TYPE); \ | 3418 | 314k | pc_t branch = immediate (pc_t); \ | 3419 | 314k | if (((TYPE) _r0) OPER operand) \ | 3420 | 314k | jumpOp (branch); \ | 3421 | 314k | else nextOp (); \ | 3422 | 314k | } \ |
m3_compile.c:op_i32_BranchIf_LessThanOrEqual_sr Line | Count | Source | 3416 | 195k | { \ | 3417 | 195k | TYPE operand = slot (TYPE); \ | 3418 | 195k | pc_t branch = immediate (pc_t); \ | 3419 | 195k | if (((TYPE) _r0) OPER operand) \ | 3420 | 195k | jumpOp (branch); \ | 3421 | 195k | else nextOp (); \ | 3422 | 195k | } \ |
m3_compile.c:op_u32_BranchIf_LessThanOrEqual_sr Line | Count | Source | 3416 | 257k | { \ | 3417 | 257k | TYPE operand = slot (TYPE); \ | 3418 | 257k | pc_t branch = immediate (pc_t); \ | 3419 | 257k | if (((TYPE) _r0) OPER operand) \ | 3420 | 257k | jumpOp (branch); \ | 3421 | 257k | else nextOp (); \ | 3422 | 257k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThanOrEqual_sr Line | Count | Source | 3416 | 222k | { \ | 3417 | 222k | TYPE operand = slot (TYPE); \ | 3418 | 222k | pc_t branch = immediate (pc_t); \ | 3419 | 222k | if (((TYPE) _r0) OPER operand) \ | 3420 | 222k | jumpOp (branch); \ | 3421 | 222k | else nextOp (); \ | 3422 | 222k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThanOrEqual_sr Line | Count | Source | 3416 | 208k | { \ | 3417 | 208k | TYPE operand = slot (TYPE); \ | 3418 | 208k | pc_t branch = immediate (pc_t); \ | 3419 | 208k | if (((TYPE) _r0) OPER operand) \ | 3420 | 208k | jumpOp (branch); \ | 3421 | 208k | else nextOp (); \ | 3422 | 208k | } \ |
Unexecuted instantiation: m3_compile.c:op_i32_BranchIf_Equal_sr Unexecuted instantiation: m3_compile.c:op_i32_BranchIf_NotEqual_sr |
3423 | | d_m3Op(TYPE##_BranchIf_##NAME##_ss) \ |
3424 | 2.99M | { \ |
3425 | 2.99M | TYPE operand2 = slot (TYPE); \ |
3426 | 2.99M | TYPE operand1 = slot (TYPE); \ |
3427 | 2.99M | pc_t branch = immediate (pc_t); \ |
3428 | 2.99M | if (operand1 OPER operand2) \ |
3429 | 2.99M | jumpOp (branch); \ |
3430 | 2.99M | else nextOp (); \ |
3431 | 2.99M | } \ m3_compile.c:op_i32_BranchIf_Equal_ss Line | Count | Source | 3424 | 170k | { \ | 3425 | 170k | TYPE operand2 = slot (TYPE); \ | 3426 | 170k | TYPE operand1 = slot (TYPE); \ | 3427 | 170k | pc_t branch = immediate (pc_t); \ | 3428 | 170k | if (operand1 OPER operand2) \ | 3429 | 170k | jumpOp (branch); \ | 3430 | 170k | else nextOp (); \ | 3431 | 170k | } \ |
m3_compile.c:op_i32_BranchIf_NotEqual_ss Line | Count | Source | 3424 | 179k | { \ | 3425 | 179k | TYPE operand2 = slot (TYPE); \ | 3426 | 179k | TYPE operand1 = slot (TYPE); \ | 3427 | 179k | pc_t branch = immediate (pc_t); \ | 3428 | 179k | if (operand1 OPER operand2) \ | 3429 | 179k | jumpOp (branch); \ | 3430 | 179k | else nextOp (); \ | 3431 | 179k | } \ |
m3_compile.c:op_i32_BranchIf_LessThan_ss Line | Count | Source | 3424 | 163k | { \ | 3425 | 163k | TYPE operand2 = slot (TYPE); \ | 3426 | 163k | TYPE operand1 = slot (TYPE); \ | 3427 | 163k | pc_t branch = immediate (pc_t); \ | 3428 | 163k | if (operand1 OPER operand2) \ | 3429 | 163k | jumpOp (branch); \ | 3430 | 163k | else nextOp (); \ | 3431 | 163k | } \ |
m3_compile.c:op_u32_BranchIf_LessThan_ss Line | Count | Source | 3424 | 291k | { \ | 3425 | 291k | TYPE operand2 = slot (TYPE); \ | 3426 | 291k | TYPE operand1 = slot (TYPE); \ | 3427 | 291k | pc_t branch = immediate (pc_t); \ | 3428 | 291k | if (operand1 OPER operand2) \ | 3429 | 291k | jumpOp (branch); \ | 3430 | 291k | else nextOp (); \ | 3431 | 291k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThan_ss Line | Count | Source | 3424 | 292k | { \ | 3425 | 292k | TYPE operand2 = slot (TYPE); \ | 3426 | 292k | TYPE operand1 = slot (TYPE); \ | 3427 | 292k | pc_t branch = immediate (pc_t); \ | 3428 | 292k | if (operand1 OPER operand2) \ | 3429 | 292k | jumpOp (branch); \ | 3430 | 292k | else nextOp (); \ | 3431 | 292k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThan_ss Line | Count | Source | 3424 | 306k | { \ | 3425 | 306k | TYPE operand2 = slot (TYPE); \ | 3426 | 306k | TYPE operand1 = slot (TYPE); \ | 3427 | 306k | pc_t branch = immediate (pc_t); \ | 3428 | 306k | if (operand1 OPER operand2) \ | 3429 | 306k | jumpOp (branch); \ | 3430 | 306k | else nextOp (); \ | 3431 | 306k | } \ |
m3_compile.c:op_i32_BranchIf_LessThanOrEqual_ss Line | Count | Source | 3424 | 500k | { \ | 3425 | 500k | TYPE operand2 = slot (TYPE); \ | 3426 | 500k | TYPE operand1 = slot (TYPE); \ | 3427 | 500k | pc_t branch = immediate (pc_t); \ | 3428 | 500k | if (operand1 OPER operand2) \ | 3429 | 500k | jumpOp (branch); \ | 3430 | 500k | else nextOp (); \ | 3431 | 500k | } \ |
m3_compile.c:op_u32_BranchIf_LessThanOrEqual_ss Line | Count | Source | 3424 | 390k | { \ | 3425 | 390k | TYPE operand2 = slot (TYPE); \ | 3426 | 390k | TYPE operand1 = slot (TYPE); \ | 3427 | 390k | pc_t branch = immediate (pc_t); \ | 3428 | 390k | if (operand1 OPER operand2) \ | 3429 | 390k | jumpOp (branch); \ | 3430 | 390k | else nextOp (); \ | 3431 | 390k | } \ |
m3_compile.c:op_i32_BranchIf_GreaterThanOrEqual_ss Line | Count | Source | 3424 | 448k | { \ | 3425 | 448k | TYPE operand2 = slot (TYPE); \ | 3426 | 448k | TYPE operand1 = slot (TYPE); \ | 3427 | 448k | pc_t branch = immediate (pc_t); \ | 3428 | 448k | if (operand1 OPER operand2) \ | 3429 | 448k | jumpOp (branch); \ | 3430 | 448k | else nextOp (); \ | 3431 | 448k | } \ |
m3_compile.c:op_u32_BranchIf_GreaterThanOrEqual_ss Line | Count | Source | 3424 | 252k | { \ | 3425 | 252k | TYPE operand2 = slot (TYPE); \ | 3426 | 252k | TYPE operand1 = slot (TYPE); \ | 3427 | 252k | pc_t branch = immediate (pc_t); \ | 3428 | 252k | if (operand1 OPER operand2) \ | 3429 | 252k | jumpOp (branch); \ | 3430 | 252k | else nextOp (); \ | 3431 | 252k | } \ |
|
3432 | | d_m3Op(TYPE##_If_##NAME##_rs) \ |
3433 | 13.0M | { \ |
3434 | 13.0M | TYPE operand = slot (TYPE); \ |
3435 | 13.0M | pc_t elsePC = immediate (pc_t); \ |
3436 | 13.0M | if (operand OPER ((TYPE) _r0)) \ |
3437 | 13.0M | nextOp (); \ |
3438 | 13.0M | else jumpOp (elsePC); \ |
3439 | 13.0M | } \ m3_compile.c:op_i32_If_Equal_rs Line | Count | Source | 3433 | 1.82M | { \ | 3434 | 1.82M | TYPE operand = slot (TYPE); \ | 3435 | 1.82M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.82M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.82M | nextOp (); \ | 3438 | 1.82M | else jumpOp (elsePC); \ | 3439 | 1.82M | } \ |
m3_compile.c:op_i32_If_NotEqual_rs Line | Count | Source | 3433 | 1.75M | { \ | 3434 | 1.75M | TYPE operand = slot (TYPE); \ | 3435 | 1.75M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.75M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.75M | nextOp (); \ | 3438 | 1.75M | else jumpOp (elsePC); \ | 3439 | 1.75M | } \ |
m3_compile.c:op_i32_If_LessThan_rs Line | Count | Source | 3433 | 1.26M | { \ | 3434 | 1.26M | TYPE operand = slot (TYPE); \ | 3435 | 1.26M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.26M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.26M | nextOp (); \ | 3438 | 1.26M | else jumpOp (elsePC); \ | 3439 | 1.26M | } \ |
m3_compile.c:op_u32_If_LessThan_rs Line | Count | Source | 3433 | 1.66M | { \ | 3434 | 1.66M | TYPE operand = slot (TYPE); \ | 3435 | 1.66M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.66M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.66M | nextOp (); \ | 3438 | 1.66M | else jumpOp (elsePC); \ | 3439 | 1.66M | } \ |
m3_compile.c:op_i32_If_GreaterThan_rs Line | Count | Source | 3433 | 1.06M | { \ | 3434 | 1.06M | TYPE operand = slot (TYPE); \ | 3435 | 1.06M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.06M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.06M | nextOp (); \ | 3438 | 1.06M | else jumpOp (elsePC); \ | 3439 | 1.06M | } \ |
m3_compile.c:op_u32_If_GreaterThan_rs Line | Count | Source | 3433 | 1.14M | { \ | 3434 | 1.14M | TYPE operand = slot (TYPE); \ | 3435 | 1.14M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.14M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.14M | nextOp (); \ | 3438 | 1.14M | else jumpOp (elsePC); \ | 3439 | 1.14M | } \ |
m3_compile.c:op_i32_If_LessThanOrEqual_rs Line | Count | Source | 3433 | 1.47M | { \ | 3434 | 1.47M | TYPE operand = slot (TYPE); \ | 3435 | 1.47M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.47M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.47M | nextOp (); \ | 3438 | 1.47M | else jumpOp (elsePC); \ | 3439 | 1.47M | } \ |
m3_compile.c:op_u32_If_LessThanOrEqual_rs Line | Count | Source | 3433 | 977k | { \ | 3434 | 977k | TYPE operand = slot (TYPE); \ | 3435 | 977k | pc_t elsePC = immediate (pc_t); \ | 3436 | 977k | if (operand OPER ((TYPE) _r0)) \ | 3437 | 977k | nextOp (); \ | 3438 | 977k | else jumpOp (elsePC); \ | 3439 | 977k | } \ |
m3_compile.c:op_i32_If_GreaterThanOrEqual_rs Line | Count | Source | 3433 | 1.00M | { \ | 3434 | 1.00M | TYPE operand = slot (TYPE); \ | 3435 | 1.00M | pc_t elsePC = immediate (pc_t); \ | 3436 | 1.00M | if (operand OPER ((TYPE) _r0)) \ | 3437 | 1.00M | nextOp (); \ | 3438 | 1.00M | else jumpOp (elsePC); \ | 3439 | 1.00M | } \ |
m3_compile.c:op_u32_If_GreaterThanOrEqual_rs Line | Count | Source | 3433 | 855k | { \ | 3434 | 855k | TYPE operand = slot (TYPE); \ | 3435 | 855k | pc_t elsePC = immediate (pc_t); \ | 3436 | 855k | if (operand OPER ((TYPE) _r0)) \ | 3437 | 855k | nextOp (); \ | 3438 | 855k | else jumpOp (elsePC); \ | 3439 | 855k | } \ |
|
3440 | | d_m3Op(TYPE##_If_##NAME##_sr) \ |
3441 | 11.0M | { \ |
3442 | 11.0M | TYPE operand = slot (TYPE); \ |
3443 | 11.0M | pc_t elsePC = immediate (pc_t); \ |
3444 | 11.0M | if (((TYPE) _r0) OPER operand) \ |
3445 | 11.0M | nextOp (); \ |
3446 | 11.0M | else jumpOp (elsePC); \ |
3447 | 11.0M | } \ m3_compile.c:op_i32_If_LessThan_sr Line | Count | Source | 3441 | 984k | { \ | 3442 | 984k | TYPE operand = slot (TYPE); \ | 3443 | 984k | pc_t elsePC = immediate (pc_t); \ | 3444 | 984k | if (((TYPE) _r0) OPER operand) \ | 3445 | 984k | nextOp (); \ | 3446 | 984k | else jumpOp (elsePC); \ | 3447 | 984k | } \ |
m3_compile.c:op_u32_If_LessThan_sr Line | Count | Source | 3441 | 1.39M | { \ | 3442 | 1.39M | TYPE operand = slot (TYPE); \ | 3443 | 1.39M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.39M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.39M | nextOp (); \ | 3446 | 1.39M | else jumpOp (elsePC); \ | 3447 | 1.39M | } \ |
m3_compile.c:op_i32_If_GreaterThan_sr Line | Count | Source | 3441 | 1.67M | { \ | 3442 | 1.67M | TYPE operand = slot (TYPE); \ | 3443 | 1.67M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.67M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.67M | nextOp (); \ | 3446 | 1.67M | else jumpOp (elsePC); \ | 3447 | 1.67M | } \ |
m3_compile.c:op_u32_If_GreaterThan_sr Line | Count | Source | 3441 | 1.22M | { \ | 3442 | 1.22M | TYPE operand = slot (TYPE); \ | 3443 | 1.22M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.22M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.22M | nextOp (); \ | 3446 | 1.22M | else jumpOp (elsePC); \ | 3447 | 1.22M | } \ |
m3_compile.c:op_i32_If_LessThanOrEqual_sr Line | Count | Source | 3441 | 1.68M | { \ | 3442 | 1.68M | TYPE operand = slot (TYPE); \ | 3443 | 1.68M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.68M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.68M | nextOp (); \ | 3446 | 1.68M | else jumpOp (elsePC); \ | 3447 | 1.68M | } \ |
m3_compile.c:op_u32_If_LessThanOrEqual_sr Line | Count | Source | 3441 | 1.09M | { \ | 3442 | 1.09M | TYPE operand = slot (TYPE); \ | 3443 | 1.09M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.09M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.09M | nextOp (); \ | 3446 | 1.09M | else jumpOp (elsePC); \ | 3447 | 1.09M | } \ |
m3_compile.c:op_i32_If_GreaterThanOrEqual_sr Line | Count | Source | 3441 | 1.70M | { \ | 3442 | 1.70M | TYPE operand = slot (TYPE); \ | 3443 | 1.70M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.70M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.70M | nextOp (); \ | 3446 | 1.70M | else jumpOp (elsePC); \ | 3447 | 1.70M | } \ |
m3_compile.c:op_u32_If_GreaterThanOrEqual_sr Line | Count | Source | 3441 | 1.29M | { \ | 3442 | 1.29M | TYPE operand = slot (TYPE); \ | 3443 | 1.29M | pc_t elsePC = immediate (pc_t); \ | 3444 | 1.29M | if (((TYPE) _r0) OPER operand) \ | 3445 | 1.29M | nextOp (); \ | 3446 | 1.29M | else jumpOp (elsePC); \ | 3447 | 1.29M | } \ |
Unexecuted instantiation: m3_compile.c:op_i32_If_Equal_sr Unexecuted instantiation: m3_compile.c:op_i32_If_NotEqual_sr |
3448 | | d_m3Op(TYPE##_If_##NAME##_ss) \ |
3449 | 9.03M | { \ |
3450 | 9.03M | TYPE operand2 = slot (TYPE); \ |
3451 | 9.03M | TYPE operand1 = slot (TYPE); \ |
3452 | 9.03M | pc_t elsePC = immediate (pc_t); \ |
3453 | 9.03M | if (operand1 OPER operand2) \ |
3454 | 9.03M | nextOp (); \ |
3455 | 9.03M | else jumpOp (elsePC); \ |
3456 | 9.03M | } m3_compile.c:op_i32_If_Equal_ss Line | Count | Source | 3449 | 630k | { \ | 3450 | 630k | TYPE operand2 = slot (TYPE); \ | 3451 | 630k | TYPE operand1 = slot (TYPE); \ | 3452 | 630k | pc_t elsePC = immediate (pc_t); \ | 3453 | 630k | if (operand1 OPER operand2) \ | 3454 | 630k | nextOp (); \ | 3455 | 630k | else jumpOp (elsePC); \ | 3456 | 630k | } |
m3_compile.c:op_i32_If_NotEqual_ss Line | Count | Source | 3449 | 1.09M | { \ | 3450 | 1.09M | TYPE operand2 = slot (TYPE); \ | 3451 | 1.09M | TYPE operand1 = slot (TYPE); \ | 3452 | 1.09M | pc_t elsePC = immediate (pc_t); \ | 3453 | 1.09M | if (operand1 OPER operand2) \ | 3454 | 1.09M | nextOp (); \ | 3455 | 1.09M | else jumpOp (elsePC); \ | 3456 | 1.09M | } |
m3_compile.c:op_i32_If_LessThan_ss Line | Count | Source | 3449 | 1.05M | { \ | 3450 | 1.05M | TYPE operand2 = slot (TYPE); \ | 3451 | 1.05M | TYPE operand1 = slot (TYPE); \ | 3452 | 1.05M | pc_t elsePC = immediate (pc_t); \ | 3453 | 1.05M | if (operand1 OPER operand2) \ | 3454 | 1.05M | nextOp (); \ | 3455 | 1.05M | else jumpOp (elsePC); \ | 3456 | 1.05M | } |
m3_compile.c:op_u32_If_LessThan_ss Line | Count | Source | 3449 | 1.17M | { \ | 3450 | 1.17M | TYPE operand2 = slot (TYPE); \ | 3451 | 1.17M | TYPE operand1 = slot (TYPE); \ | 3452 | 1.17M | pc_t elsePC = immediate (pc_t); \ | 3453 | 1.17M | if (operand1 OPER operand2) \ | 3454 | 1.17M | nextOp (); \ | 3455 | 1.17M | else jumpOp (elsePC); \ | 3456 | 1.17M | } |
m3_compile.c:op_i32_If_GreaterThan_ss Line | Count | Source | 3449 | 489k | { \ | 3450 | 489k | TYPE operand2 = slot (TYPE); \ | 3451 | 489k | TYPE operand1 = slot (TYPE); \ | 3452 | 489k | pc_t elsePC = immediate (pc_t); \ | 3453 | 489k | if (operand1 OPER operand2) \ | 3454 | 489k | nextOp (); \ | 3455 | 489k | else jumpOp (elsePC); \ | 3456 | 489k | } |
m3_compile.c:op_u32_If_GreaterThan_ss Line | Count | Source | 3449 | 1.27M | { \ | 3450 | 1.27M | TYPE operand2 = slot (TYPE); \ | 3451 | 1.27M | TYPE operand1 = slot (TYPE); \ | 3452 | 1.27M | pc_t elsePC = immediate (pc_t); \ | 3453 | 1.27M | if (operand1 OPER operand2) \ | 3454 | 1.27M | nextOp (); \ | 3455 | 1.27M | else jumpOp (elsePC); \ | 3456 | 1.27M | } |
m3_compile.c:op_i32_If_LessThanOrEqual_ss Line | Count | Source | 3449 | 496k | { \ | 3450 | 496k | TYPE operand2 = slot (TYPE); \ | 3451 | 496k | TYPE operand1 = slot (TYPE); \ | 3452 | 496k | pc_t elsePC = immediate (pc_t); \ | 3453 | 496k | if (operand1 OPER operand2) \ | 3454 | 496k | nextOp (); \ | 3455 | 496k | else jumpOp (elsePC); \ | 3456 | 496k | } |
m3_compile.c:op_u32_If_LessThanOrEqual_ss Line | Count | Source | 3449 | 1.32M | { \ | 3450 | 1.32M | TYPE operand2 = slot (TYPE); \ | 3451 | 1.32M | TYPE operand1 = slot (TYPE); \ | 3452 | 1.32M | pc_t elsePC = immediate (pc_t); \ | 3453 | 1.32M | if (operand1 OPER operand2) \ | 3454 | 1.32M | nextOp (); \ | 3455 | 1.32M | else jumpOp (elsePC); \ | 3456 | 1.32M | } |
m3_compile.c:op_i32_If_GreaterThanOrEqual_ss Line | Count | Source | 3449 | 967k | { \ | 3450 | 967k | TYPE operand2 = slot (TYPE); \ | 3451 | 967k | TYPE operand1 = slot (TYPE); \ | 3452 | 967k | pc_t elsePC = immediate (pc_t); \ | 3453 | 967k | if (operand1 OPER operand2) \ | 3454 | 967k | nextOp (); \ | 3455 | 967k | else jumpOp (elsePC); \ | 3456 | 967k | } |
m3_compile.c:op_u32_If_GreaterThanOrEqual_ss Line | Count | Source | 3449 | 516k | { \ | 3450 | 516k | TYPE operand2 = slot (TYPE); \ | 3451 | 516k | TYPE operand1 = slot (TYPE); \ | 3452 | 516k | pc_t elsePC = immediate (pc_t); \ | 3453 | 516k | if (operand1 OPER operand2) \ | 3454 | 516k | nextOp (); \ | 3455 | 516k | else jumpOp (elsePC); \ | 3456 | 516k | } |
|
3457 | | |
3458 | | d_m3FusedCmpBranch(i32, Equal, ==) |
3459 | | d_m3FusedCmpBranch(i32, NotEqual, !=) |
3460 | | d_m3FusedCmpBranch(i32, LessThan, <) |
3461 | | d_m3FusedCmpBranch(i32, GreaterThan, >) |
3462 | | d_m3FusedCmpBranch(i32, LessThanOrEqual, <=) |
3463 | | d_m3FusedCmpBranch(i32, GreaterThanOrEqual, >=) |
3464 | | d_m3FusedCmpBranch(u32, LessThan, <) |
3465 | | d_m3FusedCmpBranch(u32, GreaterThan, >) |
3466 | | d_m3FusedCmpBranch(u32, LessThanOrEqual, <=) |
3467 | | d_m3FusedCmpBranch(u32, GreaterThanOrEqual, >=) |
3468 | | |
3469 | | // i32.eqz is unary: form _r has the operand in _r0 (no operand immediate), _s reads a slot |
3470 | | d_m3Op(i32_BranchIfEqz_r) |
3471 | 109k | { |
3472 | 109k | pc_t branch = immediate(pc_t); |
3473 | 109k | if (((i32)_r0) == 0) { |
3474 | 55.7k | jumpOp(branch); |
3475 | 55.7k | } else { |
3476 | 53.5k | nextOp(); |
3477 | 53.5k | } |
3478 | 109k | } |
3479 | | |
3480 | | d_m3Op(i32_BranchIfEqz_s) |
3481 | 223k | { |
3482 | 223k | i32 operand = slot(i32); |
3483 | 223k | pc_t branch = immediate(pc_t); |
3484 | 223k | if (operand == 0) { |
3485 | 43.3k | jumpOp(branch); |
3486 | 180k | } else { |
3487 | 180k | nextOp(); |
3488 | 180k | } |
3489 | 223k | } |
3490 | | |
3491 | | d_m3Op(i32_IfEqz_r) |
3492 | 1.18M | { |
3493 | 1.18M | pc_t elsePC = immediate(pc_t); |
3494 | 1.18M | if (((i32)_r0) == 0) { |
3495 | 516k | nextOp(); |
3496 | 668k | } else { |
3497 | 668k | jumpOp(elsePC); |
3498 | 668k | } |
3499 | 1.18M | } |
3500 | | |
3501 | | d_m3Op(i32_IfEqz_s) |
3502 | 606k | { |
3503 | 606k | i32 operand = slot(i32); |
3504 | 606k | pc_t elsePC = immediate(pc_t); |
3505 | 606k | if (operand == 0) { |
3506 | 273k | nextOp(); |
3507 | 333k | } else { |
3508 | 333k | jumpOp(elsePC); |
3509 | 333k | } |
3510 | 606k | } |
3511 | | |
3512 | | #endif // d_m3FuseBranch |
3513 | | |
3514 | | |
3515 | | d_m3Op(BranchIfPrologue_r) |
3516 | 641k | { |
3517 | 641k | i32 condition = (i32)_r0; |
3518 | 641k | pc_t branch = immediate(pc_t); |
3519 | | |
3520 | 641k | if (condition) { |
3521 | | // this is the "prologue" that ends with |
3522 | | // a plain branch to the actual target |
3523 | 322k | nextOp(); |
3524 | 322k | } else { |
3525 | 319k | jumpOp(branch); // jump over the prologue |
3526 | 319k | } |
3527 | 641k | } |
3528 | | |
3529 | | |
3530 | | d_m3Op(BranchIfPrologue_s) |
3531 | 277k | { |
3532 | 277k | i32 condition = slot(i32); |
3533 | 277k | pc_t branch = immediate(pc_t); |
3534 | | |
3535 | 277k | if (condition) { |
3536 | 122k | nextOp(); |
3537 | 155k | } else { |
3538 | 155k | jumpOp(branch); |
3539 | 155k | } |
3540 | 277k | } |
3541 | | |
3542 | | |
3543 | | d_m3Op(ContinueLoop) |
3544 | 2.57M | { |
3545 | 2.57M | m3StackCheck(); |
3546 | | |
3547 | 2.57M | void* loopId = immediate(void*); |
3548 | 2.57M | return loopId; |
3549 | 2.57M | } |
3550 | | |
3551 | | |
3552 | | d_m3Op(ContinueLoopIf) |
3553 | 2.39M | { |
3554 | 2.39M | i32 condition = (i32)_r0; |
3555 | 2.39M | void* loopId = immediate(void*); |
3556 | | |
3557 | 2.39M | if (condition) { |
3558 | 2.07M | return loopId; |
3559 | 2.07M | } else { |
3560 | 316k | nextOp(); |
3561 | 316k | } |
3562 | 2.39M | } |
3563 | | |
3564 | | |
3565 | | #if d_m3HasStackSwitching |
3566 | | |
3567 | | // This is where execution can "escape" the M3 code and callback to the client / fiber switch |
3568 | | // OR it can go in the Loop operation. I think it's best to do here. adding code to the loop operation |
3569 | | // has the potential to increase its native-stack usage. |
3570 | | |
3571 | | d_m3Op(ContinueLoop_Suspendable) |
3572 | 0 | { |
3573 | 0 | m3StackCheck(); |
3574 | |
|
3575 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
3576 | 0 | if (M3_UNLIKELY(runtime->suspendRequested and runtime->activeContinuation)) { |
3577 | 0 | SuspendWithoutTag(runtime, runtime->activeContinuation, safepoint_op, _pc - 1, _sp, |
3578 | 0 | d_m3ExpRegArgs(_r0, _fp0)); |
3579 | |
|
3580 | 0 | return m3Err_continuationSuspended; |
3581 | 0 | } |
3582 | | |
3583 | 0 | void* loopId = immediate(void*); |
3584 | 0 | return loopId; |
3585 | 0 | } |
3586 | | |
3587 | | |
3588 | | # if !d_m3EntryKeepsFrame |
3589 | | // op_Entry, in code compiled while the runtime is suspendable: once the frame is |
3590 | | // set up, it checks for a pause request. Recursion passes one of these on every |
3591 | | // lap, as a loop passes its back edge, so a pause the host requests reaches code |
3592 | | // that has no loop. A pause here stops at the body's first operation, so going |
3593 | | // on from it is going on past the check. |
3594 | | d_m3Op(Entry_Suspendable) |
3595 | 0 | { |
3596 | 0 | d_m3ClearRegisters |
3597 | |
|
3598 | 0 | IM3Function function = immediate(IM3Function); |
3599 | |
|
3600 | 0 | if (EntryFits(function, _sp, _mem)) { |
3601 | 0 | EnterFrame(function, _sp); |
3602 | |
|
3603 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
3604 | 0 | if (M3_UNLIKELY(runtime->suspendRequested and runtime->activeContinuation)) { |
3605 | 0 | SuspendWithoutTag(runtime, runtime->activeContinuation, safepoint_entry, _pc, _sp, |
3606 | 0 | d_m3ExpRegArgs(_r0, _fp0)); |
3607 | |
|
3608 | 0 | return m3Err_continuationSuspended; |
3609 | 0 | } |
3610 | | |
3611 | 0 | nextOpDirect(); |
3612 | 0 | } else { |
3613 | 0 | newTrap(m3Err_trapStackOverflow); |
3614 | 0 | } |
3615 | 0 | } |
3616 | | # endif |
3617 | | |
3618 | | |
3619 | | // The check op_Entry_Suspendable makes, as an operation of its own for the |
3620 | | // builds whose op_Entry keeps a frame and so cannot make it: the start of a |
3621 | | // function's body, in code compiled while the runtime is suspendable |
3622 | | d_m3Op(EntryCheck) |
3623 | 0 | { |
3624 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
3625 | 0 | if (M3_UNLIKELY(runtime->suspendRequested and runtime->activeContinuation)) { |
3626 | 0 | SuspendWithoutTag(runtime, runtime->activeContinuation, safepoint_entry, _pc - 1, _sp, |
3627 | 0 | d_m3ExpRegArgs(_r0, _fp0)); |
3628 | |
|
3629 | 0 | return m3Err_continuationSuspended; |
3630 | 0 | } |
3631 | | |
3632 | 0 | nextOp(); |
3633 | 0 | } |
3634 | | |
3635 | | |
3636 | | d_m3Op(ContinueLoopIf_Suspendable) |
3637 | 0 | { |
3638 | 0 | i32 condition = (i32)_r0; |
3639 | 0 | void* loopId = immediate(void*); |
3640 | |
|
3641 | 0 | if (condition) { |
3642 | 0 | IM3Runtime runtime = m3MemRuntime(_mem); |
3643 | 0 | if (M3_UNLIKELY(runtime->suspendRequested and runtime->activeContinuation)) { |
3644 | 0 | SuspendWithoutTag(runtime, runtime->activeContinuation, safepoint_op, _pc - 2, _sp, |
3645 | 0 | d_m3ExpRegArgs(_r0, _fp0)); |
3646 | |
|
3647 | 0 | return m3Err_continuationSuspended; |
3648 | 0 | } |
3649 | 0 | return loopId; |
3650 | 0 | } else { |
3651 | 0 | nextOp(); |
3652 | 0 | } |
3653 | 0 | } |
3654 | | |
3655 | | |
3656 | | // Carries a resumed back edge or function entry on past the check it paused in |
3657 | | // (see M3Runtime.resumePastCheck), by running the operation the check stands |
3658 | | // in front of: the plain back edge on the same immediates, or whatever follows |
3659 | | // the entry check. |
3660 | | static |
3661 | | m3ret_t ResumePastCheck (IM3Continuation i_cont, M3MemoryHeader* _mem) |
3662 | 0 | { |
3663 | 0 | pc_t check = i_cont->pc; |
3664 | 0 | IM3Operation op = (IM3Operation)(*check); |
3665 | 0 | pc_t _pc = check + 1; |
3666 | 0 | m3stack_t _sp = i_cont->sp; |
3667 | 0 | m3reg_t _r0 = i_cont->r0; |
3668 | 0 | # if d_m3HasFloat |
3669 | 0 | f64 _fp0 = i_cont->fp0; |
3670 | 0 | # endif |
3671 | |
|
3672 | 0 | if (op == op_ContinueLoop_Suspendable) { |
3673 | 0 | op = op_ContinueLoop; |
3674 | 0 | } else if (op == op_ContinueLoopIf_Suspendable) { |
3675 | 0 | op = op_ContinueLoopIf; |
3676 | 0 | } else if (op == op_EntryCheck) { |
3677 | 0 | return nextOpImpl(); |
3678 | 0 | } else { |
3679 | 0 | return d_m3CallWithRegs(check, _sp, _mem, _r0, _fp0); |
3680 | 0 | } |
3681 | | |
3682 | | # if (d_m3EnableOpProfiling || d_m3EnableOpTracing) |
3683 | | return op(_pc, d_m3OpArgs, d_m3BaseCstr); |
3684 | | # else |
3685 | 0 | return op(_pc, d_m3OpArgs); |
3686 | 0 | # endif |
3687 | 0 | } |
3688 | | #endif // d_m3HasStackSwitching |
3689 | | |
3690 | | |
3691 | | d_m3Op(Const32) |
3692 | 2.13M | { |
3693 | 2.13M | u32 value = *(u32*)_pc++; |
3694 | 2.13M | slot(u32) = value; |
3695 | 2.13M | nextOp(); |
3696 | 2.13M | } |
3697 | | |
3698 | | |
3699 | | d_m3Op(Const64) |
3700 | 9.07M | { |
3701 | | // where a pointer is 32 bits the two lines are only 4-byte aligned |
3702 | 9.07M | u64 value; |
3703 | 9.07M | memcpy(&value, _pc, sizeof(value)); |
3704 | 9.07M | _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1; |
3705 | 9.07M | slot(u64) = value; |
3706 | 9.07M | nextOp(); |
3707 | 9.07M | } |
3708 | | |
3709 | | d_m3Op(Unsupported) |
3710 | 0 | { |
3711 | 0 | newTrap(m3Err_trapUnsupportedInstruction); |
3712 | 0 | } |
3713 | | |
3714 | | d_m3Op(Unreachable) |
3715 | 7.75k | { |
3716 | 7.75k | m3StackCheck(); |
3717 | 7.75k | newTrap(m3Err_trapUnreachable); |
3718 | 7.75k | } |
3719 | | |
3720 | | |
3721 | | d_m3Op(End) |
3722 | 0 | { |
3723 | 0 | m3StackCheck(); |
3724 | 0 | return m3Err_none; |
3725 | 0 | } |
3726 | | |
3727 | | |
3728 | | d_m3Op(SetGlobal_s32) |
3729 | 240k | { |
3730 | 240k | u32* global = immediate(u32*); |
3731 | 240k | *global = slot(u32); |
3732 | | |
3733 | 240k | nextOp(); |
3734 | 240k | } |
3735 | | |
3736 | | |
3737 | | d_m3Op(SetGlobal_s64) |
3738 | 66.9k | { |
3739 | 66.9k | u64* global = immediate(u64*); |
3740 | 66.9k | *global = slot(u64); |
3741 | | |
3742 | 66.9k | nextOp(); |
3743 | 66.9k | } |
3744 | | |
3745 | | #if d_m3HasFloat |
3746 | | d_m3Op(SetGlobal_f32) |
3747 | 0 | { |
3748 | 0 | f32* global = immediate(f32*); |
3749 | 0 | *global = (f32)_fp0; |
3750 | |
|
3751 | 0 | nextOp(); |
3752 | 0 | } |
3753 | | |
3754 | | |
3755 | | d_m3Op(SetGlobal_f64) |
3756 | 0 | { |
3757 | 0 | f64* global = immediate(f64*); |
3758 | 0 | *global = _fp0; |
3759 | |
|
3760 | 0 | nextOp(); |
3761 | 0 | } |
3762 | | #endif |
3763 | | |
3764 | | |
3765 | | #if d_m3HasMemory64 |
3766 | | |
3767 | | // Checks a 64-bit address and folds the memarg offset into it, leaving the |
3768 | | // effective address in a slot the access that follows reads as an ordinary |
3769 | | // 32-bit one, with an offset of zero. That keeps one op between a 64-bit |
3770 | | // memory and the whole load/store table, rather than a second copy of it. |
3771 | | // |
3772 | | // The spec computes the effective address as a u65 and traps if it is out of |
3773 | | // range. Here the address is first held against d_m3AddressLimit and the |
3774 | | // compiler has already refused to emit this for an offset above it, so their |
3775 | | // sum is below 2^53 and no wider arithmetic is needed. An address that then |
3776 | | // passes the bounds check is below the memory's length, which no allocator |
3777 | | // lets past 32 bits, so the truncation below is exact. |
3778 | | d_m3Op(CheckAddr64) |
3779 | 4.38M | { |
3780 | 4.38M | u64 operand = slot(u64); |
3781 | 4.38M | u32* address = slot_ptr(u32); |
3782 | | |
3783 | 4.38M | u64 offset; |
3784 | 4.38M | memcpy(&offset, _pc, sizeof(offset)); |
3785 | 4.38M | _pc += (M3_SIZEOF_PTR == 4) ? 2 : 1; |
3786 | | |
3787 | 4.38M | if (M3_LIKELY(operand < d_m3AddressLimit)) { |
3788 | 4.38M | u64 effective = operand + offset; |
3789 | | |
3790 | | // the access itself checks its own size against what is left |
3791 | 4.38M | if (M3_LIKELY(effective < _mem->length)) { |
3792 | 4.38M | *address = (u32)effective; |
3793 | 4.38M | nextOp(); |
3794 | 4.38M | } |
3795 | 4.38M | } |
3796 | | |
3797 | 4.38M | d_outOfBounds; |
3798 | 4.38M | } |
3799 | | |
3800 | | #endif // d_m3HasMemory64 |
3801 | | |
3802 | | |
3803 | | // Under d_m3GuardedMemory there is nothing to check: every address one of these |
3804 | | // operations can name lands inside the memory's reservation, and the part of it the |
3805 | | // memory does not have is not committed, so the access faults and RunCodeChecked |
3806 | | // turns that into the trap the spec asks for. |
3807 | | #if d_m3SkipMemoryBoundsCheck || d_m3GuardedMemory |
3808 | 19.1M | # define m3MemCheck(x) true |
3809 | | #else |
3810 | | # define m3MemCheck(x) M3_LIKELY(x) |
3811 | | #endif |
3812 | | |
3813 | | // memcpy here is to support non-aligned access on some platforms. |
3814 | | |
3815 | | #define d_m3Load(REG,DEST_TYPE,SRC_TYPE) \ |
3816 | 3.92M | d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r) \ |
3817 | 3.92M | { \ |
3818 | 3.92M | d_m3TracePrepare \ |
3819 | 3.92M | u32 offset = immediate (u32); \ |
3820 | 3.92M | d_m3PreloadNext (); \ |
3821 | 3.92M | u64 operand = (u32) _r0; \ |
3822 | 3.92M | operand += offset; \ |
3823 | 3.92M | \ |
3824 | 3.92M | if (m3MemCheck( \ |
3825 | 3.92M | operand + sizeof (SRC_TYPE) <= _mem->length \ |
3826 | 3.92M | )) { \ |
3827 | 3.92M | { \ |
3828 | 3.92M | u8* src8 = m3MemData(_mem) + operand; \ |
3829 | 3.92M | SRC_TYPE value; \ |
3830 | 3.92M | memcpy(&value, src8, sizeof(value)); \ |
3831 | 3.92M | M3_BSWAP_##SRC_TYPE(value); \ |
3832 | 3.92M | REG = (DEST_TYPE)value; \ |
3833 | 3.92M | d_m3TraceLoad(DEST_TYPE, operand, REG); \ |
3834 | 3.92M | } \ |
3835 | 3.92M | nextOpPreloaded (); \ |
3836 | 3.92M | } else d_outOfBounds; \ |
3837 | 3.92M | } \ |
3838 | 6.18M | d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s) \ |
3839 | 6.18M | { \ |
3840 | 6.18M | d_m3TracePrepare \ |
3841 | 6.18M | u64 operand = slot (u32); \ |
3842 | 6.18M | u32 offset = immediate (u32); \ |
3843 | 6.18M | d_m3PreloadNext (); \ |
3844 | 6.18M | operand += offset; \ |
3845 | 6.18M | \ |
3846 | 6.18M | if (m3MemCheck( \ |
3847 | 6.18M | operand + sizeof (SRC_TYPE) <= _mem->length \ |
3848 | 6.18M | )) { \ |
3849 | 6.18M | { \ |
3850 | 6.18M | u8* src8 = m3MemData(_mem) + operand; \ |
3851 | 6.18M | SRC_TYPE value; \ |
3852 | 6.18M | memcpy(&value, src8, sizeof(value)); \ |
3853 | 6.18M | M3_BSWAP_##SRC_TYPE(value); \ |
3854 | 6.18M | REG = (DEST_TYPE)value; \ |
3855 | 6.18M | d_m3TraceLoad(DEST_TYPE, operand, REG); \ |
3856 | 6.18M | } \ |
3857 | 6.18M | nextOpPreloaded (); \ |
3858 | 6.18M | } else d_outOfBounds; \ |
3859 | 6.18M | } |
3860 | | |
3861 | | // printf ("get: %d -> %d\n", operand + offset, (i64) REG); |
3862 | | |
3863 | | |
3864 | | #define d_m3Load_i(DEST_TYPE, SRC_TYPE) d_m3Load(_r0, DEST_TYPE, SRC_TYPE) |
3865 | | #define d_m3Load_f(DEST_TYPE, SRC_TYPE) d_m3Load(_fp0, DEST_TYPE, SRC_TYPE) |
3866 | | |
3867 | | #if d_m3HasFloat |
3868 | 662k | d_m3Load_f(f32, f32); m3_compile.c:op_f32_Load_f32_r Line | Count | Source | 3868 | | d_m3Load_f(f32, f32); |
m3_compile.c:op_f32_Load_f32_s Line | Count | Source | 3868 | | d_m3Load_f(f32, f32); |
|
3869 | 662k | d_m3Load_f(f64, f64); m3_compile.c:op_f64_Load_f64_r Line | Count | Source | 3869 | | d_m3Load_f(f64, f64); |
m3_compile.c:op_f64_Load_f64_s Line | Count | Source | 3869 | | d_m3Load_f(f64, f64); |
|
3870 | 480k | #endif |
3871 | 480k | |
3872 | 882k | d_m3Load_i(i32, i8); m3_compile.c:op_i32_Load_i8_r Line | Count | Source | 3872 | | d_m3Load_i(i32, i8); |
m3_compile.c:op_i32_Load_i8_s Line | Count | Source | 3872 | | d_m3Load_i(i32, i8); |
|
3873 | 882k | d_m3Load_i(i32, u8); m3_compile.c:op_i32_Load_u8_r Line | Count | Source | 3873 | | d_m3Load_i(i32, u8); |
m3_compile.c:op_i32_Load_u8_s Line | Count | Source | 3873 | | d_m3Load_i(i32, u8); |
|
3874 | 877k | d_m3Load_i(i32, i16); m3_compile.c:op_i32_Load_i16_r Line | Count | Source | 3874 | | d_m3Load_i(i32, i16); |
m3_compile.c:op_i32_Load_i16_s Line | Count | Source | 3874 | | d_m3Load_i(i32, i16); |
|
3875 | 877k | d_m3Load_i(i32, u16); m3_compile.c:op_i32_Load_u16_r Line | Count | Source | 3875 | | d_m3Load_i(i32, u16); |
m3_compile.c:op_i32_Load_u16_s Line | Count | Source | 3875 | | d_m3Load_i(i32, u16); |
|
3876 | 856k | d_m3Load_i(i32, i32); m3_compile.c:op_i32_Load_i32_r Line | Count | Source | 3876 | | d_m3Load_i(i32, i32); |
m3_compile.c:op_i32_Load_i32_s Line | Count | Source | 3876 | | d_m3Load_i(i32, i32); |
|
3877 | 521k | |
3878 | 804k | d_m3Load_i(i64, i8); m3_compile.c:op_i64_Load_i8_r Line | Count | Source | 3878 | | d_m3Load_i(i64, i8); |
m3_compile.c:op_i64_Load_i8_s Line | Count | Source | 3878 | | d_m3Load_i(i64, i8); |
|
3879 | 804k | d_m3Load_i(i64, u8); m3_compile.c:op_i64_Load_u8_r Line | Count | Source | 3879 | | d_m3Load_i(i64, u8); |
m3_compile.c:op_i64_Load_u8_s Line | Count | Source | 3879 | | d_m3Load_i(i64, u8); |
|
3880 | 901k | d_m3Load_i(i64, i16); m3_compile.c:op_i64_Load_i16_r Line | Count | Source | 3880 | | d_m3Load_i(i64, i16); |
m3_compile.c:op_i64_Load_i16_s Line | Count | Source | 3880 | | d_m3Load_i(i64, i16); |
|
3881 | 901k | d_m3Load_i(i64, u16); m3_compile.c:op_i64_Load_u16_r Line | Count | Source | 3881 | | d_m3Load_i(i64, u16); |
m3_compile.c:op_i64_Load_u16_s Line | Count | Source | 3881 | | d_m3Load_i(i64, u16); |
|
3882 | 634k | d_m3Load_i(i64, i32); m3_compile.c:op_i64_Load_i32_r Line | Count | Source | 3882 | | d_m3Load_i(i64, i32); |
m3_compile.c:op_i64_Load_i32_s Line | Count | Source | 3882 | | d_m3Load_i(i64, i32); |
|
3883 | 821k | d_m3Load_i(i64, u32); m3_compile.c:op_i64_Load_u32_r Line | Count | Source | 3883 | | d_m3Load_i(i64, u32); |
m3_compile.c:op_i64_Load_u32_s Line | Count | Source | 3883 | | d_m3Load_i(i64, u32); |
|
3884 | 839k | d_m3Load_i(i64, i64); m3_compile.c:op_i64_Load_i64_r Line | Count | Source | 3884 | | d_m3Load_i(i64, i64); |
m3_compile.c:op_i64_Load_i64_s Line | Count | Source | 3884 | | d_m3Load_i(i64, i64); |
|
3885 | 839k | |
3886 | 839k | #if d_m3FoldSetLocal |
3887 | 839k | |
3888 | 839k | // destination-folded loads: the value goes to a trailing destination slot instead of _r0. |
3889 | 839k | // operand immediates keep d_m3Load's order; the destination slot is the last immediate |
3890 | 839k | # define d_m3LoadFold(REG, DEST_TYPE, SRC_TYPE) \ |
3891 | 839k | d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_r_f) \ |
3892 | 1.73M | { \ |
3893 | 1.73M | d_m3TracePrepare \ |
3894 | 1.73M | u32 offset = immediate (u32); \ |
3895 | 1.73M | DEST_TYPE * dest = slot_ptr (DEST_TYPE); \ |
3896 | 1.73M | d_m3PreloadNext (); \ |
3897 | 1.73M | u64 operand = (u32) _r0; \ |
3898 | 1.73M | operand += offset; \ |
3899 | 1.73M | \ |
3900 | 1.73M | if (m3MemCheck( \ |
3901 | 1.73M | operand + sizeof (SRC_TYPE) <= _mem->length \ |
3902 | 1.73M | )) { \ |
3903 | 1.73M | u8* src8 = m3MemData(_mem) + operand; \ |
3904 | 1.73M | SRC_TYPE value; \ |
3905 | 1.73M | memcpy(&value, src8, sizeof(value)); \ |
3906 | 1.73M | M3_BSWAP_##SRC_TYPE(value); \ |
3907 | 1.73M | DEST_TYPE result = (DEST_TYPE)value; \ |
3908 | 1.73M | * dest = result; REG = result; \ |
3909 | 1.73M | d_m3TraceLoad(DEST_TYPE, operand, result); \ |
3910 | 1.73M | nextOpPreloaded (); \ |
3911 | 1.73M | } else d_outOfBounds; \ |
3912 | 1.73M | } \ |
3913 | | d_m3Op(DEST_TYPE##_Load_##SRC_TYPE##_s_f) \ |
3914 | 2.61M | { \ |
3915 | 2.61M | d_m3TracePrepare \ |
3916 | 2.61M | u64 operand = slot (u32); \ |
3917 | 2.61M | u32 offset = immediate (u32); \ |
3918 | 2.61M | DEST_TYPE * dest = slot_ptr (DEST_TYPE); \ |
3919 | 2.61M | d_m3PreloadNext (); \ |
3920 | 2.61M | operand += offset; \ |
3921 | 2.61M | \ |
3922 | 2.61M | if (m3MemCheck( \ |
3923 | 2.61M | operand + sizeof (SRC_TYPE) <= _mem->length \ |
3924 | 2.61M | )) { \ |
3925 | 2.61M | u8* src8 = m3MemData(_mem) + operand; \ |
3926 | 2.61M | SRC_TYPE value; \ |
3927 | 2.61M | memcpy(&value, src8, sizeof(value)); \ |
3928 | 2.61M | M3_BSWAP_##SRC_TYPE(value); \ |
3929 | 2.61M | DEST_TYPE result = (DEST_TYPE)value; \ |
3930 | 2.61M | * dest = result; REG = result; \ |
3931 | 2.61M | d_m3TraceLoad(DEST_TYPE, operand, result); \ |
3932 | 2.61M | nextOpPreloaded (); \ |
3933 | 2.61M | } else d_outOfBounds; \ |
3934 | 2.61M | } |
3935 | | |
3936 | 473k | d_m3LoadFold(_r0, i32, i8) m3_compile.c:op_i32_Load_i8_r_f Line | Count | Source | 3936 | | d_m3LoadFold(_r0, i32, i8) |
m3_compile.c:op_i32_Load_i8_s_f Line | Count | Source | 3936 | | d_m3LoadFold(_r0, i32, i8) |
|
3937 | 347k | d_m3LoadFold(_r0, i32, u8) m3_compile.c:op_i32_Load_u8_r_f Line | Count | Source | 3937 | | d_m3LoadFold(_r0, i32, u8) |
m3_compile.c:op_i32_Load_u8_s_f Line | Count | Source | 3937 | | d_m3LoadFold(_r0, i32, u8) |
|
3938 | 338k | d_m3LoadFold(_r0, i32, i16) m3_compile.c:op_i32_Load_i16_r_f Line | Count | Source | 3938 | | d_m3LoadFold(_r0, i32, i16) |
m3_compile.c:op_i32_Load_i16_s_f Line | Count | Source | 3938 | | d_m3LoadFold(_r0, i32, i16) |
|
3939 | 352k | d_m3LoadFold(_r0, i32, u16) m3_compile.c:op_i32_Load_u16_r_f Line | Count | Source | 3939 | | d_m3LoadFold(_r0, i32, u16) |
m3_compile.c:op_i32_Load_u16_s_f Line | Count | Source | 3939 | | d_m3LoadFold(_r0, i32, u16) |
|
3940 | 254k | d_m3LoadFold(_r0, i32, i32) m3_compile.c:op_i32_Load_i32_r_f Line | Count | Source | 3940 | | d_m3LoadFold(_r0, i32, i32) |
m3_compile.c:op_i32_Load_i32_s_f Line | Count | Source | 3940 | | d_m3LoadFold(_r0, i32, i32) |
|
3941 | | |
3942 | | // The fold forms take the address from _r0 and write the result straight to the |
3943 | | // destination slot, so they never touch _fp0 and the float widths need no register form. |
3944 | 314k | d_m3LoadFold(_r0, i64, i8) m3_compile.c:op_i64_Load_i8_r_f Line | Count | Source | 3944 | | d_m3LoadFold(_r0, i64, i8) |
m3_compile.c:op_i64_Load_i8_s_f Line | Count | Source | 3944 | | d_m3LoadFold(_r0, i64, i8) |
|
3945 | 270k | d_m3LoadFold(_r0, i64, u8) m3_compile.c:op_i64_Load_u8_r_f Line | Count | Source | 3945 | | d_m3LoadFold(_r0, i64, u8) |
m3_compile.c:op_i64_Load_u8_s_f Line | Count | Source | 3945 | | d_m3LoadFold(_r0, i64, u8) |
|
3946 | 421k | d_m3LoadFold(_r0, i64, i16) m3_compile.c:op_i64_Load_i16_r_f Line | Count | Source | 3946 | | d_m3LoadFold(_r0, i64, i16) |
m3_compile.c:op_i64_Load_i16_s_f Line | Count | Source | 3946 | | d_m3LoadFold(_r0, i64, i16) |
|
3947 | 282k | d_m3LoadFold(_r0, i64, u16) m3_compile.c:op_i64_Load_u16_r_f Line | Count | Source | 3947 | | d_m3LoadFold(_r0, i64, u16) |
m3_compile.c:op_i64_Load_u16_s_f Line | Count | Source | 3947 | | d_m3LoadFold(_r0, i64, u16) |
|
3948 | 450k | d_m3LoadFold(_r0, i64, i32) m3_compile.c:op_i64_Load_i32_r_f Line | Count | Source | 3948 | | d_m3LoadFold(_r0, i64, i32) |
m3_compile.c:op_i64_Load_i32_s_f Line | Count | Source | 3948 | | d_m3LoadFold(_r0, i64, i32) |
|
3949 | 322k | d_m3LoadFold(_r0, i64, u32) m3_compile.c:op_i64_Load_u32_r_f Line | Count | Source | 3949 | | d_m3LoadFold(_r0, i64, u32) |
m3_compile.c:op_i64_Load_u32_s_f Line | Count | Source | 3949 | | d_m3LoadFold(_r0, i64, u32) |
|
3950 | 202k | d_m3LoadFold(_r0, i64, i64) m3_compile.c:op_i64_Load_i64_r_f Line | Count | Source | 3950 | | d_m3LoadFold(_r0, i64, i64) |
m3_compile.c:op_i64_Load_i64_s_f Line | Count | Source | 3950 | | d_m3LoadFold(_r0, i64, i64) |
|
3951 | | # if d_m3HasFloat |
3952 | 209k | d_m3LoadFold(_fp0, f32, f32) m3_compile.c:op_f32_Load_f32_r_f Line | Count | Source | 3952 | | d_m3LoadFold(_fp0, f32, f32) |
m3_compile.c:op_f32_Load_f32_s_f Line | Count | Source | 3952 | | d_m3LoadFold(_fp0, f32, f32) |
|
3953 | 101k | d_m3LoadFold(_fp0, f64, f64) m3_compile.c:op_f64_Load_f64_r_f Line | Count | Source | 3953 | | d_m3LoadFold(_fp0, f64, f64) |
m3_compile.c:op_f64_Load_f64_s_f Line | Count | Source | 3953 | | d_m3LoadFold(_fp0, f64, f64) |
|
3954 | | # endif |
3955 | | |
3956 | | #endif // d_m3FoldSetLocal |
3957 | | |
3958 | | #define d_m3Store(REG, SRC_TYPE, DEST_TYPE) \ |
3959 | 1.31M | d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_rs) \ |
3960 | 1.31M | { \ |
3961 | 1.31M | d_m3TracePrepare \ |
3962 | 1.31M | u64 operand = slot (u32); \ |
3963 | 1.31M | u32 offset = immediate (u32); \ |
3964 | 1.31M | d_m3PreloadNext (); \ |
3965 | 1.31M | operand += offset; \ |
3966 | 1.31M | \ |
3967 | 1.31M | if (m3MemCheck( \ |
3968 | 1.31M | operand + sizeof (DEST_TYPE) <= _mem->length \ |
3969 | 1.31M | )) { \ |
3970 | 1.31M | { \ |
3971 | 1.31M | d_m3TraceStore(SRC_TYPE, operand, REG); \ |
3972 | 1.31M | u8* mem8 = m3MemData(_mem) + operand; \ |
3973 | 1.31M | DEST_TYPE val = (DEST_TYPE) REG; \ |
3974 | 1.31M | M3_BSWAP_##DEST_TYPE(val); \ |
3975 | 1.31M | memcpy(mem8, &val, sizeof(val)); \ |
3976 | 1.31M | } \ |
3977 | 1.31M | nextOpPreloaded (); \ |
3978 | 1.31M | } else d_outOfBounds; \ |
3979 | 1.31M | } \ |
3980 | 978k | d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_sr) \ |
3981 | 978k | { \ |
3982 | 978k | d_m3TracePrepare \ |
3983 | 978k | const SRC_TYPE value = slot (SRC_TYPE); \ |
3984 | 978k | u64 operand = (u32) _r0; \ |
3985 | 978k | u32 offset = immediate (u32); \ |
3986 | 978k | d_m3PreloadNext (); \ |
3987 | 978k | operand += offset; \ |
3988 | 978k | \ |
3989 | 978k | if (m3MemCheck( \ |
3990 | 978k | operand + sizeof (DEST_TYPE) <= _mem->length \ |
3991 | 978k | )) { \ |
3992 | 978k | { \ |
3993 | 978k | d_m3TraceStore(SRC_TYPE, operand, value); \ |
3994 | 978k | u8* mem8 = m3MemData(_mem) + operand; \ |
3995 | 978k | DEST_TYPE val = (DEST_TYPE) value; \ |
3996 | 978k | M3_BSWAP_##DEST_TYPE(val); \ |
3997 | 978k | memcpy(mem8, &val, sizeof(val)); \ |
3998 | 978k | } \ |
3999 | 978k | nextOpPreloaded (); \ |
4000 | 978k | } else d_outOfBounds; \ |
4001 | 978k | } \ |
4002 | 856k | d_m3Op (SRC_TYPE##_Store_##DEST_TYPE##_ss) \ |
4003 | 856k | { \ |
4004 | 856k | d_m3TracePrepare \ |
4005 | 856k | const SRC_TYPE value = slot (SRC_TYPE); \ |
4006 | 856k | u64 operand = slot (u32); \ |
4007 | 856k | u32 offset = immediate (u32); \ |
4008 | 856k | d_m3PreloadNext (); \ |
4009 | 856k | operand += offset; \ |
4010 | 856k | \ |
4011 | 856k | if (m3MemCheck( \ |
4012 | 856k | operand + sizeof (DEST_TYPE) <= _mem->length \ |
4013 | 856k | )) { \ |
4014 | 856k | { \ |
4015 | 856k | d_m3TraceStore(SRC_TYPE, operand, value); \ |
4016 | 856k | u8* mem8 = m3MemData(_mem) + operand; \ |
4017 | 856k | DEST_TYPE val = (DEST_TYPE) value; \ |
4018 | 856k | M3_BSWAP_##DEST_TYPE(val); \ |
4019 | 856k | memcpy(mem8, &val, sizeof(val)); \ |
4020 | 856k | } \ |
4021 | 856k | nextOpPreloaded (); \ |
4022 | 856k | } else d_outOfBounds; \ |
4023 | 856k | } |
4024 | | |
4025 | | // both operands can be in regs when storing a float |
4026 | | #define d_m3StoreFp(REG, TYPE) \ |
4027 | 68.9k | d_m3Op (TYPE##_Store_##TYPE##_rr) \ |
4028 | 68.9k | { \ |
4029 | 68.9k | d_m3TracePrepare \ |
4030 | 68.9k | u64 operand = (u32) _r0; \ |
4031 | 68.9k | u32 offset = immediate (u32); \ |
4032 | 68.9k | d_m3PreloadNext (); \ |
4033 | 68.9k | operand += offset; \ |
4034 | 68.9k | \ |
4035 | 68.9k | if (m3MemCheck( \ |
4036 | 68.9k | operand + sizeof (TYPE) <= _mem->length \ |
4037 | 68.9k | )) { \ |
4038 | 68.9k | { \ |
4039 | 68.9k | d_m3TraceStore(TYPE, operand, REG); \ |
4040 | 68.9k | u8* mem8 = m3MemData(_mem) + operand; \ |
4041 | 68.9k | TYPE val = (TYPE) REG; \ |
4042 | 68.9k | M3_BSWAP_##TYPE(val); \ |
4043 | 68.9k | memcpy(mem8, &val, sizeof(val)); \ |
4044 | 68.9k | } \ |
4045 | 68.9k | nextOpPreloaded (); \ |
4046 | 68.9k | } else d_outOfBounds; \ |
4047 | 68.9k | } |
4048 | | |
4049 | | |
4050 | | #define d_m3Store_i(SRC_TYPE, DEST_TYPE) d_m3Store(_r0, SRC_TYPE, DEST_TYPE) |
4051 | | #define d_m3Store_f(SRC_TYPE, DEST_TYPE) d_m3Store(_fp0, SRC_TYPE, DEST_TYPE) d_m3StoreFp (_fp0, SRC_TYPE); |
4052 | | |
4053 | | #if d_m3HasFloat |
4054 | 385k | d_m3Store_f(f32, f32) m3_compile.c:op_f32_Store_f32_rs Line | Count | Source | 4054 | | d_m3Store_f(f32, f32) |
m3_compile.c:op_f32_Store_f32_sr Line | Count | Source | 4054 | | d_m3Store_f(f32, f32) |
m3_compile.c:op_f32_Store_f32_ss Line | Count | Source | 4054 | | d_m3Store_f(f32, f32) |
m3_compile.c:op_f32_Store_f32_rr Line | Count | Source | 4054 | | d_m3Store_f(f32, f32) |
|
4055 | 385k | d_m3Store_f(f64, f64) m3_compile.c:op_f64_Store_f64_rs Line | Count | Source | 4055 | | d_m3Store_f(f64, f64) |
m3_compile.c:op_f64_Store_f64_sr Line | Count | Source | 4055 | | d_m3Store_f(f64, f64) |
m3_compile.c:op_f64_Store_f64_ss Line | Count | Source | 4055 | | d_m3Store_f(f64, f64) |
m3_compile.c:op_f64_Store_f64_rr Line | Count | Source | 4055 | | d_m3Store_f(f64, f64) |
|
4056 | 219k | #endif |
4057 | 219k | |
4058 | 325k | d_m3Store_i(i32, u8) m3_compile.c:op_i32_Store_u8_rs Line | Count | Source | 4058 | | d_m3Store_i(i32, u8) |
m3_compile.c:op_i32_Store_u8_sr Line | Count | Source | 4058 | | d_m3Store_i(i32, u8) |
m3_compile.c:op_i32_Store_u8_ss Line | Count | Source | 4058 | | d_m3Store_i(i32, u8) |
|
4059 | 424k | d_m3Store_i(i32, i16) m3_compile.c:op_i32_Store_i16_rs Line | Count | Source | 4059 | | d_m3Store_i(i32, i16) |
m3_compile.c:op_i32_Store_i16_sr Line | Count | Source | 4059 | | d_m3Store_i(i32, i16) |
m3_compile.c:op_i32_Store_i16_ss Line | Count | Source | 4059 | | d_m3Store_i(i32, i16) |
|
4060 | 733k | d_m3Store_i(i32, i32) m3_compile.c:op_i32_Store_i32_rs Line | Count | Source | 4060 | | d_m3Store_i(i32, i32) |
m3_compile.c:op_i32_Store_i32_sr Line | Count | Source | 4060 | | d_m3Store_i(i32, i32) |
m3_compile.c:op_i32_Store_i32_ss Line | Count | Source | 4060 | | d_m3Store_i(i32, i32) |
|
4061 | 733k | |
4062 | 733k | d_m3Store_i(i64, u8) m3_compile.c:op_i64_Store_u8_rs Line | Count | Source | 4062 | | d_m3Store_i(i64, u8) |
m3_compile.c:op_i64_Store_u8_sr Line | Count | Source | 4062 | | d_m3Store_i(i64, u8) |
m3_compile.c:op_i64_Store_u8_ss Line | Count | Source | 4062 | | d_m3Store_i(i64, u8) |
|
4063 | 309k | d_m3Store_i(i64, i16) m3_compile.c:op_i64_Store_i16_rs Line | Count | Source | 4063 | | d_m3Store_i(i64, i16) |
m3_compile.c:op_i64_Store_i16_sr Line | Count | Source | 4063 | | d_m3Store_i(i64, i16) |
m3_compile.c:op_i64_Store_i16_ss Line | Count | Source | 4063 | | d_m3Store_i(i64, i16) |
|
4064 | 253k | d_m3Store_i(i64, i32) m3_compile.c:op_i64_Store_i32_rs Line | Count | Source | 4064 | | d_m3Store_i(i64, i32) |
m3_compile.c:op_i64_Store_i32_sr Line | Count | Source | 4064 | | d_m3Store_i(i64, i32) |
m3_compile.c:op_i64_Store_i32_ss Line | Count | Source | 4064 | | d_m3Store_i(i64, i32) |
|
4065 | | d_m3Store_i(i64, i64) m3_compile.c:op_i64_Store_i64_rs Line | Count | Source | 4065 | | d_m3Store_i(i64, i64) |
m3_compile.c:op_i64_Store_i64_sr Line | Count | Source | 4065 | | d_m3Store_i(i64, i64) |
m3_compile.c:op_i64_Store_i64_ss Line | Count | Source | 4065 | | d_m3Store_i(i64, i64) |
|
4066 | | |
4067 | | #include "m3_exec_atomic.h" |
4068 | | |
4069 | | #undef m3MemCheck |
4070 | | |
4071 | | |
4072 | | //--------------------------------------------------------------------------------------------------------------------- |
4073 | | // debug/profiling |
4074 | | //--------------------------------------------------------------------------------------------------------------------- |
4075 | | #if d_m3EnableOpTracing |
4076 | | d_m3RetSig debugOp (d_m3OpSig, cstr_t i_opcode) |
4077 | | { |
4078 | | char name[100]; |
4079 | | strcpy(name, strstr(i_opcode, "op_") + 3); |
4080 | | char* bracket = strstr(name, "("); |
4081 | | if (bracket) { |
4082 | | *bracket = 0; |
4083 | | } |
4084 | | |
4085 | | puts(name); |
4086 | | nextOpDirect(); |
4087 | | } |
4088 | | #endif |
4089 | | |
4090 | | #if d_m3EnableOpProfiling |
4091 | | d_m3RetSig profileOp (d_m3OpSig, cstr_t i_operationName) |
4092 | | { |
4093 | | ProfileHit(i_operationName); |
4094 | | |
4095 | | nextOpDirect(); |
4096 | | } |
4097 | | |
4098 | | // Same, for an operation leaving by a branch: jumpOp hands the target pc in as _pc, |
4099 | | // so dispatching from here lands exactly where jumpOpDirect would have. |
4100 | | d_m3RetSig profileJumpOp (d_m3OpSig, cstr_t i_operationName) |
4101 | | { |
4102 | | ProfileHit(i_operationName); |
4103 | | |
4104 | | nextOpDirect(); |
4105 | | } |
4106 | | #endif |
4107 | | |
4108 | | d_m3EndExternC |
4109 | | |
4110 | | #endif // m3_exec_h |