Coverage Report

Created: 2018-06-21 18:56

/home/travis/build/MoarVM/MoarVM/src/jit/x64/emit.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
** This file has been pre-processed with DynASM.
3
** http://luajit.org/dynasm.html
4
** DynASM version 1.3.0, DynASM x64 version 1.3.0
5
** DO NOT EDIT! The original file is in "src/jit/x64/emit.dasc".
6
*/
7
8
#line 1 "src/jit/x64/emit.dasc"
9
/* -*-C-*- */
10
#include "moar.h"
11
#include "jit/internal.h"
12
#include "dasm_x86.h"
13
14
#ifdef _MSC_VER
15
#pragma warning( disable : 4129 )
16
#endif
17
18
/**
19
 * CONVENTIONS
20
21
 * Much of this file contains snippets of assembly code, which are concatenated
22
 * at runtime in order to form a single executable routine. It is essential for
23
 * the correctness of the result that each of the snippets behaves
24
 * nicely. Because you can't be expected to know what that is, it is documented
25
 * here.
26
27
 * REGISTERS:
28
29
 * Register and calling conventions differ between POSIX and windows
30
 * systems. The registers rax, rcx, rdx, r8, r9, r10 and r11 are caller-saved,
31
 * meaning that you are free to overwrrite them, and functions you may call are
32
 * free to do thesame. Hence you should save their values on stack, if you wish
33
 * to keep them after calling. In contrast, rbx, rsp, rbp, and r12-r15 are
34
 * callee-saved, meaning that their values before entering and after returning
35
 * from a function must be the same. POSIX also makes rdi and rsi caller-saved,
36
 * windows makes them callee-saved. For this reason we avoid using them.  The
37
 * first 4 (windows) or 6 (POSIX) function call arguments are placed in
38
 * registers. These registers sets are not the same between windows and POSIX,
39
 * but they're always caller-saved.
40
41
 * To deal with the ambiguity, register names have been aliased.
42
43
 * + RV stands for 'return value', and is aliased to rax
44
 * + TMP1-6 are the 6 shared caller-saved registers
45
 * + ARG1-4 are (different) aliases for argument registers
46
 * + TC, CU, WORK are registers that hold interpreter variables; these are callee-
47
 *   saved registers set up at entry and restored at exit
48
 * + TMP5 (r10) is also aliased as FUNCTION; it never conflicts with an argument
49
 *   register, and neither does TMP6.
50
 * + The suffixes d, w, and b stand for the 4, 2, and 1 byte-width value of the
51
 *   registers.
52
53
 * Note that the current convention for function calls is to load the function
54
 * pointer as a 64 bit value in a register from the machine code, and call on
55
 * that register. This is not ideal, but call doesn't natively take 64 bit
56
 * values, and it is neccesary to ensure that the function lives within 32 bits
57
 * distance from the function otherwise. Other methods are being considered.
58
59
 * LABELS:
60
61
 * Don't use dynamic labels in this code, unless they have been passed to you
62
 * from outside. Dynamic labels need to be allocated and not conflict, hence
63
 * just picking one is typically unsafe. Local labels are usually safe.
64
65
 * WRITE BARRIERS:
66
67
 * Use of write barriers is tricky, because they may involve a function call, and
68
 * that may or may not mean you have to store your temporaries on the stack.
69
 * Hence, a write barrier (MVM_ASSIGN_REF) is split into two parts:
70
71
 * + check_wb (root, value, label)
72
 * + hit_wb (root)
73
74
 * You should have the label parameter point somewhere after hit_wb, and save
75
 * and restore your temporaries around the hib_wb.
76
 **/
77
78
79
//|.arch x64
80
#if DASM_VERSION != 10300
81
#error "Version mismatch between DynASM and included encoding engine"
82
#endif
83
#line 72 "src/jit/x64/emit.dasc"
84
//|.actionlist actions
85
static const unsigned char actions[4963] = {
86
  254,0,85,72,137,229,255,72,129,250,236,0,1,0,0,255,76,137,117,250,248,76,
87
  137,109,250,240,72,137,93,250,232,255,73,137,250,254,73,137,250,245,77,139,
88
  158,231,73,139,155,231,255,72,141,68,36,250,248,73,137,134,231,255,250,255,
89
  226,255,246,10,255,73,199,134,231,0,0,0,0,255,76,139,117,250,248,76,139,109,
90
  250,240,72,139,93,250,232,255,72,137,250,236,93,195,255,72,185,235,235,72,
91
  137,139,231,255,72,199,131,231,235,255,73,139,141,231,72,139,137,231,72,137,
92
  139,231,255,73,139,142,231,72,139,137,231,72,137,139,231,255,72,139,139,231,
93
  72,139,137,231,255,72,139,137,231,73,139,150,231,72,139,146,231,72,133,201,
94
  72,15,68,202,255,77,139,158,231,255,77,139,155,231,255,77,139,147,231,255,
95
  77,139,146,231,255,77,133,210,15,133,242,247,255,76,137,250,247,76,137,222,
96
  72,199,194,235,254,1,246,5,235,235,254,0,250,255,21,242,5,255,73,137,194,
97
  246,1,255,76,137,147,231,255,76,139,155,231,77,139,155,231,255,76,137,250,
98
  247,255,73,139,181,231,72,139,182,231,72,199,194,235,254,1,250,255,21,242,
99
  5,72,133,192,15,132,242,247,72,139,0,72,137,131,231,250,233,242,248,246,1,
100
  77,139,134,231,77,139,128,231,76,137,131,231,246,2,255,73,139,142,231,255,
101
  72,139,145,231,76,139,131,231,76,137,130,231,255,102,250,247,129,231,234,
102
  15,132,242,248,77,133,192,15,132,242,248,102,65,250,247,128,231,234,15,133,
103
  242,248,72,137,206,76,137,250,247,254,1,250,255,21,242,5,246,2,255,73,139,
104
  142,231,72,139,137,231,72,139,137,231,72,137,139,231,255,72,139,139,231,72,
105
  141,145,231,76,139,137,231,77,141,145,231,77,133,201,73,15,69,210,255,76,
106
  139,2,77,133,192,255,15,133,242,249,255,77,139,134,231,77,139,128,231,246,
107
  3,255,76,139,2,255,77,133,192,15,133,242,250,255,77,139,134,231,77,139,128,
108
  231,77,139,128,231,255,102,250,247,129,231,234,15,132,242,249,77,133,192,
109
  15,132,242,249,102,65,250,247,128,231,234,15,133,242,249,72,137,85,216,76,
110
  137,69,208,72,139,179,231,76,137,250,247,254,1,250,255,21,242,5,76,139,69,
111
  208,72,139,85,216,246,3,255,76,137,2,246,4,255,76,139,2,77,133,192,15,133,
112
  242,250,255,76,137,250,247,73,139,182,231,72,139,182,231,72,139,182,231,254,
113
  1,250,255,21,242,5,73,137,192,255,250,255,21,242,5,76,139,69,208,72,139,85,
114
  216,246,3,76,137,2,255,76,137,131,231,255,72,139,139,231,72,139,147,231,255,
115
  102,250,247,129,231,234,15,132,242,248,72,133,210,15,132,242,248,102,250,
116
  247,130,231,234,15,133,242,248,255,250,255,21,242,5,72,139,139,231,72,139,
117
  147,231,246,2,255,72,137,145,231,255,72,139,139,231,72,139,145,231,72,137,
118
  147,231,255,72,139,139,231,72,139,147,231,72,139,137,231,72,137,17,255,72,
119
  139,139,231,76,139,129,231,73,139,16,72,137,147,231,255,72,139,139,231,72,
120
  139,147,231,76,141,129,231,73,131,184,231,0,15,132,242,247,77,139,128,231,
121
  246,1,255,102,250,247,129,231,234,15,132,242,248,72,133,210,15,132,242,248,
122
  102,250,247,130,231,234,15,133,242,248,72,137,85,216,76,137,69,208,72,139,
123
  179,231,76,137,250,247,254,1,250,255,21,242,5,76,139,69,208,72,139,85,216,
124
  246,2,255,73,137,144,231,255,72,139,139,231,72,137,139,231,255,72,139,139,
125
  231,73,137,142,231,255,73,139,142,231,72,131,250,249,0,15,132,242,248,73,
126
  139,150,231,72,131,250,250,0,15,132,242,247,77,139,134,231,77,139,128,231,
127
  76,57,194,15,133,242,248,246,1,72,137,139,231,73,199,134,231,235,250,233,
128
  242,249,246,2,73,139,142,231,72,139,137,231,72,137,139,231,246,3,255,76,137,
129
  250,247,73,139,182,231,254,1,250,255,21,242,5,72,137,131,231,255,72,139,139,
130
  231,102,250,247,129,231,234,15,133,242,247,72,139,145,231,72,139,146,231,
131
  129,186,231,237,15,132,242,248,246,1,76,137,250,247,72,190,235,235,254,1,
132
  250,255,21,242,5,246,2,72,137,139,231,255,73,139,142,231,72,139,137,231,72,
133
  133,201,15,132,242,247,72,139,137,231,246,1,72,137,139,231,255,73,139,141,
134
  231,255,72,199,131,231,0,0,0,0,255,72,139,139,231,72,133,201,15,148,210,72,
135
  15,182,210,72,137,147,231,255,76,139,147,231,102,65,250,247,130,231,234,15,
136
  133,242,247,77,139,154,231,77,139,155,231,65,129,187,231,237,15,133,242,247,
137
  76,137,250,247,73,139,178,231,72,139,147,231,254,1,250,255,21,242,5,72,137,
138
  131,231,250,233,242,248,246,1,76,137,250,247,72,190,235,235,254,1,72,129,
139
  131,231,237,255,72,129,171,231,237,255,72,129,139,231,237,255,72,129,163,
140
  231,237,255,72,129,179,231,237,255,72,139,131,231,255,72,1,131,231,255,72,
141
  41,131,231,255,72,9,131,231,255,72,33,131,231,255,72,49,131,231,255,72,129,
142
  192,237,255,72,129,250,232,237,255,72,129,200,237,255,72,129,224,237,255,
143
  72,129,250,240,237,255,72,3,131,231,255,72,43,131,231,255,72,11,131,231,255,
144
  72,35,131,231,255,72,51,131,231,255,72,15,175,131,231,255,138,139,231,72,
145
  211,224,255,138,139,231,72,211,250,232,255,72,49,192,72,139,139,231,72,57,
146
  193,15,140,242,249,72,250,255,192,76,139,131,231,246,1,72,250,247,193,1,0,
147
  0,0,15,132,242,248,73,250,247,250,232,246,2,77,15,175,192,72,209,250,233,
148
  15,133,242,1,246,3,72,137,131,231,255,72,139,131,231,72,139,139,231,72,131,
149
  250,249,0,15,133,242,247,76,137,250,247,72,190,235,235,254,1,250,255,21,242,
150
  5,246,1,255,15,156,214,72,131,250,248,0,15,156,210,48,250,242,68,15,182,194,
151
  72,153,72,250,247,250,249,72,133,210,15,149,209,65,32,200,255,76,41,192,72,
152
  137,131,231,255,250,255,21,242,5,246,1,72,153,72,250,247,250,249,72,137,147,
153
  231,255,72,131,131,231,1,255,72,131,171,231,1,255,72,139,139,231,72,250,247,
154
  209,72,137,139,231,255,72,139,139,231,72,250,247,217,72,137,139,231,255,72,
155
  139,131,231,72,152,72,137,131,231,255,72,139,139,231,255,102,137,202,72,137,
156
  147,231,255,250,242,15,16,131,231,255,250,242,15,88,131,231,255,250,242,15,
157
  92,131,231,255,250,242,15,89,131,231,255,250,242,15,94,131,231,255,250,242,
158
  15,17,131,231,255,250,242,72,15,42,131,231,250,242,15,17,131,231,255,250,
159
  242,72,15,44,131,231,72,137,131,231,255,72,199,193,1,0,0,0,72,193,225,63,
160
  72,139,147,231,72,49,202,72,137,147,231,255,72,59,131,231,255,15,148,208,
161
  255,15,149,208,255,15,156,208,255,15,158,208,255,15,159,208,255,15,157,208,
162
  255,72,15,182,192,72,137,131,231,255,72,59,139,231,255,15,159,210,72,15,182,
163
  210,65,15,156,208,77,15,182,192,76,41,194,72,137,147,231,255,72,199,194,1,
164
  0,0,0,255,72,199,194,250,255,250,255,250,255,250,255,255,72,199,194,0,0,0,
165
  0,255,72,59,147,231,255,72,199,193,0,0,0,0,255,72,199,193,1,0,0,0,255,250,
166
  242,15,16,131,231,102,15,46,131,231,255,15,147,209,255,15,155,210,72,15,68,
167
  202,255,15,154,210,72,15,68,202,255,15,151,209,255,72,15,182,201,72,137,139,
168
  231,255,250,242,15,16,131,231,250,242,15,16,139,231,102,15,46,193,15,151,
169
  209,72,15,182,193,102,15,46,200,15,151,209,72,15,182,201,72,41,200,72,137,
170
  131,231,255,72,199,199,235,72,139,179,231,72,139,147,231,254,1,72,129,250,
171
  248,237,15,148,208,255,72,129,250,248,237,15,149,208,255,72,139,139,231,72,
172
  133,201,15,132,242,247,72,139,137,231,72,139,137,231,72,129,185,231,237,15,
173
  133,242,247,72,199,131,231,1,0,0,0,250,233,242,248,246,1,72,199,131,231,0,
174
  0,0,0,246,2,255,72,139,139,231,72,139,145,231,72,131,194,1,76,139,129,231,
175
  255,76,57,194,15,156,209,72,15,182,201,72,137,139,231,255,72,139,139,231,
176
  72,139,145,231,72,133,210,15,149,210,72,15,182,210,72,137,147,231,255,76,
177
  139,155,231,77,133,219,15,132,242,247,73,139,179,231,76,139,150,231,77,139,
178
  146,231,76,137,250,247,65,250,255,210,76,15,183,152,231,246,1,76,137,155,
179
  231,255,76,139,155,231,77,133,219,15,132,242,247,73,139,179,231,76,139,150,
180
  231,77,139,146,231,76,137,250,247,65,250,255,210,76,15,183,152,231,77,133,
181
  219,15,132,242,247,76,15,183,152,231,246,1,76,137,155,231,255,72,139,139,
182
  231,72,133,201,15,149,210,77,139,134,231,77,139,128,231,76,57,193,65,15,149,
183
  208,68,32,194,72,15,182,210,72,137,147,231,255,72,139,139,231,72,133,201,
184
  15,148,210,77,139,134,231,77,139,128,231,76,57,193,65,15,148,208,68,8,194,
185
  72,15,182,210,72,137,147,231,255,76,137,250,247,72,199,198,235,254,1,250,
186
  255,21,242,5,73,139,142,231,72,139,137,231,72,139,137,231,72,137,136,231,
187
  102,199,128,231,234,65,139,142,231,137,136,231,72,137,131,231,255,76,139,
188
  147,231,77,133,210,255,15,132,242,247,102,65,250,247,130,231,234,255,15,133,
189
  242,247,77,139,154,231,77,139,155,231,77,133,219,255,15,132,242,247,76,137,
190
  250,247,76,137,214,72,141,147,231,77,139,147,231,65,250,255,210,250,233,242,
191
  248,246,1,255,76,137,147,231,246,2,255,72,139,139,231,72,133,201,15,132,242,
192
  247,72,139,137,231,72,139,137,231,72,133,201,246,1,15,149,209,72,15,182,201,
193
  72,137,139,231,255,73,139,142,231,72,139,137,231,72,139,137,231,72,139,147,
194
  231,72,139,146,231,72,57,209,15,133,242,247,77,139,134,231,77,139,128,231,
195
  77,139,128,231,76,137,131,231,250,233,242,248,246,1,255,76,137,250,247,72,
196
  139,179,231,255,73,139,149,231,72,139,146,231,72,199,193,235,76,141,155,231,
197
  77,137,216,254,1,72,139,139,231,72,133,201,15,132,242,247,102,250,247,129,
198
  231,234,15,133,242,247,72,199,131,231,1,0,0,0,250,233,242,248,246,1,72,199,
199
  131,231,0,0,0,0,246,2,255,73,139,142,231,72,137,139,231,73,199,134,231,0,
200
  0,0,0,255,73,139,142,231,72,133,201,15,132,242,247,72,139,137,231,72,137,
201
  139,231,250,233,242,248,246,1,73,139,142,231,72,139,137,231,72,137,139,231,
202
  246,2,255,65,139,142,231,131,193,1,65,137,142,231,72,137,139,231,255,65,139,
203
  142,231,131,250,233,1,65,137,142,231,72,137,139,231,255,72,139,179,231,76,
204
  139,150,231,77,139,146,231,77,133,210,15,133,242,247,76,137,250,247,72,190,
205
  235,235,254,1,250,255,21,242,5,246,1,76,137,250,247,72,139,147,231,255,65,
206
  250,255,210,255,76,137,250,247,72,139,179,231,72,199,194,235,254,1,250,255,
207
  21,242,5,72,133,192,15,132,242,247,72,139,0,246,1,72,137,131,231,255,73,139,
208
  182,231,72,141,182,231,102,68,139,150,231,102,68,59,150,231,15,132,242,247,
209
  76,137,250,247,254,1,72,139,139,231,72,133,201,15,133,242,247,76,137,250,
210
  247,254,1,76,137,250,247,73,139,182,231,72,139,182,231,72,199,194,235,254,
211
  1,76,137,250,247,73,139,182,231,72,139,182,231,72,139,182,231,72,199,194,
212
  235,254,1,72,139,139,231,139,145,231,77,49,192,131,250,250,0,15,142,242,247,
213
  77,139,134,231,77,139,128,231,77,139,4,208,77,139,128,231,246,1,76,137,131,
214
  231,255,102,250,247,129,231,234,15,133,242,247,72,139,145,231,72,139,146,
215
  231,129,186,231,237,15,132,242,248,246,1,255,76,137,250,247,72,139,179,231,
216
  72,49,210,254,1,72,137,198,255,72,141,187,231,77,139,158,231,73,137,187,231,
217
  255,65,198,131,231,233,255,73,139,190,231,72,139,63,73,137,187,231,255,76,
218
  137,250,247,72,139,147,231,72,139,138,231,72,139,145,231,72,139,137,231,76,
219
  139,150,231,77,139,146,231,65,250,255,210,255,250,255,21,242,5,246,2,72,139,
220
  145,231,72,15,183,146,231,72,137,147,231,255,250,255,21,242,5,246,2,72,139,
221
  177,231,72,139,147,231,76,137,250,247,254,1,250,255,21,242,5,246,2,72,139,
222
  145,231,102,68,139,130,231,102,139,146,231,102,68,57,194,15,149,208,72,15,
223
  182,192,72,137,131,231,255,250,255,21,242,5,246,2,72,139,177,231,76,137,250,
224
  247,254,1,77,139,134,231,255,72,139,145,231,72,139,146,231,129,186,231,237,
225
  15,132,242,247,255,250,255,21,242,5,246,1,72,139,147,231,72,137,145,231,255,
226
  77,139,134,231,76,137,131,231,255,76,137,250,247,72,139,183,231,72,141,182,
227
  231,72,199,194,235,254,1,76,137,250,247,72,139,183,231,72,141,182,231,254,
228
  1,76,137,250,247,72,139,179,231,72,139,147,231,72,139,139,231,76,141,131,
229
  231,76,139,150,231,77,139,146,231,77,139,146,231,65,250,255,210,255,76,137,
230
  250,247,72,139,179,231,76,139,150,231,77,139,146,231,77,139,146,231,65,250,
231
  255,210,72,137,131,231,255,76,137,250,247,72,139,179,231,72,139,147,231,76,
232
  139,150,231,77,139,146,231,77,139,146,231,65,250,255,210,255,77,137,250,243,
233
  255,77,137,250,235,255,77,139,158,231,77,141,155,231,255,77,139,158,231,77,
234
  139,155,231,255,76,139,155,231,255,76,141,155,231,255,77,139,157,231,77,139,
235
  155,231,255,73,199,195,235,255,73,187,235,235,255,76,139,155,231,77,141,155,
236
  231,255,77,139,150,231,77,139,18,77,49,219,102,69,139,154,231,78,139,28,219,
237
  255,76,141,29,243,255,77,139,158,231,77,139,155,231,77,139,155,231,255,77,
238
  139,158,231,77,139,155,231,77,141,155,231,255,77,139,158,231,77,139,155,231,
239
  77,139,155,231,77,139,155,231,255,76,139,157,231,255,76,137,223,255,76,137,
240
  222,255,76,137,218,255,76,137,217,255,77,137,216,255,77,137,217,255,102,73,
241
  15,110,195,255,102,73,15,110,203,255,102,73,15,110,211,255,102,73,15,110,
242
  219,255,102,73,15,110,227,255,102,73,15,110,250,235,255,102,73,15,110,250,
243
  243,255,102,73,15,110,250,251,255,68,136,156,251,36,231,255,102,68,137,156,
244
  251,36,231,255,76,137,156,251,36,231,255,72,139,8,72,137,139,231,255,72,139,
245
  139,231,72,137,8,255,73,139,142,231,72,139,9,72,49,210,102,139,145,231,72,
246
  137,4,211,255,72,133,192,15,132,242,250,72,139,8,250,233,242,251,246,4,73,
247
  139,142,231,72,139,137,231,246,5,72,137,139,231,255,72,137,133,231,255,73,
248
  131,190,231,0,15,132,242,247,76,137,250,247,254,1,250,233,242,10,255,250,
249
  233,243,255,72,139,131,231,72,133,192,15,133,243,255,72,139,131,231,72,133,
250
  192,15,132,243,255,102,72,15,110,131,231,102,15,87,201,102,15,46,193,15,138,
251
  243,15,133,243,255,102,72,15,110,131,231,102,15,87,201,102,15,46,193,15,138,
252
  242,247,15,133,242,247,250,233,243,246,1,255,76,137,250,247,72,139,179,231,
253
  254,1,250,255,21,242,5,72,133,192,255,72,139,139,231,72,133,201,15,132,242,
254
  247,73,139,150,231,72,139,146,231,72,57,209,15,132,242,247,250,233,243,246,
255
  1,255,72,139,139,231,72,133,201,15,132,242,247,131,185,231,0,15,132,242,247,
256
  250,233,243,246,1,255,72,139,139,231,72,133,201,15,132,243,131,185,231,0,
257
  15,132,243,246,1,255,76,137,250,247,72,139,179,231,72,139,147,231,255,73,
258
  139,141,231,72,139,137,231,254,1,72,131,250,248,250,255,255,15,142,243,255,
259
  72,139,139,231,72,139,145,231,72,139,146,231,129,186,231,237,15,133,242,247,
260
  102,250,247,129,231,234,15,132,242,248,246,1,76,137,250,247,72,190,235,235,
261
  254,1,15,140,243,255,15,141,243,255,15,143,243,255,73,139,150,231,72,139,
262
  146,231,72,139,146,231,255,72,133,201,15,132,242,247,255,72,59,145,231,15,
263
  133,242,247,255,102,250,247,129,231,234,255,102,250,247,129,231,234,15,133,
264
  242,247,255,76,139,129,231,77,139,128,231,65,129,184,231,237,15,133,242,247,
265
  72,59,145,231,15,133,242,247,255,72,57,202,15,133,242,247,255,102,250,247,
266
  129,231,234,15,132,242,247,255,76,137,250,247,72,199,198,235,72,199,194,235,
267
  254,1,250,233,242,10,246,2,255,77,139,150,231,77,137,154,231,255,65,198,130,
268
  231,233,255,73,199,130,231,235,255,72,141,147,231,73,137,146,231,255,73,139,
269
  150,231,72,139,18,73,137,146,231,255,76,139,139,231,77,137,138,231,255,73,
270
  185,235,235,77,137,138,231,255,77,139,141,231,77,139,137,231,77,137,138,231,
271
  255,76,137,85,216,76,137,93,208,255,76,137,250,247,72,139,179,231,72,141,
272
  85,208,76,137,209,73,199,192,0,0,0,0,254,1,76,139,93,208,76,139,85,216,255,
273
  76,137,250,247,72,137,198,76,137,218,76,137,209,255,76,139,144,231,77,139,
274
  146,231,65,250,255,210,255,76,137,250,247,72,139,179,231,76,137,218,72,199,
275
  193,235,254,1,72,139,139,231,72,131,250,249,0,15,140,242,248,72,129,250,249,
276
  237,15,141,242,248,72,107,201,8,72,141,21,242,247,72,1,202,250,255,226,248,
277
  7,246,1,255,247,250,233,243,248,7,255,205,3,255,64,252,138,128,251,238,10,
278
  238,8,231,255,102,253,139,128,251,238,10,238,8,231,255,72,252,139,128,251,
279
  238,10,238,8,231,255,64,252,136,128,251,238,10,238,8,231,255,102,253,137,
280
  128,251,238,10,238,8,231,255,72,252,137,128,251,238,10,238,8,231,255,72,252,
281
  137,192,238,14,238,12,255,144,255,72,252,141,128,251,238,10,238,8,231,255,
282
  72,252,141,132,251,238,10,192,238,15,238,13,231,255,72,252,184,238,0,235,
283
  235,255,72,252,199,192,238,12,235,255,253,138,128,251,238,10,238,8,231,255,
284
  64,252,138,132,251,238,10,192,238,15,238,13,231,255,102,253,139,132,251,238,
285
  10,192,238,15,238,13,231,255,72,252,139,132,251,238,10,192,238,15,238,13,
286
  231,255,64,252,136,132,251,238,10,192,238,15,238,13,231,255,102,253,137,132,
287
  251,238,10,192,238,15,238,13,231,255,72,252,137,132,251,238,10,192,238,15,
288
  238,13,231,255,102,64,252,15,190,192,238,14,238,12,255,253,15,191,192,238,
289
  14,238,12,255,72,252,15,190,192,238,14,238,12,255,72,252,15,191,192,238,14,
290
  238,12,255,253,137,192,238,14,72,152,72,252,137,192,238,12,255,102,64,252,
291
  15,182,192,238,14,238,12,255,253,15,183,192,238,14,238,12,255,72,252,15,182,
292
  192,238,14,238,12,255,72,252,15,183,192,238,14,238,12,255,253,137,192,238,
293
  14,238,12,255,72,252,137,192,238,14,255,72,252,1,192,238,14,238,12,255,72,
294
  184,235,235,72,252,1,192,238,12,255,72,252,129,192,238,12,237,255,72,252,
295
  184,238,0,235,235,72,252,1,192,238,14,238,12,255,72,252,137,192,238,14,238,
296
  12,72,252,129,192,238,12,237,255,64,252,2,128,251,238,10,238,8,231,255,102,
297
  253,3,128,251,238,10,238,8,231,255,72,252,3,128,251,238,10,238,8,231,255,
298
  64,252,2,132,251,238,10,192,238,15,238,13,231,255,102,253,3,132,251,238,10,
299
  192,238,15,238,13,231,255,72,252,3,132,251,238,10,192,238,15,238,13,231,255,
300
  72,252,33,192,238,14,238,12,255,72,184,235,235,72,252,33,192,238,12,255,72,
301
  252,129,224,238,12,237,255,72,252,184,238,0,235,235,72,252,33,192,238,14,
302
  238,12,255,72,252,137,192,238,14,238,12,72,252,129,224,238,12,237,255,64,
303
  252,34,128,251,238,10,238,8,231,255,102,253,35,128,251,238,10,238,8,231,255,
304
  72,252,35,128,251,238,10,238,8,231,255,64,252,34,132,251,238,10,192,238,15,
305
  238,13,231,255,102,253,35,132,251,238,10,192,238,15,238,13,231,255,72,252,
306
  35,132,251,238,10,192,238,15,238,13,231,255,72,252,9,192,238,14,238,12,255,
307
  72,252,49,192,238,14,238,12,255,72,252,250,247,208,238,12,255,72,252,41,192,
308
  238,14,238,12,255,72,184,235,235,72,252,41,192,238,12,255,72,252,129,250,
309
  232,238,12,237,255,72,184,235,235,72,252,137,192,238,14,238,12,72,252,41,
310
  192,238,12,255,72,252,137,192,238,14,238,12,72,252,129,250,232,238,12,237,
311
  255,64,252,42,128,251,238,10,238,8,231,255,102,253,43,128,251,238,10,238,
312
  8,231,255,72,252,43,128,251,238,10,238,8,231,255,64,252,42,132,251,238,10,
313
  192,238,15,238,13,231,255,102,253,43,132,251,238,10,192,238,15,238,13,231,
314
  255,72,252,43,132,251,238,10,192,238,15,238,13,231,255,64,252,132,192,238,
315
  14,238,12,255,102,253,133,192,238,14,238,12,255,72,252,133,192,238,14,238,
316
  12,255,64,252,128,184,251,238,8,231,0,255,102,253,131,184,251,238,8,231,0,
317
  255,72,252,131,184,251,238,8,231,0,255,64,252,128,188,251,192,238,15,238,
318
  13,231,0,255,102,253,131,188,251,192,238,15,238,13,231,0,255,72,252,131,188,
319
  251,192,238,15,238,13,231,0,255,64,252,250,246,192,238,12,233,255,102,253,
320
  250,247,192,238,12,234,255,253,250,247,192,238,12,235,255,72,252,250,247,
321
  192,238,12,235,255,72,184,235,235,72,252,133,192,238,12,255,64,252,250,246,
322
  128,251,238,8,231,233,255,102,253,250,247,128,251,238,8,231,234,255,253,250,
323
  247,128,251,238,8,231,235,255,72,252,250,247,128,251,238,8,231,235,255,72,
324
  184,235,235,72,252,133,128,251,238,8,231,255,64,252,56,192,238,14,238,12,
325
  255,102,253,57,192,238,14,238,12,255,72,252,57,192,238,14,238,12,255,64,252,
326
  15,156,208,238,12,255,64,252,15,158,208,238,12,255,64,252,15,148,208,238,
327
  12,255,64,252,15,149,208,238,12,255,64,252,15,157,208,238,12,255,64,252,15,
328
  159,208,238,12,255,72,252,141,5,238,2,243,255,253,250,255,208,238,12,255,
329
  253,250,255,144,251,238,8,231,255
330
};
331
332
#line 73 "src/jit/x64/emit.dasc"
333
//|.section code, data
334
#define DASM_SECTION_CODE 0
335
#define DASM_SECTION_DATA 1
336
#define DASM_MAXSECTION   2
337
#line 74 "src/jit/x64/emit.dasc"
338
//|.globals MVM_JIT_LABEL_
339
enum {
340
  MVM_JIT_LABEL_exit,
341
  MVM_JIT_LABEL__MAX
342
};
343
#line 75 "src/jit/x64/emit.dasc"
344
345
#if MVM_JIT_LABEL__MAX > MVM_JIT_MAX_GLOBALS
346
#error "Not enough space for labels"
347
#endif
348
349
/* type declarations */
350
//|.type REGISTER, MVMRegister
351
62.2k
#define Dt1(_V) (int)(ptrdiff_t)&(((MVMRegister *)0)_V)
352
#line 82 "src/jit/x64/emit.dasc"
353
//|.type FRAME, MVMFrame
354
229k
#define Dt2(_V) (int)(ptrdiff_t)&(((MVMFrame *)0)_V)
355
#line 83 "src/jit/x64/emit.dasc"
356
//|.type ARGCTX, MVMArgProcContext
357
404
#define Dt3(_V) (int)(ptrdiff_t)&(((MVMArgProcContext *)0)_V)
358
#line 84 "src/jit/x64/emit.dasc"
359
//|.type CALLSITEPTR, MVMCallsite*
360
24.1k
#define Dt4(_V) (int)(ptrdiff_t)&(((MVMCallsite* *)0)_V)
361
#line 85 "src/jit/x64/emit.dasc"
362
//|.type CAPTURE, MVMCallCapture
363
140
#define Dt5(_V) (int)(ptrdiff_t)&(((MVMCallCapture *)0)_V)
364
#line 86 "src/jit/x64/emit.dasc"
365
//|.type CAPTUREBODY, MVMCallCaptureBody
366
#define Dt6(_V) (int)(ptrdiff_t)&(((MVMCallCaptureBody *)0)_V)
367
#line 87 "src/jit/x64/emit.dasc"
368
//|.type ARGPROCCONTEXT, MVMArgProcContext
369
72
#define Dt7(_V) (int)(ptrdiff_t)&(((MVMArgProcContext *)0)_V)
370
#line 88 "src/jit/x64/emit.dasc"
371
//|.type STATICFRAME, MVMStaticFrame
372
#define Dt8(_V) (int)(ptrdiff_t)&(((MVMStaticFrame *)0)_V)
373
#line 89 "src/jit/x64/emit.dasc"
374
//|.type P6OPAQUE, MVMP6opaque
375
13.8k
#define Dt9(_V) (int)(ptrdiff_t)&(((MVMP6opaque *)0)_V)
376
#line 90 "src/jit/x64/emit.dasc"
377
//|.type P6OBODY, MVMP6opaqueBody
378
7.43k
#define DtA(_V) (int)(ptrdiff_t)&(((MVMP6opaqueBody *)0)_V)
379
#line 91 "src/jit/x64/emit.dasc"
380
//|.type MVMITER, MVMIter
381
0
#define DtB(_V) (int)(ptrdiff_t)&(((MVMIter *)0)_V)
382
#line 92 "src/jit/x64/emit.dasc"
383
//|.type MVMINSTANCE, MVMInstance
384
6.07k
#define DtC(_V) (int)(ptrdiff_t)&(((MVMInstance *)0)_V)
385
#line 93 "src/jit/x64/emit.dasc"
386
//|.type MVMACTIVEHANDLERS, MVMActiveHandler
387
0
#define DtD(_V) (int)(ptrdiff_t)&(((MVMActiveHandler *)0)_V)
388
#line 94 "src/jit/x64/emit.dasc"
389
//|.type OBJECT, MVMObject
390
117k
#define DtE(_V) (int)(ptrdiff_t)&(((MVMObject *)0)_V)
391
#line 95 "src/jit/x64/emit.dasc"
392
//|.type STOOGE, MVMObjectStooge
393
6.15k
#define DtF(_V) (int)(ptrdiff_t)&(((MVMObjectStooge *)0)_V)
394
#line 96 "src/jit/x64/emit.dasc"
395
//|.type VMARRAY, MVMArray
396
0
#define Dt10(_V) (int)(ptrdiff_t)&(((MVMArray *)0)_V)
397
#line 97 "src/jit/x64/emit.dasc"
398
//|.type COLLECTABLE, MVMCollectable
399
17.6k
#define Dt11(_V) (int)(ptrdiff_t)&(((MVMCollectable *)0)_V)
400
#line 98 "src/jit/x64/emit.dasc"
401
//|.type STABLE, MVMSTable
402
33.1k
#define Dt12(_V) (int)(ptrdiff_t)&(((MVMSTable *)0)_V)
403
#line 99 "src/jit/x64/emit.dasc"
404
//|.type REPR, MVMREPROps
405
7.04k
#define Dt13(_V) (int)(ptrdiff_t)&(((MVMREPROps *)0)_V)
406
#line 100 "src/jit/x64/emit.dasc"
407
//|.type STRING, MVMString
408
416
#define Dt14(_V) (int)(ptrdiff_t)&(((MVMString *)0)_V)
409
#line 101 "src/jit/x64/emit.dasc"
410
//|.type OBJECTPTR, MVMObject*
411
97.3k
#define Dt15(_V) (int)(ptrdiff_t)&(((MVMObject* *)0)_V)
412
#line 102 "src/jit/x64/emit.dasc"
413
//|.type CONTEXT, MVMContext
414
0
#define Dt16(_V) (int)(ptrdiff_t)&(((MVMContext *)0)_V)
415
#line 103 "src/jit/x64/emit.dasc"
416
//|.type CONTAINERSPEC, MVMContainerSpec
417
8.46k
#define Dt17(_V) (int)(ptrdiff_t)&(((MVMContainerSpec *)0)_V)
418
#line 104 "src/jit/x64/emit.dasc"
419
//|.type STORAGESPEC, MVMStorageSpec
420
1
#define Dt18(_V) (int)(ptrdiff_t)&(((MVMStorageSpec *)0)_V)
421
#line 105 "src/jit/x64/emit.dasc"
422
//|.type HLLCONFIG, MVMHLLConfig;
423
1.66k
#define Dt19(_V) (int)(ptrdiff_t)&(((MVMHLLConfig *)0)_V)
424
#line 106 "src/jit/x64/emit.dasc"
425
//|.type SCREFBODY, MVMSerializationContextBody
426
5
#define Dt1A(_V) (int)(ptrdiff_t)&(((MVMSerializationContextBody *)0)_V)
427
#line 107 "src/jit/x64/emit.dasc"
428
//|.type NFGSYNTH, MVMNFGSynthetic
429
#define Dt1B(_V) (int)(ptrdiff_t)&(((MVMNFGSynthetic *)0)_V)
430
#line 108 "src/jit/x64/emit.dasc"
431
//|.type CODE, MVMCode
432
7.26k
#define Dt1C(_V) (int)(ptrdiff_t)&(((MVMCode *)0)_V)
433
#line 109 "src/jit/x64/emit.dasc"
434
//|.type U8, MVMuint8
435
#define Dt1D(_V) (int)(ptrdiff_t)&(((MVMuint8 *)0)_V)
436
#line 110 "src/jit/x64/emit.dasc"
437
//|.type U16, MVMuint16
438
1
#define Dt1E(_V) (int)(ptrdiff_t)&(((MVMuint16 *)0)_V)
439
#line 111 "src/jit/x64/emit.dasc"
440
//|.type U32, MVMuint32
441
#define Dt1F(_V) (int)(ptrdiff_t)&(((MVMuint32 *)0)_V)
442
#line 112 "src/jit/x64/emit.dasc"
443
//|.type U64, MVMuint64
444
#define Dt20(_V) (int)(ptrdiff_t)&(((MVMuint64 *)0)_V)
445
#line 113 "src/jit/x64/emit.dasc"
446
447
448
/* Static allocation of relevant types to registers. I pick
449
 * callee-save registers for efficiency. It is likely we'll be calling
450
 * quite a C functions, and this saves us the trouble of storing
451
 * them. Moreover, C compilers preferentially do not use callee-saved
452
 * registers, and so in most cases, these won't be touched at all. */
453
//|.type TC, MVMThreadContext, r14
454
201k
#define Dt21(_V) (int)(ptrdiff_t)&(((MVMThreadContext *)0)_V)
455
#line 121 "src/jit/x64/emit.dasc"
456
/* Alternative base pointer. I'll be using this often, so picking rbx
457
 * here rather than the extended registers will lead to smaller
458
 * bytecode */
459
//|.type WORK, MVMRegister, rbx
460
584k
#define Dt22(_V) (int)(ptrdiff_t)&(((MVMRegister *)0)_V)
461
#line 125 "src/jit/x64/emit.dasc"
462
//|.type CU, MVMCompUnit, r13
463
49.3k
#define Dt23(_V) (int)(ptrdiff_t)&(((MVMCompUnit *)0)_V)
464
#line 126 "src/jit/x64/emit.dasc"
465
466
467
468
469
12.0k
const MVMint32 MVM_jit_support(void) {
470
12.0k
#ifdef __i386__
471
    /* Usually, this file should only be compiled only on a amd64
472
       platform; but when compiling 'fat' or 'universal' binaries, we
473
       may compile it for other platform. In this case we use the
474
       runtime check to disable the JIT */
475
    return 0;
476
#else
477
12.0k
    return 1;
478
12.0k
#endif
479
12.0k
}
480
481
11.5k
const unsigned char * MVM_jit_actions(void) {
482
11.5k
    return actions;
483
11.5k
}
484
485
/* C Call argument registers */
486
//|.if WIN32
487
//|.define ARG1, rcx
488
//|.define ARG2, rdx
489
//|.define ARG3, r8
490
//|.define ARG4, r9
491
//|.else
492
//|.define ARG1, rdi
493
//|.define ARG2, rsi
494
//|.define ARG3, rdx
495
//|.define ARG4, rcx
496
//|.define ARG5, r8
497
//|.define ARG6, r9
498
//|.endif
499
500
/* C call argument registers for floating point */
501
//|.if WIN32
502
//|.define ARG1F, xmm0
503
//|.define ARG2F, xmm1
504
//|.define ARG3F, xmm2
505
//|.define ARG4F, xmm3
506
//|.else
507
//|.define ARG1F, xmm0
508
//|.define ARG2F, xmm1
509
//|.define ARG3F, xmm2
510
//|.define ARG4F, xmm3
511
//|.define ARG5F, xmm4
512
//|.define ARG6F, xmm5
513
//|.define ARG7F, xmm6
514
//|.define ARG8F, xmm7
515
//|.endif
516
517
/* Special register for the function to be invoked
518
 * (chosen because it isn't involved in argument passing
519
 *  and volatile) */
520
//|.define FUNCTION, r10
521
/* all-purpose temporary registers */
522
//|.define TMP1, rcx
523
//|.define TMP2, rdx
524
//|.define TMP3, r8
525
//|.define TMP4, r9
526
//|.define TMP5, r10
527
//|.define TMP6, r11
528
/* same, but 32 bits wide */
529
//|.define TMP1d, ecx
530
//|.define TMP2d, edx
531
//|.define TMP3d, r8d
532
//|.define TMP4d, r9d
533
//|.define TMP5d, r10d
534
//|.define TMP6d, r11d
535
/* and 16 bits wide */
536
//|.define TMP1w, cx
537
//|.define TMP2w, dx
538
//|.define TMP3w, r8w
539
//|.define TMP4w, r9w
540
//|.define TMP5w, r10w
541
//|.define TMP6w, r11w
542
/* and 8 bits for good measure */
543
//|.define TMP1b, cl
544
//|.define TMP2b, dl
545
//|.define TMP3b, r8b
546
//|.define TMP4b, r9b
547
//|.define TMP5b, r10b
548
//|.define TMP6b, r11b
549
550
551
/* return value */
552
//|.define RV, rax
553
//|.define RVd, eax
554
//|.define RVF, xmm0
555
556
557
//|.macro callp, funcptr
558
//|.data
559
//|5:
560
//|.dword (MVMuint32)((uintptr_t)(funcptr)), (MVMuint32)((uintptr_t)(funcptr) >> 32);
561
//|.code
562
//| call qword [<5];
563
//|.endmacro
564
565
566
//|.macro check_wb, root, ref, lbl;
567
//| test word COLLECTABLE:root->flags, MVM_CF_SECOND_GEN;
568
//| jz lbl;
569
//| test ref, ref;
570
//| jz lbl;
571
//| test word COLLECTABLE:ref->flags, MVM_CF_SECOND_GEN;
572
//| jnz lbl;
573
//|.endmacro;
574
575
//|.macro hit_wb, obj
576
//| mov ARG2, obj;
577
//| mov ARG1, TC;
578
//| callp &MVM_gc_write_barrier_hit;
579
//|.endmacro
580
581
//|.macro get_spesh_slot, reg, idx;
582
//| mov reg, TC->cur_frame;
583
//| mov reg, FRAME:reg->effective_spesh_slots;
584
//| mov reg, OBJECTPTR:reg[idx];
585
//|.endmacro
586
587
//|.macro get_vmnull, reg
588
//| mov reg, TC->instance;
589
//| mov reg, MVMINSTANCE:reg->VMNull;
590
//|.endmacro
591
592
//|.macro get_cur_op, reg
593
//| mov reg, TC->interp_cur_op
594
//| mov reg, [reg]
595
//|.endmacro
596
597
//|.macro get_string, reg, idx
598
//|| MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
599
//| mov reg, CU->body.strings;
600
//| mov reg, OBJECTPTR:reg[idx];
601
//|.endmacro
602
603
//|.macro test_type_object, reg
604
//| test word OBJECT:reg->header.flags, MVM_CF_TYPE_OBJECT
605
//|.endmacro
606
607
//|.macro gc_sync_point
608
//| cmp qword TC->gc_status, 0;
609
//| je >1;
610
//| mov ARG1, TC;
611
//| callp &MVM_gc_enter_from_interrupt;
612
//|1:
613
//|.endmacro
614
615
//|.macro throw_adhoc, msg
616
//| mov ARG1, TC;
617
//| mov64 ARG2, (uintptr_t)(msg);
618
//| callp &MVM_exception_throw_adhoc;
619
//|.endmacro
620
621
//|.macro get_stable, out, in
622
//| mov out, aword OBJECT:in->st;
623
//|.endmacro
624
625
//|.macro get_repr, out, in
626
//| get_stable out, in;
627
//| mov out, aword STABLE:out->REPR;
628
//|.endmacro
629
630
//|.macro cmp_repr_id, obj, tmp, id
631
//| get_repr tmp, obj;
632
//| cmp dword REPR:tmp->ID, id;
633
//|.endmacro
634
635
//|.define FRAME_NR, dword [rbp-0x20]
636
637
/* A function prologue is always the same in x86 / x64, because
638
 * we do not provide variable arguments, instead arguments are provided
639
 * via a frame. All JIT entry points receive a prologue. */
640
641
void MVM_jit_emit_prologue(MVMThreadContext *tc, MVMJitCompiler *compiler,
642
11.5k
                           MVMJitGraph *jg) {
643
11.5k
    //|.code
644
11.5k
    dasm_put(Dst, 0);
645
11.5k
#line 305 "src/jit/x64/emit.dasc"
646
11.5k
    /* Setup stack */
647
11.5k
    //| push rbp;
648
11.5k
    //| mov rbp, rsp;
649
11.5k
    dasm_put(Dst, 2);
650
11.5k
#line 308 "src/jit/x64/emit.dasc"
651
11.5k
    /* allocate stack space: 0x100 bytes = 256 bytes
652
11.5k
     *
653
11.5k
     * layout: [ a: 0x20 | b: 0x40 | c: 0xa0 | d: 0x20 ]
654
11.5k
     * a: space for 4 callee-save registers
655
11.5k
     * b: small scratch space
656
11.5k
     * c: space for stack arguments to c calls
657
11.5k
     * d: reserve space for GPR registers to c calls (win64) or more space for
658
11.5k
     * stack arguments (posix) */
659
11.5k
    //| sub rsp, 0x100;
660
11.5k
    dasm_put(Dst, 7);
661
11.5k
#line 317 "src/jit/x64/emit.dasc"
662
11.5k
    /* save callee-save registers */
663
11.5k
    //| mov [rbp-0x8],  TC;
664
11.5k
    //| mov [rbp-0x10], CU;
665
11.5k
    //| mov [rbp-0x18], WORK;
666
11.5k
    dasm_put(Dst, 16);
667
11.5k
#line 321 "src/jit/x64/emit.dasc"
668
11.5k
    /* setup special frame variables */
669
11.5k
    //| mov TC,   ARG1;
670
11.5k
    //| mov CU,   ARG2;
671
11.5k
    //| mov TMP6, TC->cur_frame;
672
11.5k
    //| mov WORK, FRAME:TMP6->work;
673
11.5k
    dasm_put(Dst, 32, Dt21(->cur_frame), Dt2(->work));
674
11.5k
#line 326 "src/jit/x64/emit.dasc"
675
11.5k
    /* If in the future we call a function, the return address into the JIT
676
11.5k
     * frame will be stored in this position. */
677
11.5k
    if (!jg->no_trampoline) {
678
11.5k
        //| lea rax, [rsp-0x8];
679
11.5k
        //| mov aword TC->jit_return_address, rax;
680
11.5k
        dasm_put(Dst, 49, Dt21(->jit_return_address));
681
11.5k
#line 331 "src/jit/x64/emit.dasc"
682
11.5k
    }
683
11.5k
    /* ARG3 contains our 'entry label' */
684
11.5k
    //| jmp ARG3
685
11.5k
    dasm_put(Dst, 60);
686
11.5k
#line 334 "src/jit/x64/emit.dasc"
687
11.5k
}
688
689
/* And a function epilogue is also always the same */
690
11.5k
void MVM_jit_emit_epilogue(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg) {
691
11.5k
    //| ->exit:
692
11.5k
    dasm_put(Dst, 64);
693
11.5k
#line 339 "src/jit/x64/emit.dasc"
694
11.5k
    /* clear the return address, so that we know there's no longer a JIT frame
695
11.5k
     * on the stack */
696
11.5k
    if (!jg->no_trampoline) {
697
11.5k
        //| mov aword TC->jit_return_address, 0;
698
11.5k
        dasm_put(Dst, 67, Dt21(->jit_return_address));
699
11.5k
#line 343 "src/jit/x64/emit.dasc"
700
11.5k
    }
701
11.5k
    /* restore callee-save registers */
702
11.5k
    //| mov TC, [rbp-0x8];
703
11.5k
    //| mov CU, [rbp-0x10];
704
11.5k
    //| mov WORK, [rbp-0x18];
705
11.5k
    dasm_put(Dst, 76);
706
11.5k
#line 348 "src/jit/x64/emit.dasc"
707
11.5k
    /* Restore stack */
708
11.5k
    //| mov rsp, rbp;
709
11.5k
    //| pop rbp;
710
11.5k
    //| ret;
711
11.5k
    dasm_put(Dst, 92);
712
11.5k
#line 352 "src/jit/x64/emit.dasc"
713
11.5k
}
714
715
static MVMuint64 try_emit_gen2_ref(MVMThreadContext *tc, MVMJitCompiler *compiler,
716
6.37k
                                   MVMJitGraph *jg, MVMObject *obj, MVMint16 reg) {
717
6.37k
    if (!(obj->header.flags & MVM_CF_SECOND_GEN))
718
0
        return 0;
719
6.37k
    //| mov64 TMP1, (uintptr_t)obj;
720
6.37k
    //| mov WORK[reg], TMP1;
721
6.37k
    dasm_put(Dst, 99, (unsigned int)((uintptr_t)obj), (unsigned int)(((uintptr_t)obj)>>32), Dt22([reg]));
722
6.37k
#line 360 "src/jit/x64/emit.dasc"
723
6.37k
    return 1;
724
6.37k
}
725
726
93.1k
static MVMint64 fits_in_32_bit(MVMint64 number) {
727
93.1k
    /* Used to determine if a 64 bit integer can be safely used as a
728
93.1k
     * 32 bit constant for immediate mode access */
729
93.1k
    return (number >= INT32_MIN) && (number <= INT32_MAX);
730
93.1k
}
731
732
/* compile per instruction, can't really do any better yet */
733
void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
734
136k
                            MVMJitPrimitive * prim) {
735
136k
    MVMSpeshIns *ins = prim->ins;
736
136k
    MVMuint16 op = ins->info->opcode;
737
136k
    MVM_jit_log(tc, "emit opcode: <%s>\n", ins->info->name);
738
136k
    /* Quite a few of these opcodes are copies. Ultimately, I want to
739
136k
     * move copies to their own node (MVMJitCopy or such), and reduce
740
136k
     * the number of copies (and thereby increase the efficiency), but
741
136k
     * currently that isn't really feasible. */
742
136k
    switch (op) {
743
8.65k
    case MVM_OP_const_i64_16:
744
8.65k
    case MVM_OP_const_i64_32: {
745
8.65k
        MVMint32 reg = ins->operands[0].reg.orig;
746
8.65k
        /* Upgrade to 64 bit */
747
8.65k
        MVMint64 val = (op == MVM_OP_const_i64_16 ? (MVMint64)ins->operands[1].lit_i16 :
748
1
                        (MVMint64)ins->operands[1].lit_i32);
749
8.65k
        //| mov qword WORK[reg], val;
750
8.65k
        dasm_put(Dst, 108, Dt22([reg]), val);
751
8.65k
#line 387 "src/jit/x64/emit.dasc"
752
8.65k
        break;
753
8.65k
    }
754
0
    case MVM_OP_const_i64: {
755
0
        MVMint32 reg = ins->operands[0].reg.orig;
756
0
        MVMint64 val = ins->operands[1].lit_i64;
757
0
        //| mov64 TMP1, val;
758
0
        //| mov WORK[reg], TMP1;
759
0
        dasm_put(Dst, 99, (unsigned int)(val), (unsigned int)((val)>>32), Dt22([reg]));
760
0
#line 394 "src/jit/x64/emit.dasc"
761
0
        break;
762
8.65k
    }
763
476
    case MVM_OP_const_n64: {
764
476
        MVMint16 reg = ins->operands[0].reg.orig;
765
476
        MVMint64 valbytes = ins->operands[1].lit_i64;
766
476
        MVM_jit_log(tc, "store const %f\n", ins->operands[1].lit_n64);
767
476
        //| mov64 TMP1, valbytes;
768
476
        //| mov WORK[reg], TMP1;
769
476
        dasm_put(Dst, 99, (unsigned int)(valbytes), (unsigned int)((valbytes)>>32), Dt22([reg]));
770
476
#line 402 "src/jit/x64/emit.dasc"
771
476
        break;
772
8.65k
    }
773
0
    case MVM_OP_inf:
774
0
    case MVM_OP_neginf:
775
0
    case MVM_OP_nan: {
776
0
        MVMint16 reg = ins->operands[0].reg.orig;
777
0
        MVMRegister tmp;
778
0
        if (op == MVM_OP_nan)
779
0
            tmp.n64 = MVM_num_nan(tc);
780
0
        else if (op == MVM_OP_inf)
781
0
            tmp.n64 = MVM_num_posinf(tc);
782
0
        else if (op == MVM_OP_neginf)
783
0
            tmp.n64 = MVM_num_neginf(tc);
784
0
        //| mov64 TMP1, tmp.i64;
785
0
        //| mov WORK[reg], TMP1;
786
0
        dasm_put(Dst, 99, (unsigned int)(tmp.i64), (unsigned int)((tmp.i64)>>32), Dt22([reg]));
787
0
#line 417 "src/jit/x64/emit.dasc"
788
0
        break;
789
0
    }
790
6.37k
    case MVM_OP_const_s: {
791
6.37k
         MVMint16 reg = ins->operands[0].reg.orig;
792
6.37k
         MVMuint32 idx = ins->operands[1].lit_str_idx;
793
6.37k
         MVMStaticFrame *sf = jg->sg->sf;
794
6.37k
         MVMString * s = MVM_cu_string(tc, sf->body.cu, idx);
795
6.37k
         if (!try_emit_gen2_ref(tc, compiler, jg, (MVMObject*)s, reg)) {
796
0
             //| get_string TMP1, idx;
797
0
              MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
798
0
#line 426 "src/jit/x64/emit.dasc"
799
0
             //| mov WORK[reg], TMP1;
800
0
             dasm_put(Dst, 114, Dt23(->body.strings), Dt15([idx]), Dt22([reg]));
801
0
#line 427 "src/jit/x64/emit.dasc"
802
0
         }
803
6.37k
         break;
804
0
    }
805
221
    case MVM_OP_null: {
806
221
        MVMint16 reg = ins->operands[0].reg.orig;
807
221
        //| get_vmnull TMP1;
808
221
        //| mov WORK[reg], TMP1;
809
221
        dasm_put(Dst, 127, Dt21(->instance), DtC(->VMNull), Dt22([reg]));
810
221
#line 434 "src/jit/x64/emit.dasc"
811
221
        break;
812
0
    }
813
274
    case MVM_OP_getwhat:
814
274
    case MVM_OP_getwho: {
815
274
        MVMint16 dst = ins->operands[0].reg.orig;
816
274
        MVMint16 obj = ins->operands[1].reg.orig;
817
274
        //| mov TMP1, WORK[obj];
818
274
        //| mov TMP1, OBJECT:TMP1->st;
819
274
        dasm_put(Dst, 140, Dt22([obj]), DtE(->st));
820
274
#line 442 "src/jit/x64/emit.dasc"
821
274
        if (op == MVM_OP_getwho) {
822
274
            //| mov TMP1, STABLE:TMP1->WHO;
823
274
            //| get_vmnull TMP2;
824
274
            //| test TMP1, TMP1;
825
274
            //| cmovz TMP1, TMP2;
826
274
            dasm_put(Dst, 149, Dt12(->WHO), Dt21(->instance), DtC(->VMNull));
827
274
#line 447 "src/jit/x64/emit.dasc"
828
0
        } else {
829
0
            //| mov TMP1, STABLE:TMP1->WHAT;
830
0
            dasm_put(Dst, 144, Dt12(->WHAT));
831
0
#line 449 "src/jit/x64/emit.dasc"
832
0
        }
833
274
        //| mov WORK[dst], TMP1;
834
274
        dasm_put(Dst, 103, Dt22([dst]));
835
274
#line 451 "src/jit/x64/emit.dasc"
836
274
        break;
837
274
    }
838
9.07k
    case MVM_OP_getlex:
839
9.07k
    case MVM_OP_sp_getlex_o:
840
9.07k
    case MVM_OP_sp_getlex_ins: {
841
9.07k
        MVMuint16 *lexical_types;
842
9.07k
        MVMStaticFrame * sf = jg->sg->sf;
843
9.07k
        MVMint16 dst = ins->operands[0].reg.orig;
844
9.07k
        MVMint16 idx = ins->operands[1].lex.idx;
845
9.07k
        MVMint16 out = ins->operands[1].lex.outers;
846
9.07k
        MVMint16 i;
847
9.07k
        //| mov TMP6, TC->cur_frame;
848
9.07k
        dasm_put(Dst, 169, Dt21(->cur_frame));
849
9.07k
#line 463 "src/jit/x64/emit.dasc"
850
19.7k
        for (i = 0; i < out; i++) {
851
10.6k
            /* I'm going to skip compiling the check whether the outer
852
10.6k
             * node really exists, because if the code has run N times
853
10.6k
             * correctly, then the outer frame must have existed then,
854
10.6k
             * and since this chain is static, it should still exist
855
10.6k
             * now.  If it doesn't exist, that means we crash.
856
10.6k
             *
857
10.6k
             * NB: inlining /might/ make this all wrong! But, if that
858
10.6k
             * happens, the interpreter will panic even without JIT */
859
10.6k
            //| mov TMP6, FRAME:TMP6->outer;
860
10.6k
            dasm_put(Dst, 174, Dt2(->outer));
861
10.6k
#line 473 "src/jit/x64/emit.dasc"
862
10.6k
            sf = sf->body.outer;
863
10.6k
        }
864
9.07k
        /* get array of lexicals */
865
9.07k
        //| mov TMP5, FRAME:TMP6->env;
866
9.07k
        dasm_put(Dst, 179, Dt2(->env));
867
9.07k
#line 477 "src/jit/x64/emit.dasc"
868
9.07k
        /* read value */
869
9.07k
        //| mov TMP5, REGISTER:TMP5[idx];
870
9.07k
        dasm_put(Dst, 184, Dt1([idx]));
871
9.07k
#line 479 "src/jit/x64/emit.dasc"
872
9.07k
        /* it seems that if at runtime, if the outer frame has been inlined,
873
9.07k
         * this /could/ be wrong. But if that is so, the interpreted instruction
874
9.07k
         * would also be wrong, because it'd refer to the wrong lexical. */
875
2.15k
        lexical_types = (!out && jg->sg->lexical_types ?
876
1.59k
                         jg->sg->lexical_types :
877
7.47k
                         sf->body.lexical_types);
878
9.07k
        MVM_jit_log(tc, "Lexical type of register: %d\n", lexical_types[idx]);
879
9.07k
        if (lexical_types[idx] == MVM_reg_obj) {
880
5.93k
            MVM_jit_log(tc, "Emit lex vifivy check\n");
881
5.93k
            /* if it is zero, check if we need to auto-vivify */
882
5.93k
            //| test TMP5, TMP5;
883
5.93k
            //| jnz >1;
884
5.93k
            dasm_put(Dst, 189);
885
5.93k
#line 491 "src/jit/x64/emit.dasc"
886
5.93k
            /* setup args */
887
5.93k
            //| mov ARG1, TC;
888
5.93k
            //| mov ARG2, TMP6;
889
5.93k
            //| mov ARG3, idx;
890
5.93k
            //| callp &MVM_frame_vivify_lexical;
891
5.93k
            dasm_put(Dst, 197, idx);
892
5.93k
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical)), (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical) >> 32));
893
5.93k
            dasm_put(Dst, 216);
894
5.93k
#line 496 "src/jit/x64/emit.dasc"
895
5.93k
            /* use return value for the result */
896
5.93k
            //| mov TMP5, RV;
897
5.93k
            //|1:
898
5.93k
            dasm_put(Dst, 222);
899
5.93k
#line 499 "src/jit/x64/emit.dasc"
900
5.93k
        }
901
9.07k
        /* store the value */
902
9.07k
        //| mov WORK[dst], TMP5;
903
9.07k
        dasm_put(Dst, 228, Dt22([dst]));
904
9.07k
#line 502 "src/jit/x64/emit.dasc"
905
9.07k
        break;
906
9.07k
    }
907
384
    case MVM_OP_sp_getlexvia_o:
908
384
    case MVM_OP_sp_getlexvia_ins: {
909
384
        MVMint16 dst = ins->operands[0].reg.orig;
910
384
        MVMint16 idx = ins->operands[1].lit_ui16;
911
384
        MVMint16 out = ins->operands[2].lit_ui16;
912
384
        MVMint16 via = ins->operands[3].reg.orig;
913
384
        MVMint16 i;
914
384
        /* Resolve the frame. */
915
384
        //| mov TMP6, WORK[via];
916
384
        //| mov TMP6, CODE:TMP6->body.outer;
917
384
        dasm_put(Dst, 233, Dt22([via]), Dt1C(->body.outer));
918
384
#line 514 "src/jit/x64/emit.dasc"
919
643
        for (i = 1; i < out; i++) /* From 1 as we are already at outer */
920
384
            //| mov TMP6, FRAME:TMP6->outer;
921
259
            dasm_put(Dst, 174, Dt2(->outer));
922
384
#line 516 "src/jit/x64/emit.dasc"
923
384
        /* get array of lexicals */
924
384
        //| mov TMP5, FRAME:TMP6->env;
925
384
        dasm_put(Dst, 179, Dt2(->env));
926
384
#line 518 "src/jit/x64/emit.dasc"
927
384
        /* read value */
928
384
        //| mov TMP5, REGISTER:TMP5[idx];
929
384
        dasm_put(Dst, 184, Dt1([idx]));
930
384
#line 520 "src/jit/x64/emit.dasc"
931
384
        if (op == MVM_OP_sp_getlexvia_o) {
932
254
            MVM_jit_log(tc, "Emit lex vifivy check for via code-ref lookup\n");
933
254
            /* if it is zero, check if we need to auto-vivify */
934
254
            //| test TMP5, TMP5;
935
254
            //| jnz >1;
936
254
            dasm_put(Dst, 189);
937
254
#line 525 "src/jit/x64/emit.dasc"
938
254
            /* setup args */
939
254
            //| mov ARG1, TC;
940
254
            //| mov ARG2, TMP6;
941
254
            //| mov ARG3, idx;
942
254
            //| callp &MVM_frame_vivify_lexical;
943
254
            dasm_put(Dst, 197, idx);
944
254
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical)), (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical) >> 32));
945
254
            dasm_put(Dst, 216);
946
254
#line 530 "src/jit/x64/emit.dasc"
947
254
            /* use return value for the result */
948
254
            //| mov TMP5, RV;
949
254
            //|1:
950
254
            dasm_put(Dst, 222);
951
254
#line 533 "src/jit/x64/emit.dasc"
952
254
        }
953
384
        /* store the value */
954
384
        //| mov WORK[dst], TMP5;
955
384
        dasm_put(Dst, 228, Dt22([dst]));
956
384
#line 536 "src/jit/x64/emit.dasc"
957
384
        break;
958
384
    }
959
121
    case MVM_OP_getlex_no:
960
121
    case MVM_OP_sp_getlex_no: {
961
121
        MVMint16  dst = ins->operands[0].reg.orig;
962
121
        MVMuint32 idx = ins->operands[1].lit_str_idx;
963
121
        //| mov ARG1, TC;
964
121
        //| get_string ARG2, idx;
965
121
        dasm_put(Dst, 242);
966
121
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
967
121
#line 544 "src/jit/x64/emit.dasc"
968
121
        //| mov ARG3, MVM_reg_obj;
969
121
        //| callp &MVM_frame_find_lexical_by_name;
970
121
        dasm_put(Dst, 247, Dt23(->body.strings), Dt15([idx]), MVM_reg_obj);
971
121
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name)), (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name) >> 32));
972
121
#line 546 "src/jit/x64/emit.dasc"
973
121
        //| test RV, RV;
974
121
        //| jz >1;
975
121
        //| mov RV, [RV];
976
121
        //| mov WORK[dst], RV;
977
121
        //| jmp >2;
978
121
        //|1:
979
121
        //| get_vmnull TMP3;
980
121
        //| mov WORK[dst], TMP3;
981
121
        //|2:
982
121
        dasm_put(Dst, 261, Dt22([dst]), Dt21(->instance), DtC(->VMNull), Dt22([dst]));
983
121
#line 555 "src/jit/x64/emit.dasc"
984
121
        break;
985
121
    }
986
1.85k
    case MVM_OP_bindlex: {
987
1.85k
        MVMuint16 *lexical_types;
988
1.85k
        MVMStaticFrame *sf = jg->sg->sf;
989
1.85k
        MVMint16 idx = ins->operands[0].lex.idx;
990
1.85k
        MVMint16 out = ins->operands[0].lex.outers;
991
1.85k
        MVMint16 src = ins->operands[1].reg.orig;
992
1.85k
        MVMint16 i;
993
1.85k
        //| mov TMP1, TC->cur_frame;
994
1.85k
        dasm_put(Dst, 301, Dt21(->cur_frame));
995
1.85k
#line 565 "src/jit/x64/emit.dasc"
996
1.94k
        for (i = 0; i < out; i++) {
997
86
            //| mov TMP1, FRAME:TMP1->outer;
998
86
            dasm_put(Dst, 144, Dt2(->outer));
999
86
#line 567 "src/jit/x64/emit.dasc"
1000
86
            sf = sf->body.outer;
1001
86
        }
1002
1.77k
        lexical_types = (!out && jg->sg->lexical_types ?
1003
1.35k
                         jg->sg->lexical_types :
1004
498
                         sf->body.lexical_types);
1005
1.85k
        //| mov TMP2, FRAME:TMP1->env;
1006
1.85k
        //| mov TMP3, WORK[src];
1007
1.85k
        //| mov REGISTER:TMP2[idx], TMP3;
1008
1.85k
        dasm_put(Dst, 306, Dt2(->env), Dt22([src]), Dt1([idx]));
1009
1.85k
#line 575 "src/jit/x64/emit.dasc"
1010
1.85k
        if (lexical_types[idx] == MVM_reg_obj ||
1011
1.83k
            lexical_types[idx] == MVM_reg_str) {
1012
1.83k
            //| check_wb TMP1, TMP3, >2;
1013
1.83k
            //| hit_wb TMP1;
1014
1.83k
            dasm_put(Dst, 319, Dt11(->flags), MVM_CF_SECOND_GEN, Dt11(->flags), MVM_CF_SECOND_GEN);
1015
1.83k
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1016
1.83k
#line 579 "src/jit/x64/emit.dasc"
1017
1.83k
            //|2:
1018
1.83k
            dasm_put(Dst, 356);
1019
1.83k
#line 580 "src/jit/x64/emit.dasc"
1020
1.83k
        }
1021
1.85k
        break;
1022
121
    }
1023
0
    case MVM_OP_getarg_o:
1024
0
    case MVM_OP_getarg_n:
1025
0
    case MVM_OP_getarg_s:
1026
0
    case MVM_OP_getarg_i: {
1027
0
        MVMint32 reg = ins->operands[0].reg.orig;
1028
0
        MVMuint16 idx = ins->operands[1].callsite_idx;
1029
0
        //| mov TMP1, TC->cur_frame;
1030
0
        //| mov TMP1, FRAME:TMP1->args;
1031
0
        //| mov TMP1, REGISTER:TMP1[idx];
1032
0
        //| mov WORK[reg], TMP1;
1033
0
        dasm_put(Dst, 364, Dt21(->cur_frame), Dt2(->args), Dt1([idx]), Dt22([reg]));
1034
0
#line 593 "src/jit/x64/emit.dasc"
1035
0
        break;
1036
0
    }
1037
228
    case MVM_OP_sp_getarg_o:
1038
228
    case MVM_OP_sp_getarg_n:
1039
228
    case MVM_OP_sp_getarg_s:
1040
228
    case MVM_OP_sp_getarg_i: {
1041
228
        MVMint32 reg = ins->operands[0].reg.orig;
1042
228
        MVMuint16 idx = ins->operands[1].callsite_idx;
1043
228
        //| mov TMP1, TC->cur_frame;
1044
228
        //| mov TMP1, FRAME:TMP1->params.args;
1045
228
        //| mov TMP1, REGISTER:TMP1[idx];
1046
228
        //| mov WORK[reg], TMP1;
1047
228
        dasm_put(Dst, 364, Dt21(->cur_frame), Dt2(->params.args), Dt1([idx]), Dt22([reg]));
1048
228
#line 605 "src/jit/x64/emit.dasc"
1049
228
        break;
1050
228
    }
1051
10.1k
    case MVM_OP_sp_p6oget_i:
1052
10.1k
    case MVM_OP_sp_p6oget_n:
1053
10.1k
    case MVM_OP_sp_p6oget_s:
1054
10.1k
    case MVM_OP_sp_p6oget_o:
1055
10.1k
    case MVM_OP_sp_p6ogetvc_o:
1056
10.1k
    case MVM_OP_sp_p6ogetvt_o: {
1057
10.1k
        MVMint16 dst    = ins->operands[0].reg.orig;
1058
10.1k
        MVMint16 obj    = ins->operands[1].reg.orig;
1059
10.1k
        MVMint16 offset = ins->operands[2].lit_i16;
1060
10.1k
        MVMint16 body   = offsetof(MVMP6opaque, body);
1061
10.1k
        /* load address and object */
1062
10.1k
        //| mov TMP1, WORK[obj];
1063
10.1k
        //| lea TMP2, [TMP1 + (offset + body)];
1064
10.1k
        //| mov TMP4, P6OPAQUE:TMP1->body.replaced;
1065
10.1k
        //| lea TMP5, [TMP4 + offset];
1066
10.1k
        //| test TMP4, TMP4;
1067
10.1k
        //| cmovnz TMP2, TMP5;
1068
10.1k
        dasm_put(Dst, 381, Dt22([obj]), (offset + body), Dt9(->body.replaced), offset);
1069
10.1k
#line 624 "src/jit/x64/emit.dasc"
1070
10.1k
        /* TMP2 now contains address of item */
1071
10.1k
        if (op == MVM_OP_sp_p6oget_o) {
1072
117
            //| mov TMP3, [TMP2];
1073
117
            //| test TMP3, TMP3;
1074
117
            dasm_put(Dst, 405);
1075
117
#line 628 "src/jit/x64/emit.dasc"
1076
117
            /* Check if object doesn't point to NULL */
1077
117
            //| jnz >3;
1078
117
            dasm_put(Dst, 412);
1079
117
#line 630 "src/jit/x64/emit.dasc"
1080
117
            /* Otherwise load VMNull */
1081
117
            //| get_vmnull TMP3;
1082
117
            //|3:
1083
117
            dasm_put(Dst, 417, Dt21(->instance), DtC(->VMNull));
1084
117
#line 633 "src/jit/x64/emit.dasc"
1085
10.0k
        } else if (op == MVM_OP_sp_p6ogetvt_o) {
1086
5.29k
            /* vivify as type object */
1087
5.29k
            MVMint16 spesh_idx = ins->operands[3].lit_i16;
1088
5.29k
            //| mov TMP3, [TMP2];
1089
5.29k
            dasm_put(Dst, 428);
1090
5.29k
#line 637 "src/jit/x64/emit.dasc"
1091
5.29k
            /* check for null */
1092
5.29k
            //| test TMP3, TMP3;
1093
5.29k
            //| jnz >4;
1094
5.29k
            dasm_put(Dst, 432);
1095
5.29k
#line 640 "src/jit/x64/emit.dasc"
1096
5.29k
            /* if null, vivify as type object from spesh slot */
1097
5.29k
            //| get_spesh_slot TMP3, spesh_idx;
1098
5.29k
            dasm_put(Dst, 440, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]));
1099
5.29k
#line 642 "src/jit/x64/emit.dasc"
1100
5.29k
            /* need to hit write barrier? */
1101
5.29k
            //| check_wb TMP1, TMP3, >3;
1102
5.29k
            //| mov qword [rbp-0x28], TMP2; // address
1103
5.29k
            //| mov qword [rbp-0x30], TMP3; // value
1104
5.29k
            //| hit_wb WORK[obj]; // write barrier for header
1105
5.29k
            dasm_put(Dst, 453, Dt11(->flags), MVM_CF_SECOND_GEN, Dt11(->flags), MVM_CF_SECOND_GEN, Dt22([obj]));
1106
5.29k
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1107
5.29k
#line 647 "src/jit/x64/emit.dasc"
1108
5.29k
            //| mov TMP3, qword [rbp-0x30];
1109
5.29k
            //| mov TMP2, qword [rbp-0x28];
1110
5.29k
            //|3:
1111
5.29k
            dasm_put(Dst, 499);
1112
5.29k
#line 650 "src/jit/x64/emit.dasc"
1113
5.29k
            /* store vivified type value in memory location */
1114
5.29k
            //| mov qword [TMP2], TMP3;
1115
5.29k
            //|4:
1116
5.29k
            dasm_put(Dst, 515);
1117
5.29k
#line 653 "src/jit/x64/emit.dasc"
1118
4.71k
        } else if (op == MVM_OP_sp_p6ogetvc_o) {
1119
0
            MVMint16 spesh_idx = ins->operands[3].lit_i16;
1120
0
            //| mov TMP3, [TMP2];
1121
0
            //| test TMP3, TMP3;
1122
0
            //| jnz >4;
1123
0
            dasm_put(Dst, 521);
1124
0
#line 658 "src/jit/x64/emit.dasc"
1125
0
            /* vivify as clone */
1126
0
            //| mov ARG1, TC;
1127
0
            //| get_spesh_slot ARG2, spesh_idx;
1128
0
            //| callp &MVM_repr_clone;
1129
0
            dasm_put(Dst, 532, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]));
1130
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_repr_clone)), (MVMuint32)((uintptr_t)(&MVM_repr_clone) >> 32));
1131
0
#line 662 "src/jit/x64/emit.dasc"
1132
0
            //| mov TMP3, RV;
1133
0
            dasm_put(Dst, 550);
1134
0
#line 663 "src/jit/x64/emit.dasc"
1135
0
            /* reload object and address */
1136
0
            //| mov TMP1, WORK[obj];
1137
0
            //| lea TMP2, [TMP1 + (offset + body)];
1138
0
            //| mov TMP4, P6OPAQUE:TMP1->body.replaced;
1139
0
            //| lea TMP5, [TMP4 + offset];
1140
0
            //| test TMP4, TMP4;
1141
0
            //| cmovnz TMP2, TMP5;
1142
0
            dasm_put(Dst, 381, Dt22([obj]), (offset + body), Dt9(->body.replaced), offset);
1143
0
#line 670 "src/jit/x64/emit.dasc"
1144
0
            /* assign with write barrier */
1145
0
            //| check_wb TMP1, TMP3, >3;
1146
0
            //| mov qword [rbp-0x28], TMP2; // address
1147
0
            //| mov qword [rbp-0x30], TMP3; // value
1148
0
            //| hit_wb WORK[obj]; // write barrier for header
1149
0
            dasm_put(Dst, 453, Dt11(->flags), MVM_CF_SECOND_GEN, Dt11(->flags), MVM_CF_SECOND_GEN, Dt22([obj]));
1150
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1151
0
#line 675 "src/jit/x64/emit.dasc"
1152
0
            //| mov TMP3, qword [rbp-0x30];
1153
0
            //| mov TMP2, qword [rbp-0x28];
1154
0
            //|3:
1155
0
            //| mov qword [TMP2], TMP3;
1156
0
            dasm_put(Dst, 559);
1157
0
#line 679 "src/jit/x64/emit.dasc"
1158
0
            /* done */
1159
0
            //|4:
1160
0
            dasm_put(Dst, 518);
1161
0
#line 681 "src/jit/x64/emit.dasc"
1162
4.71k
        } else {
1163
4.71k
            /* the regular case */
1164
4.71k
            //| mov TMP3, [TMP2];
1165
4.71k
            dasm_put(Dst, 428);
1166
4.71k
#line 684 "src/jit/x64/emit.dasc"
1167
4.71k
        }
1168
10.1k
        /* store in local register */
1169
10.1k
        //| mov WORK[dst], TMP3;
1170
10.1k
        dasm_put(Dst, 578, Dt22([dst]));
1171
10.1k
#line 687 "src/jit/x64/emit.dasc"
1172
10.1k
        break;
1173
10.1k
    }
1174
0
    case MVM_OP_sp_bind_i64:
1175
0
    case MVM_OP_sp_bind_n:
1176
0
    case MVM_OP_sp_bind_s:
1177
0
    case MVM_OP_sp_bind_o: {
1178
0
        MVMint16 obj    = ins->operands[0].reg.orig;
1179
0
        MVMint16 offset = ins->operands[1].lit_i16;
1180
0
        MVMint16 val    = ins->operands[2].reg.orig;
1181
0
        //| mov TMP1, WORK[obj];            // object
1182
0
        //| mov TMP2, WORK[val];            // value
1183
0
        dasm_put(Dst, 583, Dt22([obj]), Dt22([val]));
1184
0
#line 698 "src/jit/x64/emit.dasc"
1185
0
        if (op == MVM_OP_sp_bind_o || op == MVM_OP_sp_bind_s) {
1186
0
            /* check if we should hit write barrier */
1187
0
            //| check_wb TMP1, TMP2, >2;
1188
0
            dasm_put(Dst, 592, Dt11(->flags), MVM_CF_SECOND_GEN, Dt11(->flags), MVM_CF_SECOND_GEN);
1189
0
#line 701 "src/jit/x64/emit.dasc"
1190
0
            /* note: it is uneccesary to store pointers, because they
1191
0
               can just be loaded from memory */
1192
0
            //| hit_wb WORK[obj];
1193
0
            dasm_put(Dst, 489, Dt22([obj]));
1194
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1195
0
#line 704 "src/jit/x64/emit.dasc"
1196
0
            //| mov TMP1, aword WORK[obj]; // reload object
1197
0
            //| mov TMP2, aword WORK[val]; // reload value
1198
0
            //|2: // done
1199
0
            dasm_put(Dst, 620, Dt22([obj]), Dt22([val]));
1200
0
#line 707 "src/jit/x64/emit.dasc"
1201
0
        }
1202
0
        //| mov qword [TMP1+offset], TMP2; // store value into body
1203
0
        dasm_put(Dst, 636, offset);
1204
0
#line 709 "src/jit/x64/emit.dasc"
1205
0
        break;
1206
0
    }
1207
0
    case MVM_OP_sp_get_i64:
1208
0
    case MVM_OP_sp_get_n:
1209
0
    case MVM_OP_sp_get_s:
1210
0
    case MVM_OP_sp_get_o: {
1211
0
        MVMint16 dst    = ins->operands[0].reg.orig;
1212
0
        MVMint16 obj    = ins->operands[1].reg.orig;
1213
0
        MVMint16 offset = ins->operands[2].lit_i16;
1214
0
        //| mov TMP1, WORK[obj];            // object
1215
0
        //| mov TMP2, qword [TMP1+offset];   // get value from body
1216
0
        //| mov WORK[dst], TMP2;
1217
0
        dasm_put(Dst, 641, Dt22([obj]), offset, Dt22([dst]));
1218
0
#line 721 "src/jit/x64/emit.dasc"
1219
0
        break;
1220
0
    }
1221
0
    case MVM_OP_sp_deref_bind_i64:
1222
0
    case MVM_OP_sp_deref_bind_n: {
1223
0
        MVMint16 obj    = ins->operands[0].reg.orig;
1224
0
        MVMint16 val    = ins->operands[1].reg.orig;
1225
0
        MVMint16 offset = ins->operands[2].lit_i16;
1226
0
        //| mov TMP1, WORK[obj];            // object
1227
0
        //| mov TMP2, WORK[val];            // value
1228
0
        //| mov TMP1, qword [TMP1+offset];  // find address of target
1229
0
        //| mov qword [TMP1], TMP2;
1230
0
        dasm_put(Dst, 654, Dt22([obj]), Dt22([val]), offset);
1231
0
#line 732 "src/jit/x64/emit.dasc"
1232
0
        break;
1233
0
    }
1234
0
    case MVM_OP_sp_deref_get_i64:
1235
0
    case MVM_OP_sp_deref_get_n: {
1236
0
        MVMint16 dst    = ins->operands[0].reg.orig;
1237
0
        MVMint16 obj    = ins->operands[1].reg.orig;
1238
0
        MVMint16 offset = ins->operands[2].lit_i16;
1239
0
        //| mov TMP1, WORK[obj];            // object
1240
0
        //| mov TMP3, qword [TMP1+offset];  // get value pointer from body
1241
0
        //| mov TMP2, qword [TMP3];         // deref the pointer
1242
0
        //| mov WORK[dst], TMP2;
1243
0
        dasm_put(Dst, 670, Dt22([obj]), offset, Dt22([dst]));
1244
0
#line 743 "src/jit/x64/emit.dasc"
1245
0
        break;
1246
0
    }
1247
3.71k
    case MVM_OP_sp_p6obind_i:
1248
3.71k
    case MVM_OP_sp_p6obind_n:
1249
3.71k
    case MVM_OP_sp_p6obind_s:
1250
3.71k
    case MVM_OP_sp_p6obind_o: {
1251
3.71k
        MVMint16 obj    = ins->operands[0].reg.orig;
1252
3.71k
        MVMint16 offset = ins->operands[1].lit_i16;
1253
3.71k
        MVMint16 val    = ins->operands[2].reg.orig;
1254
3.71k
        //| mov TMP1, WORK[obj];            // object
1255
3.71k
        //| mov TMP2, WORK[val];            // value
1256
3.71k
        //| lea TMP3, P6OPAQUE:TMP1->body;  // body
1257
3.71k
        //| cmp qword P6OBODY:TMP3->replaced, 0;
1258
3.71k
        //| je >1;
1259
3.71k
        //| mov TMP3, P6OBODY:TMP3->replaced; // replaced object body
1260
3.71k
        //|1:
1261
3.71k
        dasm_put(Dst, 686, Dt22([obj]), Dt22([val]), Dt9(->body), DtA(->replaced), DtA(->replaced));
1262
3.71k
#line 759 "src/jit/x64/emit.dasc"
1263
3.71k
        if (op == MVM_OP_sp_p6obind_o || op == MVM_OP_sp_p6obind_s) {
1264
1.68k
            /* check if we should hit write barrier */
1265
1.68k
            //| check_wb TMP1, TMP2, >2;
1266
1.68k
            //| mov qword [rbp-0x28], TMP2; // store value
1267
1.68k
            //| mov qword [rbp-0x30], TMP3; // store body pointer
1268
1.68k
            //| hit_wb WORK[obj];
1269
1.68k
            dasm_put(Dst, 714, Dt11(->flags), MVM_CF_SECOND_GEN, Dt11(->flags), MVM_CF_SECOND_GEN, Dt22([obj]));
1270
1.68k
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1271
1.68k
#line 765 "src/jit/x64/emit.dasc"
1272
1.68k
            //| mov TMP3, qword [rbp-0x30]; // restore body pointer
1273
1.68k
            //| mov TMP2, qword [rbp-0x28]; // restore value
1274
1.68k
            //|2: // done
1275
1.68k
            dasm_put(Dst, 759);
1276
1.68k
#line 768 "src/jit/x64/emit.dasc"
1277
1.68k
        }
1278
3.71k
        //| mov [TMP3+offset], TMP2; // store value into body
1279
3.71k
        dasm_put(Dst, 775, offset);
1280
3.71k
#line 770 "src/jit/x64/emit.dasc"
1281
3.71k
        break;
1282
3.71k
    }
1283
36.1k
    case MVM_OP_getwhere:
1284
36.1k
    case MVM_OP_set: {
1285
36.1k
         MVMint32 reg1 = ins->operands[0].reg.orig;
1286
36.1k
         MVMint32 reg2 = ins->operands[1].reg.orig;
1287
36.1k
         //| mov TMP1, WORK[reg2];
1288
36.1k
         //| mov WORK[reg1], TMP1;
1289
36.1k
         dasm_put(Dst, 780, Dt22([reg2]), Dt22([reg1]));
1290
36.1k
#line 778 "src/jit/x64/emit.dasc"
1291
36.1k
         break;
1292
36.1k
    }
1293
8.57k
    case MVM_OP_sp_getspeshslot: {
1294
8.57k
        MVMint16 dst = ins->operands[0].reg.orig;
1295
8.57k
        MVMint16 spesh_idx = ins->operands[1].lit_i16;
1296
8.57k
        //| get_spesh_slot TMP1, spesh_idx;
1297
8.57k
        //| mov WORK[dst], TMP1;
1298
8.57k
        dasm_put(Dst, 364, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]), Dt22([dst]));
1299
8.57k
#line 785 "src/jit/x64/emit.dasc"
1300
8.57k
        break;
1301
36.1k
    }
1302
0
    case MVM_OP_setdispatcher: {
1303
0
        MVMint16 src = ins->operands[0].reg.orig;
1304
0
        //| mov TMP1, aword WORK[src];
1305
0
        //| mov aword TC->cur_dispatcher, TMP1;
1306
0
        dasm_put(Dst, 789, Dt22([src]), Dt21(->cur_dispatcher));
1307
0
#line 791 "src/jit/x64/emit.dasc"
1308
0
        break;
1309
36.1k
    }
1310
0
    case MVM_OP_takedispatcher: {
1311
0
        MVMint16 dst = ins->operands[0].reg.orig;
1312
0
        //| mov TMP1, aword TC->cur_dispatcher;
1313
0
        //| cmp TMP1, 0;
1314
0
        //| je >2;
1315
0
        //| mov TMP2, aword TC->cur_dispatcher_for;
1316
0
        //| cmp TMP2, 0;
1317
0
        //| je >1;
1318
0
        //| mov TMP3, TC->cur_frame;
1319
0
        //| mov TMP3, FRAME:TMP3->code_ref;
1320
0
        //| cmp TMP2, TMP3;
1321
0
        //| jne >2;
1322
0
        //|1:
1323
0
        //| mov aword WORK[dst], TMP1;
1324
0
        //| mov aword TC->cur_dispatcher, NULL;
1325
0
        //| jmp >3;
1326
0
        //|2:
1327
0
        //| get_vmnull TMP1;
1328
0
        //| mov aword WORK[dst], TMP1;
1329
0
        //|3:
1330
0
        dasm_put(Dst, 798, Dt21(->cur_dispatcher), Dt21(->cur_dispatcher_for), Dt21(->cur_frame), Dt2(->code_ref), Dt22([dst]), Dt21(->cur_dispatcher), NULL, Dt21(->instance), DtC(->VMNull), Dt22([dst]));
1331
0
#line 813 "src/jit/x64/emit.dasc"
1332
0
        break;
1333
36.1k
    }
1334
0
    case MVM_OP_ctx: {
1335
0
        MVMint16 dst = ins->operands[0].reg.orig;
1336
0
        //| mov ARG1, TC;
1337
0
        //| mov ARG2, TC->cur_frame;
1338
0
        //| callp &MVM_frame_context_wrapper;
1339
0
        dasm_put(Dst, 871, Dt21(->cur_frame));
1340
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_context_wrapper)), (MVMuint32)((uintptr_t)(&MVM_frame_context_wrapper) >> 32));
1341
0
#line 820 "src/jit/x64/emit.dasc"
1342
0
        //| mov WORK[dst], RV;
1343
0
        dasm_put(Dst, 881, Dt22([dst]));
1344
0
#line 821 "src/jit/x64/emit.dasc"
1345
0
        break;
1346
36.1k
    }
1347
0
    case MVM_OP_ctxlexpad: {
1348
0
        MVMint16 src = ins->operands[1].reg.orig;
1349
0
        MVMint16 dst = ins->operands[0].reg.orig;
1350
0
        //| mov TMP1, WORK[src];
1351
0
        //| test_type_object TMP1;
1352
0
        //| jnz >1;
1353
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMContext;
1354
0
        //| je >2;
1355
0
        //|1:
1356
0
        //| throw_adhoc "ctxlexpad needs an MVMContext";
1357
0
        dasm_put(Dst, 891, Dt22([src]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMContext, (unsigned int)((uintptr_t)("ctxlexpad needs an MVMContext")), (unsigned int)(((uintptr_t)("ctxlexpad needs an MVMContext"))>>32));
1358
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1359
0
#line 833 "src/jit/x64/emit.dasc"
1360
0
        //|2:
1361
0
        //| mov WORK[dst], TMP1;
1362
0
        dasm_put(Dst, 933, Dt22([dst]));
1363
0
#line 835 "src/jit/x64/emit.dasc"
1364
0
        break;
1365
36.1k
    }
1366
0
    case MVM_OP_curcode: {
1367
0
        MVMint16 dst = ins->operands[0].reg.orig;
1368
0
        //| mov TMP1, TC->cur_frame;
1369
0
        //| mov TMP1, aword FRAME:TMP1->code_ref;
1370
0
        //| mov aword WORK[dst], TMP1;
1371
0
        dasm_put(Dst, 127, Dt21(->cur_frame), Dt2(->code_ref), Dt22([dst]));
1372
0
#line 842 "src/jit/x64/emit.dasc"
1373
0
        break;
1374
36.1k
    }
1375
0
    case MVM_OP_getcode: {
1376
0
        MVMint16 dst = ins->operands[0].reg.orig;
1377
0
        MVMuint16 idx = ins->operands[1].coderef_idx;
1378
0
        //| mov TMP1, aword CU->body.coderefs;
1379
0
        //| mov TMP1, aword OBJECTPTR:TMP1[idx];
1380
0
        //| mov aword WORK[dst], TMP1;
1381
0
        dasm_put(Dst, 114, Dt23(->body.coderefs), Dt15([idx]), Dt22([dst]));
1382
0
#line 850 "src/jit/x64/emit.dasc"
1383
0
        break;
1384
36.1k
    }
1385
0
    case MVM_OP_callercode: {
1386
0
        MVMint16 dst = ins->operands[0].reg.orig;
1387
0
        //| mov TMP1, TC->cur_frame;
1388
0
        //| mov TMP1, aword FRAME:TMP1->caller;
1389
0
        //| test TMP1, TMP1;
1390
0
        //| jz >1;
1391
0
        //| mov TMP1, aword FRAME:TMP1->code_ref;
1392
0
        //|1:
1393
0
        //| mov aword WORK[dst], TMP1;
1394
0
        dasm_put(Dst, 945, Dt21(->cur_frame), Dt2(->caller), Dt2(->code_ref), Dt22([dst]));
1395
0
#line 861 "src/jit/x64/emit.dasc"
1396
0
        break;
1397
36.1k
    }
1398
1.66k
    case MVM_OP_hllboxtype_n:
1399
1.66k
    case MVM_OP_hllboxtype_s:
1400
1.66k
    case MVM_OP_hllboxtype_i: {
1401
1.66k
        MVMint16 dst = ins->operands[0].reg.orig;
1402
1.66k
        //| mov TMP1, CU->body.hll_config;
1403
1.66k
        dasm_put(Dst, 971, Dt23(->body.hll_config));
1404
1.66k
#line 868 "src/jit/x64/emit.dasc"
1405
1.66k
        if (op == MVM_OP_hllboxtype_n) {
1406
270
            //| mov TMP1, aword HLLCONFIG:TMP1->num_box_type;
1407
270
            dasm_put(Dst, 144, Dt19(->num_box_type));
1408
270
#line 870 "src/jit/x64/emit.dasc"
1409
1.39k
        } else if (op == MVM_OP_hllboxtype_s) {
1410
147
            //| mov TMP1, aword HLLCONFIG:TMP1->str_box_type;
1411
147
            dasm_put(Dst, 144, Dt19(->str_box_type));
1412
147
#line 872 "src/jit/x64/emit.dasc"
1413
1.24k
        } else {
1414
1.24k
            //| mov TMP1, aword HLLCONFIG:TMP1->int_box_type;
1415
1.24k
            dasm_put(Dst, 144, Dt19(->int_box_type));
1416
1.24k
#line 874 "src/jit/x64/emit.dasc"
1417
1.24k
        }
1418
1.66k
        //| mov aword WORK[dst], TMP1;
1419
1.66k
        dasm_put(Dst, 103, Dt22([dst]));
1420
1.66k
#line 876 "src/jit/x64/emit.dasc"
1421
1.66k
        break;
1422
1.66k
    }
1423
0
    case MVM_OP_null_s: {
1424
0
        MVMint16 dst = ins->operands[0].reg.orig;
1425
0
        //| mov qword WORK[dst], 0;
1426
0
        dasm_put(Dst, 976, Dt22([dst]));
1427
0
#line 881 "src/jit/x64/emit.dasc"
1428
0
        break;
1429
1.66k
     }
1430
451
    case MVM_OP_isnull_s: {
1431
451
        MVMint16 dst = ins->operands[0].reg.orig;
1432
451
        MVMint16 src = ins->operands[1].reg.orig;
1433
451
        //| mov TMP1, WORK[src];
1434
451
        //| test TMP1, TMP1;
1435
451
        //| setz TMP2b;
1436
451
        //| movzx TMP2, TMP2b;
1437
451
        //| mov qword WORK[dst], TMP2;
1438
451
        dasm_put(Dst, 985, Dt22([src]), Dt22([dst]));
1439
451
#line 891 "src/jit/x64/emit.dasc"
1440
451
        break;
1441
1.66k
    }
1442
68
    case MVM_OP_captureposarg: {
1443
68
        MVMint16 dst = ins->operands[0].reg.orig;
1444
68
        MVMint16 src = ins->operands[1].reg.orig;
1445
68
        MVMint16 pos = ins->operands[2].reg.orig;
1446
68
        //| mov TMP5, qword WORK[src];
1447
68
        //| test_type_object TMP5;
1448
68
        //| jnz >1;
1449
68
        //| cmp_repr_id TMP5, TMP6, MVM_REPR_ID_MVMCallCapture;
1450
68
        //| jne >1;
1451
68
        //| mov ARG1, TC;
1452
68
        //| mov ARG2, aword CAPTURE:TMP5->body.apc;
1453
68
        //| mov ARG3, WORK[pos];
1454
68
        //| callp MVM_args_get_required_pos_obj;
1455
68
        dasm_put(Dst, 1004, Dt22([src]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture, Dt5(->body.apc), Dt22([pos]));
1456
68
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(MVM_args_get_required_pos_obj)), (MVMuint32)((uintptr_t)(MVM_args_get_required_pos_obj) >> 32));
1457
68
#line 906 "src/jit/x64/emit.dasc"
1458
68
        //| mov WORK[dst], RV;
1459
68
        //| jmp >2;
1460
68
        //|1:
1461
68
        //| throw_adhoc "captureposarg needs a MVMCallCapture";
1462
68
        dasm_put(Dst, 1050, Dt22([dst]), (unsigned int)((uintptr_t)("captureposarg needs a MVMCallCapture")), (unsigned int)(((uintptr_t)("captureposarg needs a MVMCallCapture"))>>32));
1463
68
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1464
68
#line 910 "src/jit/x64/emit.dasc"
1465
68
        //|2:
1466
68
        dasm_put(Dst, 356);
1467
68
#line 911 "src/jit/x64/emit.dasc"
1468
68
        break;
1469
1.66k
    }
1470
1.76k
    case MVM_OP_add_i:
1471
1.76k
    case MVM_OP_sub_i:
1472
1.76k
    case MVM_OP_bor_i:
1473
1.76k
    case MVM_OP_band_i:
1474
1.76k
    case MVM_OP_bxor_i: {
1475
1.76k
        MVMint32 reg_a = ins->operands[0].reg.orig;
1476
1.76k
        MVMint32 reg_b = ins->operands[1].reg.orig;
1477
1.76k
        MVMint32 reg_c = ins->operands[2].reg.orig;
1478
1.76k
1479
1.76k
        MVMSpeshFacts *operand_facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[2]);
1480
1.76k
1481
1.76k
        if (reg_a == reg_b) {
1482
173
            if (operand_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE &&
1483
53
                fits_in_32_bit(operand_facts->value.i)) {
1484
53
                MVMint64 value = operand_facts->value.i;
1485
53
                MVM_jit_log(tc, "accumulator for %s stayed in memory and "
1486
53
                            " constant value %"PRId64" used\n", ins->info->name, value);
1487
53
                switch(ins->info->opcode) {
1488
52
                case MVM_OP_add_i:
1489
52
                    //| add qword WORK[reg_a], qword value;
1490
52
                    dasm_put(Dst, 1075, Dt22([reg_a]), value);
1491
52
#line 933 "src/jit/x64/emit.dasc"
1492
52
                    break;
1493
1
                case MVM_OP_sub_i:
1494
1
                    //| sub qword WORK[reg_a], qword value;
1495
1
                    dasm_put(Dst, 1081, Dt22([reg_a]), value);
1496
1
#line 936 "src/jit/x64/emit.dasc"
1497
1
                    break;
1498
0
                case MVM_OP_bor_i:
1499
0
                    //| or qword WORK[reg_a], qword value;
1500
0
                    dasm_put(Dst, 1087, Dt22([reg_a]), value);
1501
0
#line 939 "src/jit/x64/emit.dasc"
1502
0
                    break;
1503
0
                case MVM_OP_band_i:
1504
0
                    //| and qword WORK[reg_a], qword value;
1505
0
                    dasm_put(Dst, 1093, Dt22([reg_a]), value);
1506
0
#line 942 "src/jit/x64/emit.dasc"
1507
0
                    break;
1508
0
                case MVM_OP_bxor_i:
1509
0
                    //| xor qword WORK[reg_a], qword value;
1510
0
                    dasm_put(Dst, 1099, Dt22([reg_a]), value);
1511
0
#line 945 "src/jit/x64/emit.dasc"
1512
0
                    break;
1513
53
                }
1514
120
            } else {
1515
120
                MVM_jit_log(tc, "accumulator for %s stayed in memory\n", ins->info->name);
1516
120
                //| mov rax, WORK[reg_c];
1517
120
                dasm_put(Dst, 1105, Dt22([reg_c]));
1518
120
#line 950 "src/jit/x64/emit.dasc"
1519
120
                switch(ins->info->opcode) {
1520
120
                case MVM_OP_add_i:
1521
120
                    //| add WORK[reg_a], rax;
1522
120
                    dasm_put(Dst, 1110, Dt22([reg_a]));
1523
120
#line 953 "src/jit/x64/emit.dasc"
1524
120
                    break;
1525
0
                case MVM_OP_sub_i:
1526
0
                    //| sub WORK[reg_a], rax;
1527
0
                    dasm_put(Dst, 1115, Dt22([reg_a]));
1528
0
#line 956 "src/jit/x64/emit.dasc"
1529
0
                    break;
1530
0
                case MVM_OP_bor_i:
1531
0
                    //| or WORK[reg_a], rax;
1532
0
                    dasm_put(Dst, 1120, Dt22([reg_a]));
1533
0
#line 959 "src/jit/x64/emit.dasc"
1534
0
                    break;
1535
0
                case MVM_OP_band_i:
1536
0
                    //| and WORK[reg_a], rax;
1537
0
                    dasm_put(Dst, 1125, Dt22([reg_a]));
1538
0
#line 962 "src/jit/x64/emit.dasc"
1539
0
                    break;
1540
0
                case MVM_OP_bxor_i:
1541
0
                    //| xor WORK[reg_a], rax;
1542
0
                    dasm_put(Dst, 1130, Dt22([reg_a]));
1543
0
#line 965 "src/jit/x64/emit.dasc"
1544
0
                    break;
1545
120
                }
1546
120
            }
1547
1.58k
        } else {
1548
1.58k
            if (operand_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE &&
1549
1.04k
                fits_in_32_bit(operand_facts->value.i)) {
1550
1.04k
                MVMint64 value = operand_facts->value.i;
1551
1.04k
                MVM_jit_log(tc, "constant value %"PRId64" used for %s\n",
1552
1.04k
                            value, ins->info->name);
1553
1.04k
                //| mov rax, WORK[reg_b];
1554
1.04k
                dasm_put(Dst, 1105, Dt22([reg_b]));
1555
1.04k
#line 975 "src/jit/x64/emit.dasc"
1556
1.04k
                switch(ins->info->opcode) {
1557
554
                case MVM_OP_add_i:
1558
554
                    //| add rax, qword value;
1559
554
                    dasm_put(Dst, 1135, value);
1560
554
#line 978 "src/jit/x64/emit.dasc"
1561
554
                    break;
1562
480
                case MVM_OP_sub_i:
1563
480
                    //| sub rax, qword value;
1564
480
                    dasm_put(Dst, 1140, value);
1565
480
#line 981 "src/jit/x64/emit.dasc"
1566
480
                    break;
1567
0
                case MVM_OP_bor_i:
1568
0
                    //| or rax, qword value;
1569
0
                    dasm_put(Dst, 1146, value);
1570
0
#line 984 "src/jit/x64/emit.dasc"
1571
0
                    break;
1572
6
                case MVM_OP_band_i:
1573
6
                    //| and rax, qword value;
1574
6
                    dasm_put(Dst, 1151, value);
1575
6
#line 987 "src/jit/x64/emit.dasc"
1576
6
                    break;
1577
0
                case MVM_OP_bxor_i:
1578
0
                    //| xor rax, qword value;
1579
0
                    dasm_put(Dst, 1156, value);
1580
0
#line 990 "src/jit/x64/emit.dasc"
1581
0
                    break;
1582
1.04k
                }
1583
1.04k
                //| mov WORK[reg_a], rax;
1584
1.04k
                dasm_put(Dst, 886, Dt22([reg_a]));
1585
1.04k
#line 993 "src/jit/x64/emit.dasc"
1586
547
            } else {
1587
547
                //| mov rax, WORK[reg_b];
1588
547
                dasm_put(Dst, 1105, Dt22([reg_b]));
1589
547
#line 995 "src/jit/x64/emit.dasc"
1590
547
                switch(ins->info->opcode) {
1591
1
                case MVM_OP_add_i:
1592
1
                    //| add rax, WORK[reg_c];
1593
1
                    dasm_put(Dst, 1162, Dt22([reg_c]));
1594
1
#line 998 "src/jit/x64/emit.dasc"
1595
1
                    break;
1596
314
                case MVM_OP_sub_i:
1597
314
                    //| sub rax, WORK[reg_c];
1598
314
                    dasm_put(Dst, 1167, Dt22([reg_c]));
1599
314
#line 1001 "src/jit/x64/emit.dasc"
1600
314
                    break;
1601
34
                case MVM_OP_bor_i:
1602
34
                    //| or rax, WORK[reg_c];
1603
34
                    dasm_put(Dst, 1172, Dt22([reg_c]));
1604
34
#line 1004 "src/jit/x64/emit.dasc"
1605
34
                    break;
1606
198
                case MVM_OP_band_i:
1607
198
                    //| and rax, WORK[reg_c];
1608
198
                    dasm_put(Dst, 1177, Dt22([reg_c]));
1609
198
#line 1007 "src/jit/x64/emit.dasc"
1610
198
                    break;
1611
0
                case MVM_OP_bxor_i:
1612
0
                    //| xor rax, WORK[reg_c];
1613
0
                    dasm_put(Dst, 1182, Dt22([reg_c]));
1614
0
#line 1010 "src/jit/x64/emit.dasc"
1615
0
                    break;
1616
547
                }
1617
547
                //| mov WORK[reg_a], rax;
1618
547
                dasm_put(Dst, 886, Dt22([reg_a]));
1619
547
#line 1013 "src/jit/x64/emit.dasc"
1620
547
            }
1621
1.58k
        }
1622
1.76k
        break;
1623
1.76k
    }
1624
12
    case MVM_OP_mul_i:
1625
12
    case MVM_OP_blshift_i:
1626
12
    case MVM_OP_brshift_i: {
1627
12
        MVMint32 reg_a = ins->operands[0].reg.orig;
1628
12
        MVMint32 reg_b = ins->operands[1].reg.orig;
1629
12
        MVMint32 reg_c = ins->operands[2].reg.orig;
1630
12
        //| mov rax, WORK[reg_b];
1631
12
        dasm_put(Dst, 1105, Dt22([reg_b]));
1632
12
#line 1024 "src/jit/x64/emit.dasc"
1633
12
        switch(ins->info->opcode) {
1634
12
        case MVM_OP_mul_i:
1635
12
            //| imul rax, WORK[reg_c];
1636
12
            dasm_put(Dst, 1187, Dt22([reg_c]));
1637
12
#line 1027 "src/jit/x64/emit.dasc"
1638
12
            break;
1639
0
        case MVM_OP_blshift_i:
1640
0
            //| mov cl, byte WORK[reg_c];
1641
0
            //| shl rax, cl;
1642
0
            dasm_put(Dst, 1193, Dt22([reg_c]));
1643
0
#line 1031 "src/jit/x64/emit.dasc"
1644
0
            break;
1645
0
        case MVM_OP_brshift_i:
1646
0
            //| mov cl, byte WORK[reg_c];
1647
0
            //| shr rax, cl;
1648
0
            dasm_put(Dst, 1200, Dt22([reg_c]));
1649
0
#line 1035 "src/jit/x64/emit.dasc"
1650
0
            break;
1651
12
        }
1652
12
        //| mov WORK[reg_a], rax;
1653
12
        dasm_put(Dst, 886, Dt22([reg_a]));
1654
12
#line 1038 "src/jit/x64/emit.dasc"
1655
12
        break;
1656
12
    }
1657
0
    case MVM_OP_pow_i: {
1658
0
        MVMint16 dst  = ins->operands[0].reg.orig;
1659
0
        MVMint16 base = ins->operands[1].reg.orig;
1660
0
        MVMint16 exp  = ins->operands[2].reg.orig;
1661
0
        //| xor rax, rax;
1662
0
        //| mov rcx, WORK[exp];
1663
0
        //| cmp rcx, rax;
1664
0
        //| jl >3;
1665
0
        //| inc rax;
1666
0
        //| mov r8, WORK[base];
1667
0
        //|1:
1668
0
        //| test rcx, 1;
1669
0
        //| jz >2;
1670
0
        //| imul r8;
1671
0
        //|2:
1672
0
        //| imul r8, r8;
1673
0
        //| shr rcx, 1;
1674
0
        //| jnz <1;
1675
0
        //|3:
1676
0
        //| mov WORK[dst], rax;
1677
0
        dasm_put(Dst, 1208, Dt22([exp]), Dt22([base]), Dt22([dst]));
1678
0
#line 1060 "src/jit/x64/emit.dasc"
1679
0
        break;
1680
12
    }
1681
52
    case MVM_OP_div_i: {
1682
52
        MVMint16 dst = ins->operands[0].reg.orig;
1683
52
        MVMint16 a   = ins->operands[1].reg.orig;
1684
52
        MVMint16 b   = ins->operands[2].reg.orig;
1685
52
        //| mov rax, WORK[a];
1686
52
        //| mov rcx, WORK[b];
1687
52
        //| cmp rcx, 0;
1688
52
        //| jnz >1;
1689
52
        //| throw_adhoc "Division by zero";
1690
52
        dasm_put(Dst, 1270, Dt22([a]), Dt22([b]), (unsigned int)((uintptr_t)("Division by zero")), (unsigned int)(((uintptr_t)("Division by zero"))>>32));
1691
52
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1692
52
#line 1071 "src/jit/x64/emit.dasc"
1693
52
        //|1:
1694
52
        dasm_put(Dst, 1297);
1695
52
#line 1072 "src/jit/x64/emit.dasc"
1696
52
        /* either num < 0, or denom < 0, but not both */
1697
52
        //| setl dh;
1698
52
        //| cmp rax, 0;
1699
52
        //| setl dl;
1700
52
        //| xor dl, dh;
1701
52
        //| movzx r8d, dl;
1702
52
        //| cqo;
1703
52
        //| idiv rcx;
1704
52
        //| test rdx, rdx;
1705
52
        //| setnz cl;
1706
52
        //| and r8b, cl;
1707
52
        dasm_put(Dst, 1305);
1708
52
#line 1083 "src/jit/x64/emit.dasc"
1709
52
        /* r8 = bias = (modulo != 0) & ((num < 0) ^ (denom < 0)) */
1710
52
        //| sub rax, r8;
1711
52
        //| mov WORK[dst], rax;
1712
52
        dasm_put(Dst, 1340, Dt22([dst]));
1713
52
#line 1086 "src/jit/x64/emit.dasc"
1714
52
        break;
1715
12
    }
1716
152
    case MVM_OP_mod_i: {
1717
152
        MVMint16 dst = ins->operands[0].reg.orig;
1718
152
        MVMint16 a   = ins->operands[1].reg.orig;
1719
152
        MVMint16 b   = ins->operands[2].reg.orig;
1720
152
        //| mov rax, WORK[a];
1721
152
        //| mov rcx, WORK[b];
1722
152
        //| cmp rcx, 0;
1723
152
        //| jnz >1;
1724
152
        //| throw_adhoc "Division by zero";
1725
152
        dasm_put(Dst, 1270, Dt22([a]), Dt22([b]), (unsigned int)((uintptr_t)("Division by zero")), (unsigned int)(((uintptr_t)("Division by zero"))>>32));
1726
152
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1727
152
#line 1097 "src/jit/x64/emit.dasc"
1728
152
        //|1:
1729
152
        //| cqo;
1730
152
        //| idiv rcx;
1731
152
        //| mov WORK[dst], rdx;
1732
152
        dasm_put(Dst, 1348, Dt22([dst]));
1733
152
#line 1101 "src/jit/x64/emit.dasc"
1734
152
        break;
1735
12
    }
1736
0
    case MVM_OP_inc_i: {
1737
0
         MVMint32 reg = ins->operands[0].reg.orig;
1738
0
         //| add qword WORK[reg], 1;
1739
0
         dasm_put(Dst, 1367, Dt22([reg]));
1740
0
#line 1106 "src/jit/x64/emit.dasc"
1741
0
         break;
1742
12
    }
1743
119
    case MVM_OP_dec_i: {
1744
119
        MVMint32 reg = ins->operands[0].reg.orig;
1745
119
        //| sub qword WORK[reg], 1;
1746
119
        dasm_put(Dst, 1373, Dt22([reg]));
1747
119
#line 1111 "src/jit/x64/emit.dasc"
1748
119
        break;
1749
12
    }
1750
0
    case MVM_OP_bnot_i: {
1751
0
        MVMint16 dst = ins->operands[0].reg.orig;
1752
0
        MVMint16 src = ins->operands[1].reg.orig;
1753
0
        //| mov TMP1, WORK[src];
1754
0
        //| not TMP1;
1755
0
        //| mov WORK[dst], TMP1;
1756
0
        dasm_put(Dst, 1379, Dt22([src]), Dt22([dst]));
1757
0
#line 1119 "src/jit/x64/emit.dasc"
1758
0
        break;
1759
12
    }
1760
0
    case MVM_OP_neg_i: {
1761
0
        MVMint16 dst = ins->operands[0].reg.orig;
1762
0
        MVMint16 src = ins->operands[1].reg.orig;
1763
0
        //| mov TMP1, WORK[src];
1764
0
        //| neg TMP1;
1765
0
        //| mov WORK[dst], TMP1;
1766
0
        dasm_put(Dst, 1392, Dt22([src]), Dt22([dst]));
1767
0
#line 1127 "src/jit/x64/emit.dasc"
1768
0
        break;
1769
12
    }
1770
0
    case MVM_OP_extend_i32: {
1771
0
        MVMint16 dst = ins->operands[0].reg.orig;
1772
0
        MVMint16 src = ins->operands[1].reg.orig;
1773
0
        //| mov RV, WORK[src];
1774
0
        //| cdqe
1775
0
        //| mov WORK[dst], RV;
1776
0
        dasm_put(Dst, 1405, Dt22([src]), Dt22([dst]));
1777
0
#line 1135 "src/jit/x64/emit.dasc"
1778
0
        break;
1779
12
    }
1780
0
    case MVM_OP_trunc_i16: {
1781
0
        MVMint16 dst = ins->operands[0].reg.orig;
1782
0
        MVMint16 src = ins->operands[1].reg.orig;
1783
0
        //| mov TMP1, WORK[src];
1784
0
        dasm_put(Dst, 1416, Dt22([src]));
1785
0
#line 1141 "src/jit/x64/emit.dasc"
1786
0
        /* x86-64 auto-truncates the upper 48 bits when using registers in 16
1787
0
         * bit mode */
1788
0
        //| mov TMP2w, TMP1w;
1789
0
        //| mov WORK[dst], TMP2;
1790
0
        dasm_put(Dst, 1421, Dt22([dst]));
1791
0
#line 1145 "src/jit/x64/emit.dasc"
1792
0
        break;
1793
12
    }
1794
0
    case MVM_OP_trunc_i32: {
1795
0
        MVMint16 dst = ins->operands[0].reg.orig;
1796
0
        MVMint16 src = ins->operands[1].reg.orig;
1797
0
        //| mov TMP1, WORK[src];
1798
0
        dasm_put(Dst, 1416, Dt22([src]));
1799
0
#line 1151 "src/jit/x64/emit.dasc"
1800
0
        /* x86-64 auto-truncates the upper 32 bits when using registers in 32
1801
0
         * bit mode */
1802
0
        //| mov TMP2d, TMP1d;
1803
0
        //| mov WORK[dst], TMP2;
1804
0
        dasm_put(Dst, 1422, Dt22([dst]));
1805
0
#line 1155 "src/jit/x64/emit.dasc"
1806
0
        break;
1807
12
    }
1808
438
    case MVM_OP_add_n:
1809
438
    case MVM_OP_sub_n:
1810
438
    case MVM_OP_mul_n:
1811
438
    case MVM_OP_div_n: {
1812
438
        MVMint16 reg_a = ins->operands[0].reg.orig;
1813
438
        MVMint16 reg_b = ins->operands[1].reg.orig;
1814
438
        MVMint16 reg_c = ins->operands[2].reg.orig;
1815
438
        /* Copying data to xmm (floating point) registers requires
1816
438
         * a special move instruction */
1817
438
        //| movsd xmm0, qword WORK[reg_b];
1818
438
        dasm_put(Dst, 1429, Dt22([reg_b]));
1819
438
#line 1167 "src/jit/x64/emit.dasc"
1820
438
        switch(ins->info->opcode) {
1821
121
        case MVM_OP_add_n:
1822
121
            //| addsd xmm0, qword WORK[reg_c];
1823
121
            dasm_put(Dst, 1436, Dt22([reg_c]));
1824
121
#line 1170 "src/jit/x64/emit.dasc"
1825
121
            break;
1826
119
        case MVM_OP_sub_n:
1827
119
            //| subsd xmm0, qword WORK[reg_c];
1828
119
            dasm_put(Dst, 1443, Dt22([reg_c]));
1829
119
#line 1173 "src/jit/x64/emit.dasc"
1830
119
            break;
1831
1
        case MVM_OP_mul_n:
1832
1
            //| mulsd xmm0, qword WORK[reg_c];
1833
1
            dasm_put(Dst, 1450, Dt22([reg_c]));
1834
1
#line 1176 "src/jit/x64/emit.dasc"
1835
1
            break;
1836
197
        case MVM_OP_div_n:
1837
197
            //| divsd xmm0, qword WORK[reg_c];
1838
197
            dasm_put(Dst, 1457, Dt22([reg_c]));
1839
197
#line 1179 "src/jit/x64/emit.dasc"
1840
197
            break;
1841
438
        }
1842
438
        //| movsd qword WORK[reg_a], xmm0;
1843
438
        dasm_put(Dst, 1464, Dt22([reg_a]));
1844
438
#line 1182 "src/jit/x64/emit.dasc"
1845
438
        break;
1846
438
    }
1847
2.70k
    case MVM_OP_coerce_in: {
1848
2.70k
        MVMint16 dst = ins->operands[0].reg.orig;
1849
2.70k
        MVMint16 src = ins->operands[1].reg.orig;
1850
2.70k
        /* convert simple integer to double precision */
1851
2.70k
        //| cvtsi2sd xmm0, qword WORK[src];
1852
2.70k
        //| movsd qword WORK[dst], xmm0;
1853
2.70k
        dasm_put(Dst, 1471, Dt22([src]), Dt22([dst]));
1854
2.70k
#line 1190 "src/jit/x64/emit.dasc"
1855
2.70k
        break;
1856
438
    }
1857
4.72k
    case MVM_OP_coerce_ni: {
1858
4.72k
        MVMint16 dst = ins->operands[0].reg.orig;
1859
4.72k
        MVMint16 src = ins->operands[1].reg.orig;
1860
4.72k
        /* convert double precision to simple intege */
1861
4.72k
        //| cvttsd2si rax, qword WORK[src];
1862
4.72k
        //| mov WORK[dst], rax;
1863
4.72k
        dasm_put(Dst, 1485, Dt22([src]), Dt22([dst]));
1864
4.72k
#line 1198 "src/jit/x64/emit.dasc"
1865
4.72k
        break;
1866
438
    }
1867
6
    case MVM_OP_neg_n: {
1868
6
        /* Negation is xor-ing the highest byte. Pretty simple right */
1869
6
        MVMint16 dst = ins->operands[0].reg.orig;
1870
6
        MVMint16 src = ins->operands[1].reg.orig;
1871
6
        //| mov TMP1, 1;
1872
6
        //| sal TMP1, 63;
1873
6
        //| mov TMP2, qword WORK[src];
1874
6
        //| xor TMP2, TMP1;
1875
6
        //| mov qword WORK[dst], TMP2;
1876
6
        dasm_put(Dst, 1497, Dt22([src]), Dt22([dst]));
1877
6
#line 1209 "src/jit/x64/emit.dasc"
1878
6
        break;
1879
438
    }
1880
5.68k
    case MVM_OP_eq_i:
1881
5.68k
    case MVM_OP_eqaddr:
1882
5.68k
    case MVM_OP_ne_i:
1883
5.68k
    case MVM_OP_lt_i:
1884
5.68k
    case MVM_OP_le_i:
1885
5.68k
    case MVM_OP_gt_i:
1886
5.68k
    case MVM_OP_ge_i: {
1887
5.68k
        MVMint32 reg_a = ins->operands[0].reg.orig;
1888
5.68k
        MVMint32 reg_b = ins->operands[1].reg.orig;
1889
5.68k
        MVMint32 reg_c = ins->operands[2].reg.orig;
1890
5.68k
        //| mov rax, WORK[reg_b];
1891
5.68k
        dasm_put(Dst, 1105, Dt22([reg_b]));
1892
5.68k
#line 1222 "src/jit/x64/emit.dasc"
1893
5.68k
        /* comparison result in the setting bits in the rflags register */
1894
5.68k
        //| cmp rax, WORK[reg_c];
1895
5.68k
        dasm_put(Dst, 1520, Dt22([reg_c]));
1896
5.68k
#line 1224 "src/jit/x64/emit.dasc"
1897
5.68k
        /* copy the right comparison bit to the lower byte of the rax
1898
5.68k
           register */
1899
5.68k
        switch(ins->info->opcode) {
1900
1.55k
        case MVM_OP_eqaddr:
1901
1.55k
        case MVM_OP_eq_i:
1902
1.55k
            //| sete al;
1903
1.55k
            dasm_put(Dst, 1525);
1904
1.55k
#line 1230 "src/jit/x64/emit.dasc"
1905
1.55k
            break;
1906
143
        case MVM_OP_ne_i:
1907
143
            //| setne al;
1908
143
            dasm_put(Dst, 1529);
1909
143
#line 1233 "src/jit/x64/emit.dasc"
1910
143
            break;
1911
3.03k
        case MVM_OP_lt_i:
1912
3.03k
            //| setl al;
1913
3.03k
            dasm_put(Dst, 1533);
1914
3.03k
#line 1236 "src/jit/x64/emit.dasc"
1915
3.03k
            break;
1916
6
        case MVM_OP_le_i:
1917
6
            //| setle al;
1918
6
            dasm_put(Dst, 1537);
1919
6
#line 1239 "src/jit/x64/emit.dasc"
1920
6
            break;
1921
566
        case MVM_OP_gt_i:
1922
566
            //| setg al;
1923
566
            dasm_put(Dst, 1541);
1924
566
#line 1242 "src/jit/x64/emit.dasc"
1925
566
            break;
1926
385
        case MVM_OP_ge_i:
1927
385
            //| setge al;
1928
385
            dasm_put(Dst, 1545);
1929
385
#line 1245 "src/jit/x64/emit.dasc"
1930
385
            break;
1931
5.68k
        }
1932
5.68k
        /* zero extend al (lower byte) to rax (whole register) */
1933
5.68k
        //| movzx rax, al;
1934
5.68k
        //| mov WORK[reg_a], rax;
1935
5.68k
        dasm_put(Dst, 1549, Dt22([reg_a]));
1936
5.68k
#line 1250 "src/jit/x64/emit.dasc"
1937
5.68k
        break;
1938
5.68k
    }
1939
0
    case MVM_OP_cmp_i : {
1940
0
        MVMint32 reg_a = ins->operands[0].reg.orig;
1941
0
        MVMint32 reg_b = ins->operands[1].reg.orig;
1942
0
        MVMint32 reg_c = ins->operands[2].reg.orig;
1943
0
        //| mov TMP1, WORK[reg_b];
1944
0
        dasm_put(Dst, 1416, Dt22([reg_b]));
1945
0
#line 1257 "src/jit/x64/emit.dasc"
1946
0
        /* comparison result in the setting bits in the rflags register */
1947
0
        //| cmp TMP1, WORK[reg_c];
1948
0
        dasm_put(Dst, 1558, Dt22([reg_c]));
1949
0
#line 1259 "src/jit/x64/emit.dasc"
1950
0
        /* copy the right comparison bit to the lower byte of the rax
1951
0
           register */
1952
0
        //| setg TMP2b;
1953
0
        //| movzx TMP2, TMP2b;
1954
0
        //| setl TMP3b;
1955
0
        //| movzx TMP3, TMP3b;
1956
0
        //| sub TMP2, TMP3;
1957
0
        //| mov WORK[reg_a], TMP2;
1958
0
        dasm_put(Dst, 1563, Dt22([reg_a]));
1959
0
#line 1267 "src/jit/x64/emit.dasc"
1960
0
        break;
1961
5.68k
    }
1962
0
    case MVM_OP_gt_s:
1963
0
    case MVM_OP_ge_s:
1964
0
    case MVM_OP_lt_s:
1965
0
    case MVM_OP_le_s: {
1966
0
        /* src/jit/graph.c already put a call to the MVM_string_compare
1967
0
           function into the graph, so here we just have to deal with the
1968
0
           returned integers. */
1969
0
        MVMint32 reg = ins->operands[0].reg.orig;
1970
0
        switch(ins->info->opcode) {
1971
0
            case MVM_OP_gt_s:
1972
0
                //| mov TMP2, 1;
1973
0
                dasm_put(Dst, 1586);
1974
0
#line 1280 "src/jit/x64/emit.dasc"
1975
0
                break;
1976
0
            case MVM_OP_lt_s:
1977
0
                //| mov TMP2, -1;
1978
0
                dasm_put(Dst, 1594);
1979
0
#line 1283 "src/jit/x64/emit.dasc"
1980
0
                break;
1981
0
            case MVM_OP_ge_s: case MVM_OP_le_s:
1982
0
                //| mov TMP2, 0;
1983
0
                dasm_put(Dst, 1606);
1984
0
#line 1286 "src/jit/x64/emit.dasc"
1985
0
                break;
1986
0
        }
1987
0
        //| cmp TMP2, WORK[reg];
1988
0
        dasm_put(Dst, 1614, Dt22([reg]));
1989
0
#line 1289 "src/jit/x64/emit.dasc"
1990
0
        /* Mind the reversedness of the constant and the value as compared to
1991
0
         * interp.c */
1992
0
        switch(ins->info->opcode) {
1993
0
            case MVM_OP_gt_s:
1994
0
                //| sete al;
1995
0
                dasm_put(Dst, 1525);
1996
0
#line 1294 "src/jit/x64/emit.dasc"
1997
0
                break;
1998
0
            case MVM_OP_ge_s:
1999
0
                //| setle al;
2000
0
                dasm_put(Dst, 1537);
2001
0
#line 1297 "src/jit/x64/emit.dasc"
2002
0
                break;
2003
0
            case MVM_OP_lt_s:
2004
0
                //| sete al;
2005
0
                dasm_put(Dst, 1525);
2006
0
#line 1300 "src/jit/x64/emit.dasc"
2007
0
                break;
2008
0
            case MVM_OP_le_s:
2009
0
                //| setge al;
2010
0
                dasm_put(Dst, 1545);
2011
0
#line 1303 "src/jit/x64/emit.dasc"
2012
0
                break;
2013
0
        }
2014
0
        //| movzx rax, al;
2015
0
        //| mov WORK[reg], rax;
2016
0
        dasm_put(Dst, 1549, Dt22([reg]));
2017
0
#line 1307 "src/jit/x64/emit.dasc"
2018
0
        break;
2019
0
    }
2020
433
    case MVM_OP_not_i: {
2021
433
        MVMint16 dst = ins->operands[0].reg.orig;
2022
433
        MVMint16 src = ins->operands[1].reg.orig;
2023
433
        //| mov TMP1, WORK[src];
2024
433
        //| test TMP1, TMP1;
2025
433
        //| setz TMP2b;
2026
433
        //| movzx TMP2, TMP2b;
2027
433
        //| mov WORK[dst], TMP2;
2028
433
        dasm_put(Dst, 985, Dt22([src]), Dt22([dst]));
2029
433
#line 1317 "src/jit/x64/emit.dasc"
2030
433
        break;
2031
0
    }
2032
3.49k
    case MVM_OP_eq_n:
2033
3.49k
    case MVM_OP_ne_n:
2034
3.49k
    case MVM_OP_le_n:
2035
3.49k
    case MVM_OP_lt_n:
2036
3.49k
    case MVM_OP_ge_n:
2037
3.49k
    case MVM_OP_gt_n: {
2038
3.49k
        MVMint16 dst = ins->operands[0].reg.orig;
2039
3.49k
        MVMint16 a   = ins->operands[1].reg.orig;
2040
3.49k
        MVMint16 b   = ins->operands[2].reg.orig;
2041
3.49k
        if (op == MVM_OP_eq_n) {
2042
1.83k
            //| mov TMP1, 0;
2043
1.83k
            dasm_put(Dst, 1619);
2044
1.83k
#line 1330 "src/jit/x64/emit.dasc"
2045
1.65k
        } else if (op == MVM_OP_ne_n) {
2046
311
            //| mov TMP1, 1;
2047
311
            dasm_put(Dst, 1627);
2048
311
#line 1332 "src/jit/x64/emit.dasc"
2049
311
        }
2050
3.49k
        if (op == MVM_OP_lt_n || op == MVM_OP_le_n) {
2051
434
            //| movsd xmm0, qword WORK[b];
2052
434
            //| ucomisd xmm0, qword WORK[a];
2053
434
            dasm_put(Dst, 1635, Dt22([b]), Dt22([a]));
2054
434
#line 1336 "src/jit/x64/emit.dasc"
2055
3.05k
        } else {
2056
3.05k
            //| movsd xmm0, qword WORK[a];
2057
3.05k
            //| ucomisd xmm0, qword WORK[b];
2058
3.05k
            dasm_put(Dst, 1635, Dt22([a]), Dt22([b]));
2059
3.05k
#line 1339 "src/jit/x64/emit.dasc"
2060
3.05k
        }
2061
3.49k
2062
3.49k
        if (op == MVM_OP_le_n || op == MVM_OP_ge_n) {
2063
617
            //| setae TMP1b;
2064
617
            dasm_put(Dst, 1647);
2065
617
#line 1343 "src/jit/x64/emit.dasc"
2066
2.87k
        } else if (op == MVM_OP_eq_n) {
2067
1.83k
            //| setnp TMP2b; // zero if either is NaN, 1 otherwise
2068
1.83k
            //| cmove TMP1, TMP2; // if equal, overwrite 0 with 1
2069
1.83k
            dasm_put(Dst, 1651);
2070
1.83k
#line 1346 "src/jit/x64/emit.dasc"
2071
1.03k
        } else if (op == MVM_OP_ne_n) {
2072
311
            //| setp TMP2b; // 1 if either is NaN (in which case they can't be equal)
2073
311
            //| cmove TMP1, TMP2; // if equal, overwrite 1 with IsNan(a) | IsNaN(b)
2074
311
            dasm_put(Dst, 1659);
2075
311
#line 1349 "src/jit/x64/emit.dasc"
2076
727
        } else {
2077
727
            //| seta TMP1b;
2078
727
            dasm_put(Dst, 1667);
2079
727
#line 1351 "src/jit/x64/emit.dasc"
2080
727
        }
2081
3.49k
        //| movzx TMP1, TMP1b;
2082
3.49k
        //| mov WORK[dst], TMP1;
2083
3.49k
        dasm_put(Dst, 1671, Dt22([dst]));
2084
3.49k
#line 1354 "src/jit/x64/emit.dasc"
2085
3.49k
        break;
2086
3.49k
    }
2087
0
    case MVM_OP_cmp_n: {
2088
0
        MVMint16 dst = ins->operands[0].reg.orig;
2089
0
        MVMint16 a   = ins->operands[1].reg.orig;
2090
0
        MVMint16 b   = ins->operands[2].reg.orig;
2091
0
        //| movsd xmm0, qword WORK[a];
2092
0
        //| movsd xmm1, qword WORK[b];
2093
0
        //| ucomisd xmm0, xmm1
2094
0
        //| seta TMP1b;
2095
0
        //| movzx rax, TMP1b;
2096
0
        //| ucomisd xmm1, xmm0
2097
0
        //| seta TMP1b;
2098
0
        //| movzx TMP1, TMP1b;
2099
0
        //| sub rax, TMP1;
2100
0
        //| mov WORK[dst], rax;
2101
0
        dasm_put(Dst, 1680, Dt22([a]), Dt22([b]), Dt22([dst]));
2102
0
#line 1370 "src/jit/x64/emit.dasc"
2103
0
        break;
2104
3.49k
    }
2105
0
    case MVM_OP_eq_I:
2106
0
    case MVM_OP_ne_I:
2107
0
    case MVM_OP_lt_I:
2108
0
    case MVM_OP_le_I:
2109
0
    case MVM_OP_gt_I:
2110
0
    case MVM_OP_ge_I: {
2111
0
        MVMint32 reg_a = ins->operands[0].reg.orig;
2112
0
        MVMint32 reg_b = ins->operands[1].reg.orig;
2113
0
        MVMint32 reg_c = ins->operands[2].reg.orig;
2114
0
        /* Call the bigint comparison function. */
2115
0
        //| mov ARG1, tc;
2116
0
        //| mov ARG2, WORK[reg_b];
2117
0
        //| mov ARG3, WORK[reg_c];
2118
0
        //| callp &MVM_bigint_cmp;
2119
0
        dasm_put(Dst, 1722, tc, Dt22([reg_b]), Dt22([reg_c]));
2120
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_bigint_cmp)), (MVMuint32)((uintptr_t)(&MVM_bigint_cmp) >> 32));
2121
0
        dasm_put(Dst, 216);
2122
0
#line 1386 "src/jit/x64/emit.dasc"
2123
0
        /* Handle result by opcode. */
2124
0
        switch(ins->info->opcode) {
2125
0
        case MVM_OP_eq_I:
2126
0
            //| cmp RV, MP_EQ
2127
0
            //| sete al;
2128
0
            dasm_put(Dst, 1736, MP_EQ);
2129
0
#line 1391 "src/jit/x64/emit.dasc"
2130
0
            break;
2131
0
        case MVM_OP_ne_I:
2132
0
            //| cmp RV, MP_EQ
2133
0
            //| setne al;
2134
0
            dasm_put(Dst, 1745, MP_EQ);
2135
0
#line 1395 "src/jit/x64/emit.dasc"
2136
0
            break;
2137
0
        case MVM_OP_lt_I:
2138
0
            //| cmp RV, MP_LT
2139
0
            //| sete al;
2140
0
            dasm_put(Dst, 1736, MP_LT);
2141
0
#line 1399 "src/jit/x64/emit.dasc"
2142
0
            break;
2143
0
        case MVM_OP_le_I:
2144
0
            //| cmp RV, MP_GT
2145
0
            //| setne al;
2146
0
            dasm_put(Dst, 1745, MP_GT);
2147
0
#line 1403 "src/jit/x64/emit.dasc"
2148
0
            break;
2149
0
        case MVM_OP_gt_I:
2150
0
            //| cmp RV, MP_GT
2151
0
            //| sete al;
2152
0
            dasm_put(Dst, 1736, MP_GT);
2153
0
#line 1407 "src/jit/x64/emit.dasc"
2154
0
            break;
2155
0
        case MVM_OP_ge_I:
2156
0
            //| cmp RV, MP_LT
2157
0
            //| setne al;
2158
0
            dasm_put(Dst, 1745, MP_LT);
2159
0
#line 1411 "src/jit/x64/emit.dasc"
2160
0
            break;
2161
0
        }
2162
0
        /* zero extend al (lower byte) to rax (whole register) */
2163
0
        //| movzx rax, al;
2164
0
        //| mov WORK[reg_a], rax;
2165
0
        dasm_put(Dst, 1549, Dt22([reg_a]));
2166
0
#line 1416 "src/jit/x64/emit.dasc"
2167
0
        break;
2168
0
    }
2169
17
    case MVM_OP_isint:
2170
17
    case MVM_OP_isnum:
2171
17
    case MVM_OP_isstr:
2172
17
    case MVM_OP_islist:
2173
17
    case MVM_OP_ishash: {
2174
17
        MVMint16 dst = ins->operands[0].reg.orig;
2175
17
        MVMint16 obj = ins->operands[1].reg.orig;
2176
17
        MVMint32 reprid = op == MVM_OP_isint ? MVM_REPR_ID_P6int :
2177
17
                          op == MVM_OP_isnum ? MVM_REPR_ID_P6num :
2178
17
                          op == MVM_OP_isstr ? MVM_REPR_ID_P6str :
2179
6
                          op == MVM_OP_islist ? MVM_REPR_ID_VMArray :
2180
6
                     /*  op == MVM_OP_ishash */ MVM_REPR_ID_MVMHash;
2181
17
        //| mov TMP1, aword WORK[obj];
2182
17
        //| test TMP1, TMP1;
2183
17
        //| jz >1;
2184
17
        //| mov TMP1, OBJECT:TMP1->st;
2185
17
        //| mov TMP1, STABLE:TMP1->REPR;
2186
17
        //| cmp qword REPR:TMP1->ID, reprid;
2187
17
        //| jne >1;
2188
17
        //| mov qword WORK[dst], 1;
2189
17
        //| jmp >2;
2190
17
        //|1:
2191
17
        //| mov qword WORK[dst], 0;
2192
17
        //|2:
2193
17
        dasm_put(Dst, 1754, Dt22([obj]), DtE(->st), Dt12(->REPR), Dt13(->ID), reprid, Dt22([dst]), Dt22([dst]));
2194
17
#line 1442 "src/jit/x64/emit.dasc"
2195
17
        break;
2196
17
    }
2197
0
    case MVM_OP_sp_boolify_iter_arr: {
2198
0
        MVMint16 dst = ins->operands[0].reg.orig;
2199
0
        MVMint16 obj = ins->operands[1].reg.orig;
2200
0
        //| mov TMP1, aword WORK[obj];
2201
0
        //| mov TMP2, MVMITER:TMP1->body.array_state.index;
2202
0
        //| add TMP2, 1;
2203
0
        //| mov TMP3, MVMITER:TMP1->body.array_state.limit;
2204
0
        dasm_put(Dst, 1807, Dt22([obj]), DtB(->body.array_state.index), DtB(->body.array_state.limit));
2205
0
#line 1451 "src/jit/x64/emit.dasc"
2206
0
        /* index - limit will give a carry flag when index < limit */
2207
0
        //| cmp TMP2, TMP3;
2208
0
        //| setl TMP1b;
2209
0
        //| movzx TMP1, TMP1b;
2210
0
        //| mov aword WORK[dst], TMP1;
2211
0
        dasm_put(Dst, 1824, Dt22([dst]));
2212
0
#line 1456 "src/jit/x64/emit.dasc"
2213
0
        break;
2214
17
    }
2215
0
    case MVM_OP_sp_boolify_iter_hash: {
2216
0
        MVMint16 dst = ins->operands[0].reg.orig;
2217
0
        MVMint16 obj = ins->operands[1].reg.orig;
2218
0
        //| mov TMP1, aword WORK[obj];
2219
0
        //| mov TMP2, MVMITER:TMP1->body.hash_state.next;
2220
0
        //| test TMP2, TMP2;
2221
0
        //| setnz TMP2b;
2222
0
        //| movzx TMP2, TMP2b;
2223
0
        //| mov aword WORK[dst], TMP2;
2224
0
        dasm_put(Dst, 1839, Dt22([obj]), DtB(->body.hash_state.next), Dt22([dst]));
2225
0
#line 1467 "src/jit/x64/emit.dasc"
2226
0
        break;
2227
17
    }
2228
1
    case MVM_OP_objprimspec: {
2229
1
        MVMint16 dst  = ins->operands[0].reg.orig;
2230
1
        MVMint16 type = ins->operands[1].reg.orig;
2231
1
        //| mov TMP6, aword WORK[type];
2232
1
        //| test TMP6, TMP6;
2233
1
        //| jz >1;
2234
1
        //| mov ARG2, OBJECT:TMP6->st;
2235
1
        //| mov FUNCTION, STABLE:ARG2->REPR;
2236
1
        //| mov FUNCTION, REPR:FUNCTION->get_storage_spec;
2237
1
        //| mov ARG1, TC;
2238
1
        //| call FUNCTION;
2239
1
        //| movzx TMP6, word STORAGESPEC:RV->boxed_primitive;
2240
1
        //|1:
2241
1
        //| mov aword WORK[dst], TMP6;
2242
1
        dasm_put(Dst, 1862, Dt22([type]), DtE(->st), Dt12(->REPR), Dt13(->get_storage_spec), Dt18(->boxed_primitive), Dt22([dst]));
2243
1
#line 1483 "src/jit/x64/emit.dasc"
2244
1
        break;
2245
17
    }
2246
0
    case MVM_OP_objprimbits: {
2247
0
        MVMint16 dst  = ins->operands[0].reg.orig;
2248
0
        MVMint16 type = ins->operands[1].reg.orig;
2249
0
        //| mov TMP6, aword WORK[type];
2250
0
        //| test TMP6, TMP6;
2251
0
        //| jz >1;
2252
0
        //| mov ARG2, OBJECT:TMP6->st;
2253
0
        //| mov FUNCTION, STABLE:ARG2->REPR;
2254
0
        //| mov FUNCTION, REPR:FUNCTION->get_storage_spec;
2255
0
        //| mov ARG1, TC;
2256
0
        //| call FUNCTION;
2257
0
        //| movzx TMP6, word STORAGESPEC:RV->boxed_primitive;
2258
0
        //| test TMP6, TMP6;
2259
0
        //| jz >1;
2260
0
        //| movzx TMP6, word STORAGESPEC:RV->bits;
2261
0
        //|1:
2262
0
        //| mov aword WORK[dst], TMP6;
2263
0
        dasm_put(Dst, 1905, Dt22([type]), DtE(->st), Dt12(->REPR), Dt13(->get_storage_spec), Dt18(->boxed_primitive), Dt18(->bits), Dt22([dst]));
2264
0
#line 1502 "src/jit/x64/emit.dasc"
2265
0
        break;
2266
17
    }
2267
666
    case MVM_OP_isnonnull: {
2268
666
        MVMint16 dst = ins->operands[0].reg.orig;
2269
666
        MVMint16 obj = ins->operands[1].reg.orig;
2270
666
        //| mov TMP1, WORK[obj];
2271
666
        //| test TMP1, TMP1;
2272
666
        //| setnz TMP2b;
2273
666
        //| get_vmnull TMP3;
2274
666
        //| cmp TMP1, TMP3;
2275
666
        //| setne TMP3b;
2276
666
        //| and TMP2b, TMP3b;
2277
666
        //| movzx TMP2, TMP2b;
2278
666
        //| mov WORK[dst], TMP2;
2279
666
        dasm_put(Dst, 1960, Dt22([obj]), Dt21(->instance), DtC(->VMNull), Dt22([dst]));
2280
666
#line 1516 "src/jit/x64/emit.dasc"
2281
666
        break;
2282
17
    }
2283
510
    case MVM_OP_isnull: {
2284
510
        MVMint16 dst = ins->operands[0].reg.orig;
2285
510
        MVMint16 obj = ins->operands[1].reg.orig;
2286
510
        //| mov TMP1, WORK[obj];
2287
510
        //| test TMP1, TMP1;
2288
510
        //| setz TMP2b;
2289
510
        //| get_vmnull TMP3;
2290
510
        //| cmp TMP1, TMP3;
2291
510
        //| sete TMP3b;
2292
510
        //| or TMP2b, TMP3b;
2293
510
        //| movzx TMP2, TMP2b;
2294
510
        //| mov WORK[dst], TMP2;
2295
510
        dasm_put(Dst, 1997, Dt22([obj]), Dt21(->instance), DtC(->VMNull), Dt22([dst]));
2296
510
#line 1530 "src/jit/x64/emit.dasc"
2297
510
        break;
2298
17
    }
2299
713
    case MVM_OP_sp_fastcreate: {
2300
713
        MVMint16 dst       = ins->operands[0].reg.orig;
2301
713
        MVMuint16 size     = ins->operands[1].lit_i16;
2302
713
        MVMint16 spesh_idx = ins->operands[2].lit_i16;
2303
713
        //| mov ARG1, TC;
2304
713
        //| mov ARG2, size;
2305
713
        //| callp &MVM_gc_allocate_zeroed;
2306
713
        dasm_put(Dst, 2034, size);
2307
713
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_allocate_zeroed)), (MVMuint32)((uintptr_t)(&MVM_gc_allocate_zeroed) >> 32));
2308
713
#line 1539 "src/jit/x64/emit.dasc"
2309
713
        //| get_spesh_slot TMP1, spesh_idx;
2310
713
        //| mov aword OBJECT:RV->st, TMP1;  // st is 64 bit (pointer)
2311
713
        //| mov word OBJECT:RV->header.size, size; // object size is 16 bit
2312
713
        //| mov TMP1d, dword TC->thread_id;  // thread id is 32 bit
2313
713
        //| mov dword OBJECT:RV->header.owner, TMP1d; // does this even work?
2314
713
        //| mov aword WORK[dst], RV; // store in local register
2315
713
        dasm_put(Dst, 2044, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]), DtE(->st), DtE(->header.size), size, Dt21(->thread_id), DtE(->header.owner), Dt22([dst]));
2316
713
#line 1545 "src/jit/x64/emit.dasc"
2317
713
        break;
2318
17
    }
2319
8.46k
    case MVM_OP_decont:
2320
8.46k
    case MVM_OP_sp_decont: {
2321
8.46k
        MVMint16 dst = ins->operands[0].reg.orig;
2322
8.46k
        MVMint16 src = ins->operands[1].reg.orig;
2323
8.46k
        //| mov TMP5, WORK[src];
2324
8.46k
        //| test TMP5, TMP5;
2325
8.46k
        dasm_put(Dst, 2082, Dt22([src]));
2326
8.46k
#line 1553 "src/jit/x64/emit.dasc"
2327
8.46k
        // obj is null
2328
8.46k
        //| jz >1;
2329
8.46k
        //| test_type_object TMP5;
2330
8.46k
        dasm_put(Dst, 2090, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
2331
8.46k
#line 1556 "src/jit/x64/emit.dasc"
2332
8.46k
        // object is type object (not concrete)
2333
8.46k
        //| jnz >1;
2334
8.46k
        //| mov TMP6, OBJECT:TMP5->st;
2335
8.46k
        //| mov TMP6, STABLE:TMP6->container_spec;
2336
8.46k
        //| test TMP6, TMP6;
2337
8.46k
        dasm_put(Dst, 2102, DtE(->st), Dt12(->container_spec));
2338
8.46k
#line 1561 "src/jit/x64/emit.dasc"
2339
8.46k
        // container spec is zero
2340
8.46k
        //| jz >1;
2341
8.46k
        //| mov ARG1, TC;
2342
8.46k
        //| mov ARG2, TMP5;      // object
2343
8.46k
        //| lea ARG3, WORK[dst]; // destination register
2344
8.46k
        //| mov FUNCTION, CONTAINERSPEC:TMP6->fetch; // get function pointer
2345
8.46k
        //| call FUNCTION;
2346
8.46k
        //| jmp >2;
2347
8.46k
        //|1:
2348
8.46k
        dasm_put(Dst, 2118, Dt22([dst]), Dt17(->fetch));
2349
8.46k
#line 1570 "src/jit/x64/emit.dasc"
2350
8.46k
        // otherwise just move the object into the register
2351
8.46k
        //| mov WORK[dst], TMP5;
2352
8.46k
        //|2:
2353
8.46k
        dasm_put(Dst, 2148, Dt22([dst]));
2354
8.46k
#line 1573 "src/jit/x64/emit.dasc"
2355
8.46k
        break;
2356
8.46k
    }
2357
20
    case MVM_OP_iscont: {
2358
20
        MVMint16 dst = ins->operands[0].reg.orig;
2359
20
        MVMint16 obj = ins->operands[1].reg.orig;
2360
20
        //| mov TMP1, aword WORK[obj];
2361
20
        //| test TMP1, TMP1;
2362
20
        //| jz >1;
2363
20
        //| mov TMP1, OBJECT:TMP1->st;
2364
20
        //| mov TMP1, STABLE:TMP1->container_spec;
2365
20
        //| test TMP1, TMP1;
2366
20
        //|1:
2367
20
        //| setnz TMP1b;
2368
20
        //| movzx TMP1, TMP1b;
2369
20
        //| mov qword WORK[dst], TMP1;
2370
20
        dasm_put(Dst, 2155, Dt22([obj]), DtE(->st), Dt12(->container_spec), Dt22([dst]));
2371
20
#line 1588 "src/jit/x64/emit.dasc"
2372
20
        break;
2373
8.46k
    }
2374
12.5k
    case MVM_OP_sp_findmeth: {
2375
12.5k
        MVMint16 dst = ins->operands[0].reg.orig;
2376
12.5k
        MVMint16 obj = ins->operands[1].reg.orig;
2377
12.5k
        MVMint32 str_idx = ins->operands[2].lit_str_idx;
2378
12.5k
        MVMuint16 ss_idx = ins->operands[3].lit_i16;
2379
12.5k
        //| get_spesh_slot TMP1, ss_idx;
2380
12.5k
        //| mov TMP2, WORK[obj];
2381
12.5k
        //| mov TMP2, OBJECT:TMP2->st;
2382
12.5k
        //| cmp TMP1, TMP2;
2383
12.5k
        //| jne >1;
2384
12.5k
        //| get_spesh_slot TMP3, ss_idx + 1;
2385
12.5k
        //| mov WORK[dst], TMP3;
2386
12.5k
        //| jmp >2;
2387
12.5k
        //|1:
2388
12.5k
        dasm_put(Dst, 2191, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([ss_idx]), Dt22([obj]), DtE(->st), Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([ss_idx + 1]), Dt22([dst]));
2389
12.5k
#line 1604 "src/jit/x64/emit.dasc"
2390
12.5k
        /* call find_method_spesh */
2391
12.5k
        //| mov ARG1, TC;
2392
12.5k
        //| mov ARG2, WORK[obj];
2393
12.5k
        //| get_string ARG3, str_idx;
2394
12.5k
        dasm_put(Dst, 2241, Dt22([obj]));
2395
12.5k
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, str_idx);
2396
12.5k
#line 1608 "src/jit/x64/emit.dasc"
2397
12.5k
        //| mov ARG4, ss_idx;
2398
12.5k
        //| lea TMP6, WORK[dst];
2399
12.5k
        //|.if WIN32;
2400
12.5k
        //| mov qword [rsp+0x20], TMP6;
2401
12.5k
        //|.else;
2402
12.5k
        //| mov ARG5, TMP6;
2403
12.5k
        //|.endif
2404
12.5k
        //| callp &MVM_6model_find_method_spesh;
2405
12.5k
        dasm_put(Dst, 2250, Dt23(->body.strings), Dt15([str_idx]), ss_idx, Dt22([dst]));
2406
12.5k
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_6model_find_method_spesh)), (MVMuint32)((uintptr_t)(&MVM_6model_find_method_spesh) >> 32));
2407
12.5k
#line 1616 "src/jit/x64/emit.dasc"
2408
12.5k
        //|2:
2409
12.5k
        dasm_put(Dst, 356);
2410
12.5k
#line 1617 "src/jit/x64/emit.dasc"
2411
12.5k
        break;
2412
8.46k
    }
2413
551
    case MVM_OP_isconcrete: {
2414
551
        MVMint16 dst = ins->operands[0].reg.orig;
2415
551
        MVMint16 obj = ins->operands[1].reg.orig;
2416
551
        //| mov TMP1, WORK[obj];
2417
551
        //| test TMP1, TMP1;
2418
551
        //| jz >1;
2419
551
        //| test_type_object TMP1;
2420
551
        //| jnz >1;
2421
551
        //| mov qword WORK[dst], 1;
2422
551
        //| jmp >2;
2423
551
        //|1:
2424
551
        //| mov qword WORK[dst], 0;
2425
551
        //|2:
2426
551
        dasm_put(Dst, 2271, Dt22([obj]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, Dt22([dst]), Dt22([dst]));
2427
551
#line 1632 "src/jit/x64/emit.dasc"
2428
551
        break;
2429
8.46k
    }
2430
6
    case MVM_OP_takehandlerresult: {
2431
6
        MVMint16 dst = ins->operands[0].reg.orig;
2432
6
        //| mov TMP1, aword TC->last_handler_result;
2433
6
        //| mov aword WORK[dst], TMP1;
2434
6
        //| mov aword TC->last_handler_result, 0;
2435
6
        dasm_put(Dst, 2317, Dt21(->last_handler_result), Dt22([dst]), Dt21(->last_handler_result));
2436
6
#line 1639 "src/jit/x64/emit.dasc"
2437
6
        break;
2438
8.46k
    }
2439
0
    case MVM_OP_exception: {
2440
0
        MVMint16 dst = ins->operands[0].reg.orig;
2441
0
        //| mov TMP1, TC->active_handlers;
2442
0
        //| test TMP1, TMP1;
2443
0
        //| jz >1;
2444
0
        //| mov TMP1, MVMACTIVEHANDLERS:TMP1->ex_obj;
2445
0
        //| mov WORK[dst], TMP1;
2446
0
        //| jmp >2;
2447
0
        //|1:
2448
0
        //| get_vmnull TMP1;
2449
0
        //| mov WORK[dst], TMP1;
2450
0
        //|2:
2451
0
        dasm_put(Dst, 2334, Dt21(->active_handlers), DtD(->ex_obj), Dt22([dst]), Dt21(->instance), DtC(->VMNull), Dt22([dst]));
2452
0
#line 1653 "src/jit/x64/emit.dasc"
2453
0
        break;
2454
8.46k
    }
2455
766
    case MVM_OP_scwbdisable: {
2456
766
        MVMint16 dst = ins->operands[0].reg.orig;
2457
766
        //| mov TMP1d, dword TC->sc_wb_disable_depth;
2458
766
        //| add TMP1d, 1;
2459
766
        //| mov dword TC->sc_wb_disable_depth, TMP1d;
2460
766
        //| mov qword WORK[dst], TMP1;
2461
766
        dasm_put(Dst, 2374, Dt21(->sc_wb_disable_depth), Dt21(->sc_wb_disable_depth), Dt22([dst]));
2462
766
#line 1661 "src/jit/x64/emit.dasc"
2463
766
        break;
2464
8.46k
    }
2465
766
    case MVM_OP_scwbenable: {
2466
766
        MVMint16 dst = ins->operands[0].reg.orig;
2467
766
        //| mov TMP1d, dword TC->sc_wb_disable_depth; // should do zero-extension
2468
766
        //| sub TMP1d, 1;
2469
766
        //| mov dword TC->sc_wb_disable_depth, TMP1d;
2470
766
        //| mov qword WORK[dst], TMP1;
2471
766
        dasm_put(Dst, 2390, Dt21(->sc_wb_disable_depth), Dt21(->sc_wb_disable_depth), Dt22([dst]));
2472
766
#line 1669 "src/jit/x64/emit.dasc"
2473
766
        break;
2474
8.46k
    }
2475
0
    case MVM_OP_assign:
2476
0
    case MVM_OP_assignunchecked: {
2477
0
        MVMint16 cont = ins->operands[0].reg.orig;
2478
0
        MVMint16 obj  = ins->operands[1].reg.orig;
2479
0
        //| mov ARG2, aword WORK[cont];
2480
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2481
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2482
0
        //| test FUNCTION, FUNCTION;
2483
0
        //| jnz >1;
2484
0
        //| throw_adhoc "Cannot assign to an immutable value";
2485
0
        dasm_put(Dst, 2407, Dt22([cont]), DtE(->st), Dt12(->container_spec), (unsigned int)((uintptr_t)("Cannot assign to an immutable value")), (unsigned int)(((uintptr_t)("Cannot assign to an immutable value"))>>32));
2486
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2487
0
#line 1681 "src/jit/x64/emit.dasc"
2488
0
        //|1:
2489
0
        //| mov ARG1, TC;
2490
0
        //| mov ARG3, aword WORK[obj];
2491
0
        dasm_put(Dst, 2436, Dt22([obj]));
2492
0
#line 1684 "src/jit/x64/emit.dasc"
2493
0
        if (op == MVM_OP_assign) {
2494
0
            //| mov FUNCTION, CONTAINERSPEC:FUNCTION->store;
2495
0
            dasm_put(Dst, 184, Dt17(->store));
2496
0
#line 1686 "src/jit/x64/emit.dasc"
2497
0
        } else {
2498
0
            //| mov FUNCTION, CONTAINERSPEC:FUNCTION->store_unchecked;
2499
0
            dasm_put(Dst, 184, Dt17(->store_unchecked));
2500
0
#line 1688 "src/jit/x64/emit.dasc"
2501
0
        }
2502
0
        //| call FUNCTION;
2503
0
        dasm_put(Dst, 2452);
2504
0
#line 1690 "src/jit/x64/emit.dasc"
2505
0
        break;
2506
0
    }
2507
2.18k
    case MVM_OP_getlexstatic_o:
2508
2.18k
    case MVM_OP_getlexperinvtype_o: {
2509
2.18k
        MVMint16 dst  = ins->operands[0].reg.orig;
2510
2.18k
        MVMint16 name = ins->operands[1].reg.orig;
2511
2.18k
        //| mov ARG1, TC;
2512
2.18k
        //| mov ARG2, aword WORK[name];
2513
2.18k
        //| mov ARG3, MVM_reg_obj;
2514
2.18k
        //| callp &MVM_frame_find_lexical_by_name;
2515
2.18k
        dasm_put(Dst, 2457, Dt22([name]), MVM_reg_obj);
2516
2.18k
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name)), (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name) >> 32));
2517
2.18k
#line 1700 "src/jit/x64/emit.dasc"
2518
2.18k
        //| test RV, RV;
2519
2.18k
        //| jz >1;
2520
2.18k
        //| mov RV, [RV];
2521
2.18k
        //|1:
2522
2.18k
        //| mov WORK[dst], RV;
2523
2.18k
        dasm_put(Dst, 2471, Dt22([dst]));
2524
2.18k
#line 1705 "src/jit/x64/emit.dasc"
2525
2.18k
        break;
2526
2.18k
    }
2527
202
    case MVM_OP_paramnamesused:
2528
202
        //| mov ARG2, TC->cur_frame;
2529
202
        //| lea ARG2, FRAME:ARG2->params;
2530
202
        //| mov TMP5w, word ARGCTX:ARG2->num_pos;
2531
202
        //| cmp TMP5w, word ARGCTX:ARG2->arg_count;
2532
202
        //| je >1;
2533
202
        //| mov ARG1, TC;
2534
202
        //| callp &MVM_args_assert_nameds_used;
2535
202
        dasm_put(Dst, 2493, Dt21(->cur_frame), Dt2(->params), Dt3(->num_pos), Dt3(->arg_count));
2536
202
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_args_assert_nameds_used)), (MVMuint32)((uintptr_t)(&MVM_args_assert_nameds_used) >> 32));
2537
202
#line 1715 "src/jit/x64/emit.dasc"
2538
202
        //|1:
2539
202
        dasm_put(Dst, 1297);
2540
202
#line 1716 "src/jit/x64/emit.dasc"
2541
202
        break;
2542
0
    case MVM_OP_assertparamcheck: {
2543
0
        MVMint16 ok = ins->operands[0].reg.orig;
2544
0
        //| mov TMP1, qword WORK[ok];
2545
0
        //| test TMP1, TMP1;
2546
0
        //| jnz >1;
2547
0
        //| mov ARG1, TC;
2548
0
        //| callp &MVM_args_bind_failed;
2549
0
        dasm_put(Dst, 2521, Dt22([ok]));
2550
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_args_bind_failed)), (MVMuint32)((uintptr_t)(&MVM_args_bind_failed) >> 32));
2551
0
#line 1724 "src/jit/x64/emit.dasc"
2552
0
        //|1:
2553
0
        dasm_put(Dst, 1297);
2554
0
#line 1725 "src/jit/x64/emit.dasc"
2555
0
        break;
2556
2.18k
    }
2557
0
    case MVM_OP_prof_enterspesh:
2558
0
        //| mov ARG1, TC;
2559
0
        //| mov ARG2, TC->cur_frame;
2560
0
        //| mov ARG2, aword FRAME:ARG2->static_info;
2561
0
        //| mov ARG3, aword MVM_PROFILE_ENTER_JIT;
2562
0
        //| callp &MVM_profile_log_enter;
2563
0
        dasm_put(Dst, 2538, Dt21(->cur_frame), Dt2(->static_info), MVM_PROFILE_ENTER_JIT);
2564
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_profile_log_enter)), (MVMuint32)((uintptr_t)(&MVM_profile_log_enter) >> 32));
2565
0
        dasm_put(Dst, 216);
2566
0
#line 1733 "src/jit/x64/emit.dasc"
2567
0
        break;
2568
0
    case MVM_OP_prof_enterinline: {
2569
0
        MVMint16 spesh_idx = ins->operands[0].lit_i16;
2570
0
        //| mov ARG1, TC;
2571
0
        //| get_spesh_slot ARG2, spesh_idx;
2572
0
        //| mov ARG3, aword MVM_PROFILE_ENTER_JIT_INLINE;
2573
0
        //| callp &MVM_profile_log_enter;
2574
0
        dasm_put(Dst, 2556, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]), MVM_PROFILE_ENTER_JIT_INLINE);
2575
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_profile_log_enter)), (MVMuint32)((uintptr_t)(&MVM_profile_log_enter) >> 32));
2576
0
        dasm_put(Dst, 216);
2577
0
#line 1740 "src/jit/x64/emit.dasc"
2578
0
        break;
2579
2.18k
    }
2580
5
    case MVM_OP_getobjsc: {
2581
5
        MVMint16 dst = ins->operands[0].reg.orig;
2582
5
        MVMint16 obj = ins->operands[1].reg.orig;
2583
5
        //| mov TMP1, aword WORK[obj];
2584
5
        //| mov TMP2d, dword COLLECTABLE:TMP1->sc_forward_u.sc.sc_idx;
2585
5
        //| xor TMP3, TMP3;
2586
5
        //| cmp TMP2d, 0;
2587
5
        //| jle >1;
2588
5
        //| mov TMP3, aword TC->instance;
2589
5
        //| mov TMP3, aword MVMINSTANCE:TMP3->all_scs;
2590
5
        //| mov TMP3, aword [TMP3 + TMP2d * 8];
2591
5
        //| mov TMP3, SCREFBODY:TMP3->sc;
2592
5
        //|1:
2593
5
        //| mov aword WORK[dst], TMP3;
2594
5
        dasm_put(Dst, 2578, Dt22([obj]), Dt11(->sc_forward_u.sc.sc_idx), Dt21(->instance), DtC(->all_scs), Dt1A(->sc), Dt22([dst]));
2595
5
#line 1756 "src/jit/x64/emit.dasc"
2596
5
        break;
2597
2.18k
    }
2598
0
    case MVM_OP_invokewithcapture: {
2599
0
        MVMint16 dest    = ins->operands[0].reg.orig;
2600
0
        MVMint16 code    = ins->operands[1].reg.orig;
2601
0
        MVMint16 capture = ins->operands[2].reg.orig;
2602
0
        //| mov TMP1, aword WORK[capture];
2603
0
        dasm_put(Dst, 1416, Dt22([capture]));
2604
0
#line 1763 "src/jit/x64/emit.dasc"
2605
0
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2606
0
        //| test_type_object TMP1;
2607
0
        //| jnz >1;
2608
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCallCapture;
2609
0
        //| je >2;
2610
0
        //|1:
2611
0
        dasm_put(Dst, 2619, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture);
2612
0
#line 1769 "src/jit/x64/emit.dasc"
2613
0
        /* else throw */
2614
0
        //| throw_adhoc "invokewithcapture needs a MVMCallCapture";
2615
0
        dasm_put(Dst, 923, (unsigned int)((uintptr_t)("invokewithcapture needs a MVMCallCapture")), (unsigned int)(((uintptr_t)("invokewithcapture needs a MVMCallCapture"))>>32));
2616
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2617
0
#line 1771 "src/jit/x64/emit.dasc"
2618
0
        //|2:
2619
0
        dasm_put(Dst, 356);
2620
0
#line 1772 "src/jit/x64/emit.dasc"
2621
0
        /* code = MVM_frame_find_invokee(tc, code, NULL) */
2622
0
        //| mov ARG1, TC;
2623
0
        //| mov ARG2, WORK[code];
2624
0
        //| xor ARG3, ARG3;
2625
0
        //| callp &MVM_frame_find_invokee;
2626
0
        dasm_put(Dst, 2648, Dt22([code]));
2627
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee)), (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee) >> 32));
2628
0
        dasm_put(Dst, 216);
2629
0
#line 1777 "src/jit/x64/emit.dasc"
2630
0
2631
0
        //| mov ARG2, RV; // ARG2 = code
2632
0
        dasm_put(Dst, 2661);
2633
0
#line 1779 "src/jit/x64/emit.dasc"
2634
0
        /* tc->cur_frame->return_value = &GET_REG(cur_op, 2) */
2635
0
        //| lea ARG1, WORK[dest]; // ARG1 is used as scratch space
2636
0
        //| mov TMP6, aword TC->cur_frame;
2637
0
        //| mov aword FRAME:TMP6->return_value, ARG1;
2638
0
        dasm_put(Dst, 2665, Dt22([dest]), Dt21(->cur_frame), Dt2(->return_value));
2639
0
#line 1783 "src/jit/x64/emit.dasc"
2640
0
        /* tc->cur_frame->return_type = MVM_RETURN_OBJ */
2641
0
        //| mov byte FRAME:TMP6->return_type, MVM_RETURN_OBJ;
2642
0
        dasm_put(Dst, 2678, Dt2(->return_type), MVM_RETURN_OBJ);
2643
0
#line 1785 "src/jit/x64/emit.dasc"
2644
0
        /* tc->cur_frame->return_address = cur_op */
2645
0
        //| get_cur_op ARG1;
2646
0
        //| mov aword FRAME:TMP6->return_address, ARG1;
2647
0
        dasm_put(Dst, 2684, Dt21(->interp_cur_op), Dt2(->return_address));
2648
0
#line 1788 "src/jit/x64/emit.dasc"
2649
0
        /* STABLE(code)->invoke(tc, code, capture->body.apc->effective_callsite,
2650
0
           capture->body.apc->arg) */
2651
0
        //| mov ARG1, TC;
2652
0
        //| mov ARG3, WORK[capture];
2653
0
        //| mov ARG4, aword CAPTURE:ARG3->body.apc;
2654
0
        //| mov ARG3, aword ARGCTX:ARG4->callsite;
2655
0
        //| mov ARG4, aword ARGCTX:ARG4->args;
2656
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2657
0
        //| mov FUNCTION, STABLE:FUNCTION->invoke;
2658
0
        //| call FUNCTION;
2659
0
        dasm_put(Dst, 2696, Dt22([capture]), Dt5(->body.apc), Dt3(->callsite), Dt3(->args), DtE(->st), Dt12(->invoke));
2660
0
#line 1798 "src/jit/x64/emit.dasc"
2661
0
        /* jumping out is handled by invokish */
2662
0
        break;
2663
2.18k
    }
2664
72
    case MVM_OP_captureposelems: {
2665
72
        MVMint16 dest    = ins->operands[0].reg.orig;
2666
72
        MVMint16 capture = ins->operands[1].reg.orig;
2667
72
        //| mov TMP1, aword WORK[capture];
2668
72
        dasm_put(Dst, 1416, Dt22([capture]));
2669
72
#line 1805 "src/jit/x64/emit.dasc"
2670
72
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2671
72
        //| test_type_object TMP1;
2672
72
        //| jnz >1;
2673
72
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCallCapture;
2674
72
        //| je >2;
2675
72
        //|1:
2676
72
        dasm_put(Dst, 2619, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture);
2677
72
#line 1811 "src/jit/x64/emit.dasc"
2678
72
        /* else throw */
2679
72
        //| throw_adhoc "captureposelems needs a concrete MVMCallCapture";
2680
72
        dasm_put(Dst, 923, (unsigned int)((uintptr_t)("captureposelems needs a concrete MVMCallCapture")), (unsigned int)(((uintptr_t)("captureposelems needs a concrete MVMCallCapture"))>>32));
2681
72
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2682
72
#line 1813 "src/jit/x64/emit.dasc"
2683
72
        //|2:
2684
72
        //| mov TMP2, aword CAPTURE:TMP1->body.apc;
2685
72
        //| movzx TMP2, word ARGPROCCONTEXT:TMP2->num_pos;
2686
72
        //| mov WORK[dest], TMP2;
2687
72
        dasm_put(Dst, 2729, Dt5(->body.apc), Dt7(->num_pos), Dt22([dest]));
2688
72
#line 1817 "src/jit/x64/emit.dasc"
2689
72
        break;
2690
2.18k
    }
2691
0
    case MVM_OP_captureexistsnamed: {
2692
0
        MVMint16 dst = ins->operands[0].reg.orig;
2693
0
        MVMint16 obj = ins->operands[1].reg.orig;
2694
0
        MVMint16 name = ins->operands[2].reg.orig;
2695
0
        //| mov TMP1, WORK[obj];
2696
0
        //| test_type_object TMP1;
2697
0
        //| jnz >1;
2698
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCallCapture;
2699
0
        //| je >2;
2700
0
        //|1:
2701
0
        //| throw_adhoc "captureexistsnamed needs a MVMCallCapture";
2702
0
        dasm_put(Dst, 891, Dt22([obj]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture, (unsigned int)((uintptr_t)("captureexistsnamed needs a MVMCallCapture")), (unsigned int)(((uintptr_t)("captureexistsnamed needs a MVMCallCapture"))>>32));
2703
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2704
0
#line 1830 "src/jit/x64/emit.dasc"
2705
0
        //|2:
2706
0
        //| mov ARG2, CAPTURE:TMP1->body.apc;
2707
0
        //| mov ARG3, WORK[name];
2708
0
        //| mov ARG1, TC;
2709
0
        //| callp MVM_args_has_named;
2710
0
        dasm_put(Dst, 2750, Dt5(->body.apc), Dt22([name]));
2711
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(MVM_args_has_named)), (MVMuint32)((uintptr_t)(MVM_args_has_named) >> 32));
2712
0
#line 1835 "src/jit/x64/emit.dasc"
2713
0
        //| mov WORK[dst], RV;
2714
0
        dasm_put(Dst, 881, Dt22([dst]));
2715
0
#line 1836 "src/jit/x64/emit.dasc"
2716
0
        break;
2717
2.18k
    }
2718
0
    case MVM_OP_capturehasnameds: {
2719
0
        MVMint16 dest    = ins->operands[0].reg.orig;
2720
0
        MVMint16 capture = ins->operands[1].reg.orig;
2721
0
        //| mov TMP1, aword WORK[capture];
2722
0
        dasm_put(Dst, 1416, Dt22([capture]));
2723
0
#line 1842 "src/jit/x64/emit.dasc"
2724
0
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2725
0
        //| test_type_object TMP1;
2726
0
        //| jnz >1;
2727
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCallCapture;
2728
0
        //| je >2;
2729
0
        //|1:
2730
0
        dasm_put(Dst, 2619, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture);
2731
0
#line 1848 "src/jit/x64/emit.dasc"
2732
0
        /* else throw */
2733
0
        //| throw_adhoc "capturehasnameds needs a concrete MVMCallCapture";
2734
0
        dasm_put(Dst, 923, (unsigned int)((uintptr_t)("capturehasnameds needs a concrete MVMCallCapture")), (unsigned int)(((uintptr_t)("capturehasnameds needs a concrete MVMCallCapture"))>>32));
2735
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2736
0
#line 1850 "src/jit/x64/emit.dasc"
2737
0
        //|2:
2738
0
        //| mov TMP2, CAPTURE:TMP1->body.apc;
2739
0
        //| mov TMP3w, word ARGPROCCONTEXT:TMP2->num_pos;
2740
0
        //| mov TMP2w, word ARGPROCCONTEXT:TMP2->arg_count;
2741
0
        //| cmp TMP2w, TMP3w;
2742
0
        //| setne al;
2743
0
        //| movzx rax, al;
2744
0
        //| mov WORK[dest], rax;
2745
0
        dasm_put(Dst, 2771, Dt5(->body.apc), Dt7(->num_pos), Dt7(->arg_count), Dt22([dest]));
2746
0
#line 1858 "src/jit/x64/emit.dasc"
2747
0
        break;
2748
2.18k
    }
2749
0
    case MVM_OP_capturenamedshash: {
2750
0
        MVMint16 dst = ins->operands[0].reg.orig;
2751
0
        MVMint16 obj = ins->operands[1].reg.orig;
2752
0
        //| mov TMP1, WORK[obj];
2753
0
        //| test_type_object TMP1;
2754
0
        //| jnz >1;
2755
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCallCapture;
2756
0
        //| je >2;
2757
0
        //|1:
2758
0
        //| throw_adhoc "capturenamedshash needs a MVMCallCapture";
2759
0
        dasm_put(Dst, 891, Dt22([obj]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCallCapture, (unsigned int)((uintptr_t)("capturenamedshash needs a MVMCallCapture")), (unsigned int)(((uintptr_t)("capturenamedshash needs a MVMCallCapture"))>>32));
2760
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2761
0
#line 1870 "src/jit/x64/emit.dasc"
2762
0
        //|2:
2763
0
        //| mov ARG2, CAPTURE:TMP1->body.apc;
2764
0
        //| mov ARG1, TC;
2765
0
        //| callp MVM_args_slurpy_named;
2766
0
        dasm_put(Dst, 2807, Dt5(->body.apc));
2767
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(MVM_args_slurpy_named)), (MVMuint32)((uintptr_t)(MVM_args_slurpy_named) >> 32));
2768
0
#line 1874 "src/jit/x64/emit.dasc"
2769
0
        //| mov WORK[dst], RV;
2770
0
        dasm_put(Dst, 881, Dt22([dst]));
2771
0
#line 1875 "src/jit/x64/emit.dasc"
2772
0
        break;
2773
2.18k
    }
2774
0
    case MVM_OP_getstdin:
2775
0
    case MVM_OP_getstdout:
2776
0
    case MVM_OP_getstderr: {
2777
0
        MVMint16 dst = ins->operands[0].reg.orig;
2778
0
        //| mov TMP3, aword TC->instance;
2779
0
        dasm_put(Dst, 2824, Dt21(->instance));
2780
0
#line 1882 "src/jit/x64/emit.dasc"
2781
0
        if (ins->info->opcode == MVM_OP_getstdin) {
2782
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stdin_handle;
2783
0
            dasm_put(Dst, 448, DtC(->stdin_handle));
2784
0
#line 1884 "src/jit/x64/emit.dasc"
2785
0
        } else if (ins->info->opcode == MVM_OP_getstdout) {
2786
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stdout_handle;
2787
0
            dasm_put(Dst, 448, DtC(->stdout_handle));
2788
0
#line 1886 "src/jit/x64/emit.dasc"
2789
0
        } else if (ins->info->opcode == MVM_OP_getstderr) {
2790
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stderr_handle;
2791
0
            dasm_put(Dst, 448, DtC(->stderr_handle));
2792
0
#line 1888 "src/jit/x64/emit.dasc"
2793
0
        }
2794
0
        //| mov aword WORK[dst], TMP3;
2795
0
        dasm_put(Dst, 578, Dt22([dst]));
2796
0
#line 1890 "src/jit/x64/emit.dasc"
2797
0
        break;
2798
0
    }
2799
1.05k
    case MVM_OP_ordat:
2800
1.05k
    case MVM_OP_ordfirst: {
2801
1.05k
        MVMint16 dst = ins->operands[0].reg.orig;
2802
1.05k
        MVMint16 str = ins->operands[1].reg.orig;
2803
1.05k
        //| mov ARG1, TC;
2804
1.05k
        //| mov ARG2, aword WORK[str];
2805
1.05k
        dasm_put(Dst, 2241, Dt22([str]));
2806
1.05k
#line 1898 "src/jit/x64/emit.dasc"
2807
1.05k
        if (op == MVM_OP_ordat) {
2808
128
            MVMint16 idx = ins->operands[2].reg.orig;
2809
128
            //| mov ARG3, qword WORK[idx];
2810
128
            dasm_put(Dst, 587, Dt22([idx]));
2811
128
#line 1901 "src/jit/x64/emit.dasc"
2812
927
        } else {
2813
927
            //| mov ARG3, 0;
2814
927
            dasm_put(Dst, 1606);
2815
927
#line 1903 "src/jit/x64/emit.dasc"
2816
927
        }
2817
1.05k
        //| callp &MVM_string_ord_at;
2818
1.05k
        dasm_put(Dst, 208);
2819
1.05k
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_string_ord_at)), (MVMuint32)((uintptr_t)(&MVM_string_ord_at) >> 32));
2820
1.05k
#line 1905 "src/jit/x64/emit.dasc"
2821
1.05k
        //| mov qword WORK[dst], RV;
2822
1.05k
        dasm_put(Dst, 881, Dt22([dst]));
2823
1.05k
#line 1906 "src/jit/x64/emit.dasc"
2824
1.05k
        break;
2825
1.05k
    }
2826
0
    case MVM_OP_setcodeobj: {
2827
0
        MVMint16 obj  = ins->operands[0].reg.orig;
2828
0
        MVMint16 code = ins->operands[1].reg.orig;
2829
0
        //| mov TMP1, aword WORK[obj];
2830
0
        dasm_put(Dst, 1416, Dt22([obj]));
2831
0
#line 1912 "src/jit/x64/emit.dasc"
2832
0
        /* if (REPR(obj)->ID == MVM_REPR_ID_MVMCode) */
2833
0
        //| cmp_repr_id TMP1, TMP2, MVM_REPR_ID_MVMCode;
2834
0
        //| je >1;
2835
0
        dasm_put(Dst, 2829, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCode);
2836
0
#line 1915 "src/jit/x64/emit.dasc"
2837
0
        /* else throw */
2838
0
        //| throw_adhoc "setcodeobj needs a code ref";
2839
0
        dasm_put(Dst, 923, (unsigned int)((uintptr_t)("setcodeobj needs a code ref")), (unsigned int)(((uintptr_t)("setcodeobj needs a code ref"))>>32));
2840
0
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2841
0
#line 1917 "src/jit/x64/emit.dasc"
2842
0
        //|1:
2843
0
        //| mov TMP2, aword WORK[code];
2844
0
        //| mov aword CODE:TMP1->body.code_object, TMP2;
2845
0
        dasm_put(Dst, 2846, Dt22([code]), Dt1C(->body.code_object));
2846
0
#line 1920 "src/jit/x64/emit.dasc"
2847
0
        break;
2848
1.05k
    }
2849
0
    case MVM_OP_lastexpayload: {
2850
0
        MVMint16 dst = ins->operands[0].reg.orig;
2851
0
        //| mov TMP3, aword TC->last_payload;
2852
0
        //| mov aword WORK[dst], TMP3;
2853
0
        dasm_put(Dst, 2862, Dt21(->last_payload), Dt22([dst]));
2854
0
#line 1926 "src/jit/x64/emit.dasc"
2855
0
        break;
2856
1.05k
    }
2857
178
    case MVM_OP_param_sp: {
2858
178
        MVMuint16 dst = ins->operands[0].reg.orig;
2859
178
        MVMuint16 off = ins->operands[1].lit_ui16;
2860
178
        //| mov ARG1, TC
2861
178
        //| mov ARG2, TC:ARG1->cur_frame
2862
178
        //| lea ARG2, FRAME:ARG2->params
2863
178
        //| mov ARG3, off
2864
178
        //| callp &MVM_args_slurpy_positional;
2865
178
        dasm_put(Dst, 2871, Dt21(->cur_frame), Dt2(->params), off);
2866
178
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_args_slurpy_positional)), (MVMuint32)((uintptr_t)(&MVM_args_slurpy_positional) >> 32));
2867
178
#line 1936 "src/jit/x64/emit.dasc"
2868
178
        //| mov qword WORK[dst], RV;
2869
178
        dasm_put(Dst, 881, Dt22([dst]));
2870
178
#line 1937 "src/jit/x64/emit.dasc"
2871
178
        break;
2872
1.05k
    }
2873
40
    case MVM_OP_param_sn: {
2874
40
        MVMuint16 dst = ins->operands[0].reg.orig;
2875
40
        //| mov ARG1, TC
2876
40
        //| mov ARG2, TC:ARG1->cur_frame
2877
40
        //| lea ARG2, FRAME:ARG2->params
2878
40
        //| callp &MVM_args_slurpy_named;
2879
40
        dasm_put(Dst, 2889, Dt21(->cur_frame), Dt2(->params));
2880
40
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_args_slurpy_named)), (MVMuint32)((uintptr_t)(&MVM_args_slurpy_named) >> 32));
2881
40
#line 1945 "src/jit/x64/emit.dasc"
2882
40
        //| mov qword WORK[dst], RV;
2883
40
        dasm_put(Dst, 881, Dt22([dst]));
2884
40
#line 1946 "src/jit/x64/emit.dasc"
2885
40
        break;
2886
1.05k
    }
2887
0
    case MVM_OP_sp_cas_o: {
2888
0
        MVMint16 target = ins->operands[1].reg.orig;
2889
0
        MVMint16 expected = ins->operands[2].reg.orig;
2890
0
        MVMint16 value = ins->operands[3].reg.orig;
2891
0
        MVMint16 result = ins->operands[0].reg.orig;
2892
0
        //| mov ARG1, TC;
2893
0
        //| mov ARG2, aword WORK[target];
2894
0
        //| mov ARG3, aword WORK[expected];
2895
0
        //| mov ARG4, aword WORK[value];
2896
0
        //|.if WIN32;
2897
0
        //| lea TMP6, WORK[result]
2898
0
        //| mov qword [rsp+0x20], TMP6
2899
0
        //|.else;
2900
0
        //| lea ARG5, WORK[result]
2901
0
        //|.endif
2902
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2903
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2904
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->cas;
2905
0
        //| call FUNCTION;
2906
0
        dasm_put(Dst, 2903, Dt22([target]), Dt22([expected]), Dt22([value]), Dt22([result]), DtE(->st), Dt12(->container_spec), Dt17(->cas));
2907
0
#line 1967 "src/jit/x64/emit.dasc"
2908
0
        break;
2909
1.05k
    }
2910
0
    case MVM_OP_sp_atomicload_o: {
2911
0
        MVMint16 target = ins->operands[1].reg.orig;
2912
0
        MVMint16 result = ins->operands[0].reg.orig;
2913
0
        //| mov ARG1, TC;
2914
0
        //| mov ARG2, aword WORK[target];
2915
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2916
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2917
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->atomic_load;
2918
0
        //| call FUNCTION;
2919
0
        //| mov WORK[result], RV
2920
0
        dasm_put(Dst, 2940, Dt22([target]), DtE(->st), Dt12(->container_spec), Dt17(->atomic_load), Dt22([result]));
2921
0
#line 1979 "src/jit/x64/emit.dasc"
2922
0
        break;
2923
1.05k
    }
2924
0
    case MVM_OP_sp_atomicstore_o: {
2925
0
        MVMint16 target = ins->operands[0].reg.orig;
2926
0
        MVMint16 value = ins->operands[1].reg.orig;
2927
0
        //| mov ARG1, TC;
2928
0
        //| mov ARG2, aword WORK[target];
2929
0
        //| mov ARG3, aword WORK[value];
2930
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2931
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2932
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->atomic_store;
2933
0
        //| call FUNCTION;
2934
0
        dasm_put(Dst, 2969, Dt22([target]), Dt22([value]), DtE(->st), Dt12(->container_spec), Dt17(->atomic_store));
2935
0
#line 1991 "src/jit/x64/emit.dasc"
2936
0
        break;
2937
1.05k
    }
2938
0
    default:
2939
0
        MVM_panic(1, "Can't JIT opcode <%s>", ins->info->name);
2940
136k
    }
2941
136k
}
2942
2943
2944
2945
/* Call argument decoder */
2946
static void load_call_arg(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
2947
258k
                          MVMJitCallArg arg) {
2948
258k
    switch(arg.type) {
2949
84.7k
    case MVM_JIT_INTERP_VAR:
2950
84.7k
        switch (arg.v.ivar) {
2951
74.0k
        case MVM_JIT_INTERP_TC:
2952
74.0k
            //| mov TMP6, TC;
2953
74.0k
            dasm_put(Dst, 2998);
2954
74.0k
#line 2008 "src/jit/x64/emit.dasc"
2955
74.0k
            break;
2956
10.3k
        case MVM_JIT_INTERP_CU:
2957
10.3k
            //| mov TMP6, CU;
2958
10.3k
            dasm_put(Dst, 3003);
2959
10.3k
#line 2011 "src/jit/x64/emit.dasc"
2960
10.3k
            break;
2961
0
        case MVM_JIT_INTERP_FRAME:
2962
0
            //| mov TMP6, TC->cur_frame;
2963
0
            dasm_put(Dst, 169, Dt21(->cur_frame));
2964
0
#line 2014 "src/jit/x64/emit.dasc"
2965
0
            break;
2966
109
        case MVM_JIT_INTERP_PARAMS:
2967
109
            //| mov TMP6, TC->cur_frame;
2968
109
            //| lea TMP6, FRAME:TMP6->params;
2969
109
            dasm_put(Dst, 3008, Dt21(->cur_frame), Dt2(->params));
2970
109
#line 2018 "src/jit/x64/emit.dasc"
2971
109
            break;
2972
263
        case MVM_JIT_INTERP_CALLER:
2973
263
            //| mov TMP6, TC->cur_frame;
2974
263
            //| mov TMP6, aword FRAME:TMP6->caller;
2975
263
            dasm_put(Dst, 3017, Dt21(->cur_frame), Dt2(->caller));
2976
263
#line 2022 "src/jit/x64/emit.dasc"
2977
263
            break;
2978
84.7k
        }
2979
84.7k
        break;
2980
94.0k
    case MVM_JIT_REG_VAL:
2981
94.0k
        //| mov TMP6, qword WORK[arg.v.reg];
2982
94.0k
        dasm_put(Dst, 3026, Dt22([arg.v.reg]));
2983
94.0k
#line 2027 "src/jit/x64/emit.dasc"
2984
94.0k
        break;
2985
454
    case MVM_JIT_REG_VAL_F:
2986
454
        //| mov TMP6, qword WORK[arg.v.reg];
2987
454
        dasm_put(Dst, 3026, Dt22([arg.v.reg]));
2988
454
#line 2030 "src/jit/x64/emit.dasc"
2989
454
        break;
2990
12.1k
    case MVM_JIT_REG_ADDR:
2991
12.1k
        //| lea TMP6, WORK[arg.v.reg];
2992
12.1k
        dasm_put(Dst, 3031, Dt22([arg.v.reg]));
2993
12.1k
#line 2033 "src/jit/x64/emit.dasc"
2994
12.1k
        break;
2995
7.77k
    case MVM_JIT_STR_IDX:
2996
7.77k
        //| get_string TMP6, arg.v.lit_i64;
2997
7.77k
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, arg.v.lit_i64);
2998
7.77k
        dasm_put(Dst, 3036, Dt23(->body.strings), Dt15([arg.v.lit_i64]));
2999
7.77k
#line 2036 "src/jit/x64/emit.dasc"
3000
7.77k
        break;
3001
46.9k
    case MVM_JIT_LITERAL:
3002
46.9k
        //| mov TMP6, arg.v.lit_i64;
3003
46.9k
        dasm_put(Dst, 3045, arg.v.lit_i64);
3004
46.9k
#line 2039 "src/jit/x64/emit.dasc"
3005
46.9k
        break;
3006
10
    case MVM_JIT_LITERAL_64:
3007
10
    case MVM_JIT_LITERAL_PTR:
3008
10
    case MVM_JIT_LITERAL_F:
3009
10
        //| mov64 TMP6, arg.v.lit_i64;
3010
10
        dasm_put(Dst, 3050, (unsigned int)(arg.v.lit_i64), (unsigned int)((arg.v.lit_i64)>>32));
3011
10
#line 2044 "src/jit/x64/emit.dasc"
3012
10
        break;
3013
6.15k
    case MVM_JIT_REG_STABLE:
3014
6.15k
        //| mov TMP6, qword WORK[arg.v.reg];
3015
6.15k
        //| mov TMP6, OBJECT:TMP6->st;
3016
6.15k
        dasm_put(Dst, 233, Dt22([arg.v.reg]), DtE(->st));
3017
6.15k
#line 2048 "src/jit/x64/emit.dasc"
3018
6.15k
        break;
3019
6.15k
    case MVM_JIT_REG_OBJBODY:
3020
6.15k
        //| mov TMP6, qword WORK[arg.v.reg];
3021
6.15k
        //| lea TMP6, STOOGE:TMP6->data;
3022
6.15k
        dasm_put(Dst, 3055, Dt22([arg.v.reg]), DtF(->data));
3023
6.15k
#line 2052 "src/jit/x64/emit.dasc"
3024
6.15k
        break;
3025
1
    case MVM_JIT_REG_DYNIDX:
3026
1
        //| get_cur_op TMP5;
3027
1
        //| xor TMP6, TMP6;
3028
1
        //| mov TMP6w, U16:TMP5[arg.v.reg];
3029
1
        //| mov TMP6, qword [WORK + TMP6*8];
3030
1
        dasm_put(Dst, 3064, Dt21(->interp_cur_op), Dt1E([arg.v.reg]));
3031
1
#line 2058 "src/jit/x64/emit.dasc"
3032
1
        break;
3033
0
    case MVM_JIT_DATA_LABEL:
3034
0
        //| lea TMP6, [=>(arg.v.lit_i64)];
3035
0
        dasm_put(Dst, 3084, (arg.v.lit_i64));
3036
0
#line 2061 "src/jit/x64/emit.dasc"
3037
0
        break;
3038
2
    case MVM_JIT_ARG_I64:
3039
2
        //| mov TMP6, TC->cur_frame;
3040
2
        //| mov TMP6, FRAME:TMP6->args;
3041
2
        //| mov TMP6, qword REGISTER:TMP6[arg.v.lit_i64];
3042
2
        dasm_put(Dst, 3089, Dt21(->cur_frame), Dt2(->args), Dt1([arg.v.lit_i64]));
3043
2
#line 2066 "src/jit/x64/emit.dasc"
3044
2
        break;
3045
0
    case MVM_JIT_ARG_I64_RW:
3046
0
        //| mov TMP6, TC->cur_frame;
3047
0
        //| mov TMP6, FRAME:TMP6->args;
3048
0
        //| lea TMP6, qword REGISTER:TMP6[arg.v.lit_i64];
3049
0
        dasm_put(Dst, 3102, Dt21(->cur_frame), Dt2(->args), Dt1([arg.v.lit_i64]));
3050
0
#line 2071 "src/jit/x64/emit.dasc"
3051
0
        break;
3052
1
    case MVM_JIT_ARG_PTR:
3053
1
        //| mov TMP6, TC->cur_frame;
3054
1
        //| mov TMP6, FRAME:TMP6->args;
3055
1
        //| mov TMP6, qword REGISTER:TMP6[arg.v.lit_i64];
3056
1
        //| mov TMP6, aword STOOGE:TMP6->data;
3057
1
        dasm_put(Dst, 3115, Dt21(->cur_frame), Dt2(->args), Dt1([arg.v.lit_i64]), DtF(->data));
3058
1
#line 2077 "src/jit/x64/emit.dasc"
3059
1
        break;
3060
0
    case MVM_JIT_ARG_VMARRAY:
3061
0
        //| mov TMP6, TC->cur_frame;
3062
0
        //| mov TMP6, FRAME:TMP6->args;
3063
0
        //| mov TMP6, qword REGISTER:TMP6[arg.v.lit_i64];
3064
0
        //| mov TMP6, aword VMARRAY:TMP6->body.slots;
3065
0
        dasm_put(Dst, 3115, Dt21(->cur_frame), Dt2(->args), Dt1([arg.v.lit_i64]), Dt10(->body.slots));
3066
0
#line 2083 "src/jit/x64/emit.dasc"
3067
0
        break;
3068
0
    case MVM_JIT_PARAM_I64:
3069
0
        //| mov TMP6, qword WORK[arg.v.lit_i64];
3070
0
        dasm_put(Dst, 3026, Dt22([arg.v.lit_i64]));
3071
0
#line 2086 "src/jit/x64/emit.dasc"
3072
0
        break;
3073
0
    case MVM_JIT_PARAM_I64_RW:
3074
0
        //| lea TMP6, qword WORK[arg.v.lit_i64];
3075
0
        dasm_put(Dst, 3031, Dt22([arg.v.lit_i64]));
3076
0
#line 2089 "src/jit/x64/emit.dasc"
3077
0
        break;
3078
0
    case MVM_JIT_PARAM_PTR:
3079
0
        //| mov TMP6, aword WORK[arg.v.lit_i64];
3080
0
        //| mov TMP6, aword STOOGE:TMP6->data;
3081
0
        dasm_put(Dst, 233, Dt22([arg.v.lit_i64]), DtF(->data));
3082
0
#line 2093 "src/jit/x64/emit.dasc"
3083
0
        break;
3084
0
    case MVM_JIT_PARAM_VMARRAY:
3085
0
        //| mov TMP6, aword WORK[arg.v.lit_i64];
3086
0
        //| mov TMP6, aword VMARRAY:TMP6->body.slots;
3087
0
        dasm_put(Dst, 233, Dt22([arg.v.lit_i64]), Dt10(->body.slots));
3088
0
#line 2097 "src/jit/x64/emit.dasc"
3089
0
        break;
3090
150
    case MVM_JIT_SPESH_SLOT_VALUE:
3091
150
        //| get_spesh_slot TMP6, arg.v.lit_i64;
3092
150
        dasm_put(Dst, 3089, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([arg.v.lit_i64]));
3093
150
#line 2100 "src/jit/x64/emit.dasc"
3094
150
        break;
3095
4
    case MVM_JIT_STACK_VALUE:
3096
4
        //| mov TMP6, [rbp-(0x28+arg.v.lit_i64*8)];
3097
4
        dasm_put(Dst, 3132, -(0x28+arg.v.lit_i64*8));
3098
4
#line 2103 "src/jit/x64/emit.dasc"
3099
4
        break;
3100
0
    default:
3101
0
        MVM_oops(tc, "JIT: Unknown JIT argument type %d", arg.type);
3102
258k
    }
3103
258k
}
3104
3105
static void emit_gpr_arg(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3106
249k
                         MVMint32 i) {
3107
249k
    switch (i) {
3108
74.0k
    case 0:
3109
74.0k
        //| mov ARG1, TMP6;
3110
74.0k
        dasm_put(Dst, 3137);
3111
74.0k
#line 2114 "src/jit/x64/emit.dasc"
3112
74.0k
        break;
3113
68.6k
    case 1:
3114
68.6k
        //| mov ARG2, TMP6;
3115
68.6k
        dasm_put(Dst, 3141);
3116
68.6k
#line 2117 "src/jit/x64/emit.dasc"
3117
68.6k
        break;
3118
50.2k
    case 2:
3119
50.2k
        //| mov ARG3, TMP6;
3120
50.2k
        dasm_put(Dst, 3145);
3121
50.2k
#line 2120 "src/jit/x64/emit.dasc"
3122
50.2k
        break;
3123
31.8k
    case 3:
3124
31.8k
        //| mov ARG4, TMP6;
3125
31.8k
        dasm_put(Dst, 3149);
3126
31.8k
#line 2123 "src/jit/x64/emit.dasc"
3127
31.8k
        break;
3128
74.0k
//|.if POSIX
3129
15.7k
    case 4:
3130
15.7k
//|        mov ARG5, TMP6;
3131
15.7k
dasm_put(Dst, 3153);
3132
15.7k
       break;
3133
74.0k
#line 2128 "src/jit/x64/emit.dasc"
3134
8.98k
  case 5:
3135
8.98k
//|      mov ARG6, TMP6;
3136
8.98k
dasm_put(Dst, 3157);
3137
8.98k
     break;
3138
74.0k
#line 2131 "src/jit/x64/emit.dasc"
3139
74.0k
//|.endif
3140
0
    default:
3141
0
        MVM_oops(tc, "JIT: can't store %d arguments in GPR", i);
3142
249k
    }
3143
249k
}
3144
3145
static void emit_sse_arg(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3146
454
                         MVMint32 i) {
3147
454
    switch (i) {
3148
454
    case 0:
3149
454
        //| movd ARG1F, TMP6;
3150
454
        dasm_put(Dst, 3161);
3151
454
#line 2142 "src/jit/x64/emit.dasc"
3152
454
        break;
3153
0
    case 1:
3154
0
        //| movd ARG2F, TMP6;
3155
0
        dasm_put(Dst, 3167);
3156
0
#line 2145 "src/jit/x64/emit.dasc"
3157
0
        break;
3158
0
    case 2:
3159
0
        //| movd ARG3F, TMP6;
3160
0
        dasm_put(Dst, 3173);
3161
0
#line 2148 "src/jit/x64/emit.dasc"
3162
0
        break;
3163
0
    case 3:
3164
0
        //| movd ARG4F, TMP6;
3165
0
        dasm_put(Dst, 3179);
3166
0
#line 2151 "src/jit/x64/emit.dasc"
3167
0
        break;
3168
454
//|.if POSIX
3169
0
    case 4:
3170
0
//|        movd ARG5F, TMP6;
3171
0
dasm_put(Dst, 3185);
3172
0
       break;
3173
454
#line 2156 "src/jit/x64/emit.dasc"
3174
0
    case 5:
3175
0
//|         movd ARG6F, TMP6;
3176
0
dasm_put(Dst, 3191);
3177
0
        break;
3178
454
#line 2159 "src/jit/x64/emit.dasc"
3179
0
    case 6:
3180
0
//|        movd ARG7F, TMP6;
3181
0
dasm_put(Dst, 3198);
3182
0
       break;
3183
454
#line 2162 "src/jit/x64/emit.dasc"
3184
0
    case 7:
3185
0
//|        movd ARG8F, TMP6;
3186
0
dasm_put(Dst, 3205);
3187
0
       break;
3188
454
#line 2165 "src/jit/x64/emit.dasc"
3189
454
//|.endif
3190
0
    default:
3191
0
        MVM_oops(tc, "JIT: can't put  %d arguments in SSE", i);
3192
454
    }
3193
454
}
3194
3195
static void emit_stack_arg(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3196
8.66k
                           MVMint32 arg_size, MVMint32 pos) {
3197
8.66k
    /* basically, stack arguments are passed in right-to-left order
3198
8.66k
       on both POSIX and W64 backends, it seems. Thus the most logical
3199
8.66k
       thing to do is to count from the stack top upwards. */
3200
8.66k
    if (pos + arg_size > 160) {
3201
0
        MVM_oops(tc, "JIT: trying to pass arguments "
3202
0
                 " in local space (stack top offset:"
3203
0
                 " %d, size: %d)", pos, arg_size);
3204
0
    }
3205
8.66k
    switch(arg_size) {
3206
0
    case 1:
3207
0
        //| mov byte [rsp+pos], TMP6b;
3208
0
        dasm_put(Dst, 3212, pos);
3209
0
#line 2184 "src/jit/x64/emit.dasc"
3210
0
        break;
3211
0
    case 2:
3212
0
        //| mov word [rsp+pos], TMP6w;
3213
0
        dasm_put(Dst, 3219, pos);
3214
0
#line 2187 "src/jit/x64/emit.dasc"
3215
0
        break;
3216
0
    case 4:
3217
0
        //| mov dword [rsp+pos], TMP6d;
3218
0
        dasm_put(Dst, 3220, pos);
3219
0
#line 2190 "src/jit/x64/emit.dasc"
3220
0
        break;
3221
8.66k
    case 8:
3222
8.66k
        //| mov qword [rsp+pos], TMP6;
3223
8.66k
        dasm_put(Dst, 3227, pos);
3224
8.66k
#line 2193 "src/jit/x64/emit.dasc"
3225
8.66k
        break;
3226
0
    default:
3227
0
        MVM_oops(tc, "JIT: can't pass arguments size %d bytes",
3228
0
                 arg_size);
3229
8.66k
    }
3230
8.66k
}
3231
3232
static void emit_posix_callargs(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3233
74.0k
                                MVMJitCallArg args[], MVMint32 num_args) {
3234
74.0k
    MVMint32 num_gpr = 0, num_fpr = 0, num_stack = 0, i;
3235
74.0k
    MVMJitCallArg in_gpr[6], in_fpr[8], *on_stack = NULL;
3236
74.0k
    if (num_args > 6)
3237
7.02k
        on_stack = MVM_malloc(sizeof(MVMJitCallArg) * (num_args - 6));
3238
74.0k
    /* divide in gpr, fpr, stack values */
3239
332k
    for (i = 0; i < num_args; i++) {
3240
258k
        switch (args[i].type) {
3241
258k
        case MVM_JIT_INTERP_VAR:
3242
258k
        case MVM_JIT_REG_VAL:
3243
258k
        case MVM_JIT_REG_ADDR:
3244
258k
        case MVM_JIT_REG_OBJBODY:
3245
258k
        case MVM_JIT_REG_STABLE:
3246
258k
        case MVM_JIT_REG_DYNIDX:
3247
258k
        case MVM_JIT_STR_IDX:
3248
258k
        case MVM_JIT_LITERAL:
3249
258k
        case MVM_JIT_LITERAL_64:
3250
258k
        case MVM_JIT_LITERAL_PTR:
3251
258k
        case MVM_JIT_DATA_LABEL:
3252
258k
        case MVM_JIT_ARG_I64:
3253
258k
        case MVM_JIT_ARG_I64_RW:
3254
258k
        case MVM_JIT_ARG_PTR:
3255
258k
        case MVM_JIT_ARG_VMARRAY:
3256
258k
        case MVM_JIT_PARAM_I64:
3257
258k
        case MVM_JIT_PARAM_I64_RW:
3258
258k
        case MVM_JIT_PARAM_PTR:
3259
258k
        case MVM_JIT_PARAM_VMARRAY:
3260
258k
        case MVM_JIT_SPESH_SLOT_VALUE:
3261
258k
        case MVM_JIT_STACK_VALUE:
3262
258k
            if (num_gpr < 6) {
3263
249k
                in_gpr[num_gpr++] = args[i];
3264
8.66k
            } else {
3265
8.66k
                on_stack[num_stack++] = args[i];
3266
8.66k
            }
3267
258k
            break;
3268
454
        case MVM_JIT_REG_VAL_F:
3269
454
        case MVM_JIT_LITERAL_F:
3270
454
            if (num_fpr < 8) {
3271
454
                in_fpr[num_fpr++] = args[i];
3272
0
            } else {
3273
0
                on_stack[num_stack++] = args[i];
3274
0
            }
3275
454
            break;
3276
0
        default:
3277
0
            MVM_oops(tc, "JIT: Unknown JIT argument type %d for emit_posix_callargs", args[i].type);
3278
258k
        }
3279
258k
    }
3280
323k
    for (i = 0; i < num_gpr; i++) {
3281
249k
        load_call_arg(tc, compiler, jg, in_gpr[i]);
3282
249k
        emit_gpr_arg(tc, compiler, jg, i);
3283
249k
    }
3284
74.5k
    for (i = 0; i < num_fpr; i++) {
3285
454
        load_call_arg(tc, compiler, jg, in_fpr[i]);
3286
454
        emit_sse_arg(tc, compiler, jg, i);
3287
454
    }
3288
74.0k
    /* push right-to-left */
3289
82.7k
    for (i = 0; i < num_stack; i++) {
3290
8.66k
        load_call_arg(tc, compiler, jg, on_stack[i]);
3291
8.66k
        // I'm not sure this is correct, btw
3292
8.66k
        emit_stack_arg(tc, compiler, jg, 8, i*8);
3293
8.66k
    }
3294
74.0k
    if (on_stack)
3295
7.02k
        MVM_free(on_stack);
3296
74.0k
}
3297
3298
static void emit_win64_callargs(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3299
0
                                MVMJitCallArg args[], MVMint32 num_args) {
3300
0
    MVMint32 i;
3301
0
    MVMint32 num_reg_args = (num_args > 4 ? 4 : num_args);
3302
0
    for (i = 0; i < num_reg_args; i++) {
3303
0
        load_call_arg(tc, compiler, jg, args[i]);
3304
0
        if (args[i].type == MVM_JIT_REG_VAL_F ||
3305
0
            args[i].type == MVM_JIT_LITERAL_F) {
3306
0
            emit_sse_arg(tc, compiler, jg, i);
3307
0
        } else {
3308
0
            emit_gpr_arg(tc, compiler, jg, i);
3309
0
        }
3310
0
    }
3311
0
    for (; i < num_args; i++) {
3312
0
        load_call_arg(tc, compiler, jg, args[i]);
3313
0
        emit_stack_arg(tc, compiler, jg, 8, i * 8);
3314
0
    }
3315
0
}
3316
3317
void MVM_jit_emit_call_c(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3318
74.0k
                         MVMJitCallC * call_spec) {
3319
74.0k
3320
74.0k
    MVM_jit_log(tc, "emit c call <%d args>\n", call_spec->num_args);
3321
74.0k
    if (call_spec->has_vargs) {
3322
0
        MVM_oops(tc, "JIT can't handle varargs yet");
3323
0
    }
3324
74.0k
    //|.if WIN32;
3325
74.0k
#line 2294 "src/jit/x64/emit.dasc"
3326
74.0k
    //|.else;
3327
74.0k
     emit_posix_callargs(tc, compiler, jg, call_spec->args, call_spec->num_args);
3328
74.0k
    //|.endif
3329
74.0k
    /* Emit the call. I think we should be able to do something smarter than
3330
74.0k
     * store the constant into the bytecode, like a data segment. But I'm
3331
74.0k
     * not sure. */
3332
74.0k
    //| callp call_spec->func_ptr;
3333
74.0k
    dasm_put(Dst, 208);
3334
74.0k
    dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(call_spec->func_ptr)), (MVMuint32)((uintptr_t)(call_spec->func_ptr) >> 32));
3335
74.0k
    dasm_put(Dst, 216);
3336
74.0k
#line 2301 "src/jit/x64/emit.dasc"
3337
74.0k
    /* right, now determine what to do with the return value */
3338
74.0k
    switch(call_spec->rv_mode) {
3339
40.9k
    case MVM_JIT_RV_VOID:
3340
40.9k
        break;
3341
33.1k
    case MVM_JIT_RV_INT:
3342
33.1k
    case MVM_JIT_RV_PTR:
3343
33.1k
        //| mov WORK[call_spec->rv_idx], RV;
3344
33.1k
        dasm_put(Dst, 886, Dt22([call_spec->rv_idx]));
3345
33.1k
#line 2308 "src/jit/x64/emit.dasc"
3346
33.1k
        break;
3347
12
    case MVM_JIT_RV_NUM:
3348
12
        //| movsd qword WORK[call_spec->rv_idx], RVF;
3349
12
        dasm_put(Dst, 1464, Dt22([call_spec->rv_idx]));
3350
12
#line 2311 "src/jit/x64/emit.dasc"
3351
12
        break;
3352
0
    case MVM_JIT_RV_DEREF:
3353
0
        //| mov TMP1, [RV];
3354
0
        //| mov WORK[call_spec->rv_idx], TMP1;
3355
0
        dasm_put(Dst, 3234, Dt22([call_spec->rv_idx]));
3356
0
#line 2315 "src/jit/x64/emit.dasc"
3357
0
        break;
3358
0
    case MVM_JIT_RV_ADDR:
3359
0
        /* store local at address */
3360
0
        //| mov TMP1, WORK[call_spec->rv_idx];
3361
0
        //| mov [RV], TMP1;
3362
0
        dasm_put(Dst, 3242, Dt22([call_spec->rv_idx]));
3363
0
#line 2320 "src/jit/x64/emit.dasc"
3364
0
        break;
3365
1
    case MVM_JIT_RV_DYNIDX:
3366
1
        /* store in register relative to cur_op */
3367
1
        //| get_cur_op TMP1;
3368
1
        //| xor TMP2, TMP2;
3369
1
        //| mov TMP2w, word [TMP1 + call_spec->rv_idx*2];
3370
1
        //| mov aword [WORK + TMP2*8], RV;
3371
1
        dasm_put(Dst, 3250, Dt21(->interp_cur_op), call_spec->rv_idx*2);
3372
1
#line 2327 "src/jit/x64/emit.dasc"
3373
1
        break;
3374
0
    case MVM_JIT_RV_DEREF_OR_VMNULL:
3375
0
        //| test RV, RV;
3376
0
        //| jz >4;
3377
0
        //| mov TMP1, [RV];
3378
0
        //| jmp >5;
3379
0
        //|4:
3380
0
        //| get_vmnull TMP1;
3381
0
        //|5:
3382
0
        //| mov WORK[call_spec->rv_idx], TMP1;
3383
0
        dasm_put(Dst, 3269, Dt21(->instance), DtC(->VMNull), Dt22([call_spec->rv_idx]));
3384
0
#line 2337 "src/jit/x64/emit.dasc"
3385
0
        break;
3386
5
    case MVM_JIT_RV_TO_STACK:
3387
5
        //| mov [rbp-(0x28+call_spec->rv_idx*8)], RV;
3388
5
        dasm_put(Dst, 3300, -(0x28+call_spec->rv_idx*8));
3389
5
#line 2340 "src/jit/x64/emit.dasc"
3390
5
        break;
3391
74.0k
    }
3392
74.0k
}
3393
3394
void MVM_jit_emit_block_branch(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3395
22.8k
                               MVMJitBranch * branch) {
3396
22.8k
    MVMSpeshIns *ins = branch->ins;
3397
22.8k
    MVMint32 name = branch->dest;
3398
22.8k
    /* move gc sync point to the front so as to not have
3399
22.8k
     * awkward dispatching issues */
3400
22.8k
    //| gc_sync_point;
3401
22.8k
    dasm_put(Dst, 3305, Dt21(->gc_status));
3402
22.8k
    dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_gc_enter_from_interrupt)), (MVMuint32)((uintptr_t)(&MVM_gc_enter_from_interrupt) >> 32));
3403
22.8k
    dasm_put(Dst, 1297);
3404
22.8k
#line 2351 "src/jit/x64/emit.dasc"
3405
22.8k
    if (ins == NULL || ins->info->opcode == MVM_OP_goto) {
3406
5.68k
        MVM_jit_log(tc, "emit jump to label %d\n", name);
3407
5.68k
        if (name == MVM_JIT_BRANCH_EXIT) {
3408
0
            //| jmp ->exit
3409
0
            dasm_put(Dst, 3320);
3410
0
#line 2355 "src/jit/x64/emit.dasc"
3411
5.68k
        } else {
3412
5.68k
            //| jmp =>(name)
3413
5.68k
            dasm_put(Dst, 3325, (name));
3414
5.68k
#line 2357 "src/jit/x64/emit.dasc"
3415
5.68k
        }
3416
17.1k
    } else {
3417
17.1k
        MVMint16 val = ins->operands[0].reg.orig;
3418
17.1k
        MVM_jit_log(tc, "emit branch <%s> to label %d\n",
3419
17.1k
                    ins->info->name, name);
3420
17.1k
        switch(ins->info->opcode) {
3421
3.69k
        case MVM_OP_if_i:
3422
3.69k
            //| mov rax, WORK[val];
3423
3.69k
            //| test rax, rax;
3424
3.69k
            //| jnz =>(name); // jump to dynamic label
3425
3.69k
            dasm_put(Dst, 3329, Dt22([val]), (name));
3426
3.69k
#line 2367 "src/jit/x64/emit.dasc"
3427
3.69k
            break;
3428
8.49k
        case MVM_OP_unless_i:
3429
8.49k
            //| mov rax, WORK[val];
3430
8.49k
            //| test rax, rax;
3431
8.49k
            //| jz =>(name);
3432
8.49k
            dasm_put(Dst, 3340, Dt22([val]), (name));
3433
8.49k
#line 2372 "src/jit/x64/emit.dasc"
3434
8.49k
            break;
3435
19
        case MVM_OP_if_n:
3436
19
            //| movd xmm0, qword WORK[val];
3437
19
            //| xorpd xmm1, xmm1; // make it zero
3438
19
            //| ucomisd xmm0, xmm1;
3439
19
            //| jp =>(name);  // is NaN?
3440
19
            //| jne =>(name); // not equal to zero? we're golden
3441
19
            dasm_put(Dst, 3351, Dt22([val]), (name), (name));
3442
19
#line 2379 "src/jit/x64/emit.dasc"
3443
19
            break;
3444
54
        case MVM_OP_unless_n:
3445
54
            //| movd xmm0, qword WORK[val];
3446
54
            //| xorpd xmm1, xmm1; // make it zero
3447
54
            //| ucomisd xmm0, xmm1;
3448
54
            //| jp >1; // is NaN
3449
54
            //| jne >1; // is not zero
3450
54
            //| jmp =>(name); // it is zero yay!
3451
54
            //|1:
3452
54
            dasm_put(Dst, 3372, Dt22([val]), (name));
3453
54
#line 2388 "src/jit/x64/emit.dasc"
3454
54
            break;
3455
0
        case MVM_OP_if_s0:
3456
0
        case MVM_OP_unless_s0:
3457
0
            //| mov ARG1, TC;
3458
0
            //| mov ARG2, WORK[val];
3459
0
            //| callp &MVM_coerce_istrue_s;
3460
0
            dasm_put(Dst, 3400, Dt22([val]));
3461
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_coerce_istrue_s)), (MVMuint32)((uintptr_t)(&MVM_coerce_istrue_s) >> 32));
3462
0
#line 2394 "src/jit/x64/emit.dasc"
3463
0
            //| test RV, RV;
3464
0
            dasm_put(Dst, 3410);
3465
0
#line 2395 "src/jit/x64/emit.dasc"
3466
0
            if (ins->info->opcode == MVM_OP_unless_s0)
3467
0
                //| jz =>(name);
3468
0
                dasm_put(Dst, 3347, (name));
3469
0
#line 2397 "src/jit/x64/emit.dasc"
3470
0
            else
3471
0
                //| jnz =>(name);
3472
0
                dasm_put(Dst, 3336, (name));
3473
0
#line 2399 "src/jit/x64/emit.dasc"
3474
0
            break;
3475
4.16k
        case MVM_OP_ifnonnull:
3476
4.16k
            //| mov TMP1, WORK[val];
3477
4.16k
            //| test TMP1, TMP1;
3478
4.16k
            //| jz >1;
3479
4.16k
            //| get_vmnull TMP2;
3480
4.16k
            //| cmp TMP1, TMP2;
3481
4.16k
            //| je >1;
3482
4.16k
            //| jmp =>(name);
3483
4.16k
            //|1:
3484
4.16k
            dasm_put(Dst, 3419, Dt22([val]), Dt21(->instance), DtC(->VMNull), (name));
3485
4.16k
#line 2409 "src/jit/x64/emit.dasc"
3486
4.16k
            break;
3487
150
        case MVM_OP_if_s:
3488
150
            //| mov TMP1, WORK[val];
3489
150
            //| test TMP1, TMP1;
3490
150
            //| jz >1;
3491
150
            //| cmp dword STRING:TMP1->body.num_graphs, 0;
3492
150
            //| je >1;
3493
150
            //| jmp =>(name);
3494
150
            //|1:
3495
150
            dasm_put(Dst, 3451, Dt22([val]), Dt14(->body.num_graphs), (name));
3496
150
#line 2418 "src/jit/x64/emit.dasc"
3497
150
            break;
3498
266
        case MVM_OP_unless_s:
3499
266
            //| mov TMP1, WORK[val];
3500
266
            //| test TMP1, TMP1;
3501
266
            //| jz =>(name);
3502
266
            //| cmp dword STRING:TMP1->body.num_graphs, 0;
3503
266
            //| je =>(name);
3504
266
            //|1:
3505
266
            dasm_put(Dst, 3476, Dt22([val]), (name), Dt14(->body.num_graphs), (name));
3506
266
#line 2426 "src/jit/x64/emit.dasc"
3507
266
            break;
3508
347
        case MVM_OP_indexat:
3509
347
        case MVM_OP_indexnat: {
3510
347
            MVMint16 offset = ins->operands[1].reg.orig;
3511
347
            MVMuint32 str_idx = ins->operands[2].lit_str_idx;
3512
347
            //| mov ARG1, TC;
3513
347
            //| mov ARG2, WORK[val];
3514
347
            //| mov ARG3, WORK[offset];
3515
347
            //| get_string ARG4, str_idx;
3516
347
            dasm_put(Dst, 3496, Dt22([val]), Dt22([offset]));
3517
347
             MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, str_idx);
3518
347
#line 2435 "src/jit/x64/emit.dasc"
3519
347
            //| callp &MVM_string_char_at_in_string;
3520
347
            dasm_put(Dst, 3509, Dt23(->body.strings), Dt15([str_idx]));
3521
347
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_string_char_at_in_string)), (MVMuint32)((uintptr_t)(&MVM_string_char_at_in_string) >> 32));
3522
347
            dasm_put(Dst, 216);
3523
347
#line 2436 "src/jit/x64/emit.dasc"
3524
347
            /* This subtlety is due to the value being overloaded to
3525
347
             * -2 if it is out of bounds. Note that -1 is passed as a
3526
347
             * 32 bit integer, but this magically works in a 64 bit
3527
347
             * comparison because 32 bit values are sign-extended */
3528
347
            //| cmp RV, -1;
3529
347
            dasm_put(Dst, 3519);
3530
347
#line 2441 "src/jit/x64/emit.dasc"
3531
347
            if (ins->info->opcode == MVM_OP_indexat)
3532
347
                //| jle =>(name);
3533
339
                dasm_put(Dst, 3526, (name));
3534
347
#line 2443 "src/jit/x64/emit.dasc"
3535
8
            else {
3536
8
3537
8
                //| jne =>(name);
3538
8
                dasm_put(Dst, 3336, (name));
3539
8
#line 2446 "src/jit/x64/emit.dasc"
3540
8
            }
3541
347
            break;
3542
347
        }
3543
0
        case MVM_OP_lexprimspec: {
3544
0
            MVMint16 dst = ins->operands[0].reg.orig;
3545
0
            MVMint16 ctx = ins->operands[1].reg.orig;
3546
0
            MVMint16 name = ins->operands[2].reg.orig;
3547
0
            //| mov TMP1, WORK[ctx];
3548
0
            //| cmp_repr_id, TMP1, TMP2, MVM_REPR_ID_MVMContext;
3549
0
            //| jne >1;
3550
0
            //| test_type_object TMP1;
3551
0
            //| jz >2;
3552
0
            //|1:
3553
0
            //| throw_adhoc "lexprimspec needs a context";
3554
0
            dasm_put(Dst, 3530, Dt22([ctx]), DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMContext, DtE(->header.flags), MVM_CF_TYPE_OBJECT, (unsigned int)((uintptr_t)("lexprimspec needs a context")), (unsigned int)(((uintptr_t)("lexprimspec needs a context"))>>32));
3555
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
3556
0
#line 2460 "src/jit/x64/emit.dasc"
3557
0
            //|2:
3558
0
            //| mov ARG2, CONTEXT:TMP1->body.context;
3559
0
            //| mov ARG3, WORK[name];
3560
0
            //| mov ARG1, TC;
3561
0
            //| callp MVM_frame_lexical_primspec;
3562
0
            dasm_put(Dst, 2750, Dt16(->body.context), Dt22([name]));
3563
0
            dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(MVM_frame_lexical_primspec)), (MVMuint32)((uintptr_t)(MVM_frame_lexical_primspec) >> 32));
3564
0
#line 2465 "src/jit/x64/emit.dasc"
3565
0
            //| mov WORK[dst], RV;
3566
0
            dasm_put(Dst, 881, Dt22([dst]));
3567
0
#line 2466 "src/jit/x64/emit.dasc"
3568
0
            break;
3569
347
        }
3570
0
        default:
3571
0
            MVM_panic(1, "JIT: Can't handle conditional <%s>", ins->info->name);
3572
17.1k
        }
3573
17.1k
    }
3574
22.8k
}
3575
3576
void MVM_jit_emit_label(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3577
672k
                        MVMint32 label) {
3578
672k
    MVM_jit_log(tc, "Emitting label %d\n", label);
3579
672k
    //| =>(label):
3580
672k
    dasm_put(Dst, 195, (label));
3581
672k
#line 2478 "src/jit/x64/emit.dasc"
3582
672k
}
3583
3584
142k
void MVM_jit_emit_branch(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMint32 label) {
3585
142k
    //| jmp =>(label);
3586
142k
    dasm_put(Dst, 3325, (label));
3587
142k
#line 2482 "src/jit/x64/emit.dasc"
3588
142k
}
3589
3590
void MVM_jit_emit_conditional_branch(MVMThreadContext *tc, MVMJitCompiler *compiler,
3591
361k
                                     MVMint32 cond, MVMint32 label) {
3592
361k
    switch (cond) {
3593
0
    case MVM_JIT_LT:
3594
0
        //| jl =>(label);
3595
0
        dasm_put(Dst, 3572, (label));
3596
0
#line 2489 "src/jit/x64/emit.dasc"
3597
0
        break;
3598
0
    case MVM_JIT_LE:
3599
0
        //| jle =>(label);
3600
0
        dasm_put(Dst, 3526, (label));
3601
0
#line 2492 "src/jit/x64/emit.dasc"
3602
0
        break;
3603
16.9k
    case MVM_JIT_EQ:
3604
16.9k
        //| je =>(label);
3605
16.9k
        dasm_put(Dst, 3347, (label));
3606
16.9k
#line 2495 "src/jit/x64/emit.dasc"
3607
16.9k
        break;
3608
573
    case MVM_JIT_NE:
3609
573
        //| jne =>(label);
3610
573
        dasm_put(Dst, 3336, (label));
3611
573
#line 2498 "src/jit/x64/emit.dasc"
3612
573
        break;
3613
0
    case MVM_JIT_GE:
3614
0
        //| jge =>(label);
3615
0
        dasm_put(Dst, 3576, (label));
3616
0
#line 2501 "src/jit/x64/emit.dasc"
3617
0
        break;
3618
0
    case MVM_JIT_GT:
3619
0
        //| jg =>(label);
3620
0
        dasm_put(Dst, 3580, (label));
3621
0
#line 2504 "src/jit/x64/emit.dasc"
3622
0
        break;
3623
83.6k
    case MVM_JIT_NZ:
3624
83.6k
        //| jnz =>(label);
3625
83.6k
        dasm_put(Dst, 3336, (label));
3626
83.6k
#line 2507 "src/jit/x64/emit.dasc"
3627
83.6k
        break;
3628
260k
    case MVM_JIT_ZR:
3629
260k
        //| jz =>(label);
3630
260k
        dasm_put(Dst, 3347, (label));
3631
260k
#line 2510 "src/jit/x64/emit.dasc"
3632
260k
        break;
3633
0
    default:
3634
0
        MVM_oops(tc, "this condition cannot be compiled with conditional_branch");
3635
361k
    }
3636
361k
}
3637
3638
void MVM_jit_emit_guard(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3639
34.0k
                        MVMJitGuard *guard) {
3640
34.0k
    MVMint16 op        = guard->ins->info->opcode;
3641
34.0k
    MVMint16 obj       = guard->ins->operands[0].reg.orig;
3642
34.0k
    MVM_jit_log(tc, "emit guard <%s>\n", guard->ins->info->name);
3643
34.0k
    /* load object and spesh slot value, except for those that don't need it */
3644
34.0k
    //| mov TMP1, WORK[obj];
3645
34.0k
    dasm_put(Dst, 1416, Dt22([obj]));
3646
34.0k
#line 2523 "src/jit/x64/emit.dasc"
3647
34.0k
    if (op != MVM_OP_sp_guardjustconc && op != MVM_OP_sp_guardjusttype) {
3648
34.0k
        MVMint16 spesh_idx = guard->ins->operands[1].lit_i16;
3649
34.0k
        //| get_spesh_slot TMP2, spesh_idx;
3650
34.0k
        dasm_put(Dst, 3584, Dt21(->cur_frame), Dt2(->effective_spesh_slots), Dt15([spesh_idx]));
3651
34.0k
#line 2526 "src/jit/x64/emit.dasc"
3652
34.0k
    }
3653
34.0k
    if (op == MVM_OP_sp_guard) {
3654
4
        /* object in question should just match the type, so it shouldn't
3655
4
         * be zero, and the STABLE should be equal to the value in the spesh
3656
4
         * slot */
3657
4
        /* check for null */
3658
4
        //| test TMP1, TMP1;
3659
4
        //| jz >1;
3660
4
        dasm_put(Dst, 3597);
3661
4
#line 2534 "src/jit/x64/emit.dasc"
3662
4
        /* get stable and compare */
3663
4
        //| cmp TMP2, OBJECT:TMP1->st;
3664
4
        //| jne >1;
3665
4
        dasm_put(Dst, 3605, DtE(->st));
3666
4
#line 2537 "src/jit/x64/emit.dasc"
3667
4
        /* we're good, no need to deopt */
3668
34.0k
    } else if (op == MVM_OP_sp_guardtype) {
3669
2.34k
        /* object in question should be a type object, so it shouldn't
3670
2.34k
         * be zero, should not be concrete, and the STABLE should be
3671
2.34k
         * equal to the value in the spesh slot */
3672
2.34k
        /* check for null */
3673
2.34k
        //| test TMP1, TMP1;
3674
2.34k
        //| jz >1;
3675
2.34k
        dasm_put(Dst, 3597);
3676
2.34k
#line 2545 "src/jit/x64/emit.dasc"
3677
2.34k
        /* check if type object (not concrete) */
3678
2.34k
        //| test_type_object TMP1;
3679
2.34k
        dasm_put(Dst, 3614, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3680
2.34k
#line 2547 "src/jit/x64/emit.dasc"
3681
2.34k
        /* if zero, this is a concrete object, and we should deopt */
3682
2.34k
        //| jz >1;
3683
2.34k
        dasm_put(Dst, 2841);
3684
2.34k
#line 2549 "src/jit/x64/emit.dasc"
3685
2.34k
        /* get stable and compare */
3686
2.34k
        //| cmp TMP2, OBJECT:TMP1->st;
3687
2.34k
        //| jne >1;
3688
2.34k
        dasm_put(Dst, 3605, DtE(->st));
3689
2.34k
#line 2552 "src/jit/x64/emit.dasc"
3690
2.34k
        /* we're good, no need to deopt */
3691
31.7k
    } else if (op == MVM_OP_sp_guardconc) {
3692
24.8k
        /* object should be a non-null concrete (non-type) object */
3693
24.8k
        //| test TMP1, TMP1;
3694
24.8k
        //| jz >1;
3695
24.8k
        dasm_put(Dst, 3597);
3696
24.8k
#line 2557 "src/jit/x64/emit.dasc"
3697
24.8k
        /* shouldn't be type object */
3698
24.8k
        //| test_type_object TMP1;
3699
24.8k
        //| jnz >1;
3700
24.8k
        dasm_put(Dst, 3621, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3701
24.8k
#line 2560 "src/jit/x64/emit.dasc"
3702
24.8k
        /* should have our stable */
3703
24.8k
        //| cmp TMP2, OBJECT:TMP1->st;
3704
24.8k
        //| jne >1;
3705
24.8k
        dasm_put(Dst, 3605, DtE(->st));
3706
24.8k
#line 2563 "src/jit/x64/emit.dasc"
3707
6.89k
    } else if (op == MVM_OP_sp_guardsf) {
3708
6.88k
        /* Should be an MVMCode */
3709
6.88k
        //| cmp_repr_id TMP1, TMP3, MVM_REPR_ID_MVMCode;
3710
6.88k
        //| jne >1;
3711
6.88k
        //| cmp TMP2, CODE:TMP1->body.sf;
3712
6.88k
        //| jne >1;
3713
6.88k
        dasm_put(Dst, 3632, DtE(->st), Dt12(->REPR), Dt13(->ID), MVM_REPR_ID_MVMCode, Dt1C(->body.sf));
3714
6.88k
#line 2569 "src/jit/x64/emit.dasc"
3715
8
    } else if (op == MVM_OP_sp_guardobj) {
3716
2
        /* object should match that from the spesh slot */
3717
2
        //| cmp TMP2, TMP1;
3718
2
        //| jne >1;
3719
2
        dasm_put(Dst, 3658);
3720
2
#line 2573 "src/jit/x64/emit.dasc"
3721
6
    } else if (op == MVM_OP_sp_guardjustconc) {
3722
2
        /* object should be a non-null concrete (non-type) object;
3723
2
         * exact type doesn't matter */
3724
2
        //| test TMP1, TMP1;
3725
2
        //| jz >1;
3726
2
        dasm_put(Dst, 3597);
3727
2
#line 2578 "src/jit/x64/emit.dasc"
3728
2
        /* shouldn't be type object */
3729
2
        //| test_type_object TMP1;
3730
2
        //| jnz >1;
3731
2
        dasm_put(Dst, 3621, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3732
2
#line 2581 "src/jit/x64/emit.dasc"
3733
4
    } else if (op == MVM_OP_sp_guardjusttype) {
3734
4
        /* object in question should be a type object, so it shouldn't
3735
4
         * be zero, and should not be concrete */
3736
4
        /* check for null */
3737
4
        //| test TMP1, TMP1;
3738
4
        //| jz >1;
3739
4
        dasm_put(Dst, 3597);
3740
4
#line 2587 "src/jit/x64/emit.dasc"
3741
4
        /* should be type object */
3742
4
        //| test_type_object TMP1;
3743
4
        //| jz >1;
3744
4
        dasm_put(Dst, 3666, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3745
4
#line 2590 "src/jit/x64/emit.dasc"
3746
4
    }
3747
34.0k
    /* if we're here, we didn't jump to deopt, so skip it */
3748
34.0k
    //| jmp >2;
3749
34.0k
    //|1:
3750
34.0k
    dasm_put(Dst, 2141);
3751
34.0k
#line 2594 "src/jit/x64/emit.dasc"
3752
34.0k
    /* emit deopt */
3753
34.0k
    //| mov ARG1, TC;
3754
34.0k
    //| mov ARG2, guard->deopt_offset;
3755
34.0k
    //| mov ARG3, guard->deopt_target;
3756
34.0k
    //| callp &MVM_spesh_deopt_one_direct;
3757
34.0k
    dasm_put(Dst, 3677, guard->deopt_offset, guard->deopt_target);
3758
34.0k
    dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_spesh_deopt_one_direct)), (MVMuint32)((uintptr_t)(&MVM_spesh_deopt_one_direct) >> 32));
3759
34.0k
    dasm_put(Dst, 216);
3760
34.0k
#line 2599 "src/jit/x64/emit.dasc"
3761
34.0k
    /* jump out */
3762
34.0k
    //| jmp ->exit;
3763
34.0k
    //|2:
3764
34.0k
    dasm_put(Dst, 3691);
3765
34.0k
#line 2602 "src/jit/x64/emit.dasc"
3766
34.0k
}
3767
3768
24.1k
void MVM_jit_emit_invoke(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg, MVMJitInvoke *invoke) {
3769
24.1k
    MVMint16 i;
3770
24.1k
    MVMuint16 callsite_idx = invoke->callsite_idx;
3771
24.1k
    MVM_jit_log(tc, "Emit invoke (%d args)\n", invoke->arg_count);
3772
24.1k
    /* Store callsite in tmp6, which we use at the end of invoke */
3773
24.1k
    //| mov TMP6, CU->body.callsites;
3774
24.1k
    //| mov TMP6, CALLSITEPTR:TMP6[callsite_idx];
3775
24.1k
    dasm_put(Dst, 3036, Dt23(->body.callsites), Dt4([callsite_idx]));
3776
24.1k
#line 2611 "src/jit/x64/emit.dasc"
3777
24.1k
3778
24.1k
    /* Store callsite in the frame. I use TMP5 as it never conflicts
3779
24.1k
     * with argument passing (like TMP6, but unlike other TMP regs) */
3780
24.1k
    //| mov TMP5, TC->cur_frame;
3781
24.1k
    //| mov FRAME:TMP5->cur_args_callsite, TMP6;
3782
24.1k
    dasm_put(Dst, 3698, Dt21(->cur_frame), Dt2(->cur_args_callsite));
3783
24.1k
#line 2616 "src/jit/x64/emit.dasc"
3784
24.1k
3785
24.1k
    /* Setup the frame for returning to our current position */
3786
24.1k
    if (sizeof(MVMReturnType) == 1) {
3787
24.1k
        //| mov byte FRAME:TMP5->return_type, invoke->return_type;
3788
24.1k
        dasm_put(Dst, 3707, Dt2(->return_type), invoke->return_type);
3789
24.1k
#line 2620 "src/jit/x64/emit.dasc"
3790
0
    } else {
3791
0
        MVM_panic(1, "JIT: MVMReturnType has unexpected size");
3792
0
    }
3793
24.1k
    /* The register for our return value */
3794
24.1k
    if (invoke->return_type == MVM_RETURN_VOID) {
3795
471
        //| mov aword FRAME:TMP5->return_value, NULL;
3796
471
        dasm_put(Dst, 3713, Dt2(->return_value), NULL);
3797
471
#line 2626 "src/jit/x64/emit.dasc"
3798
23.6k
    } else {
3799
23.6k
        //| lea TMP2, WORK[invoke->return_register];
3800
23.6k
        //| mov aword FRAME:TMP5->return_value, TMP2;
3801
23.6k
        dasm_put(Dst, 3719, Dt22([invoke->return_register]), Dt2(->return_value));
3802
23.6k
#line 2629 "src/jit/x64/emit.dasc"
3803
23.6k
    }
3804
24.1k
    /* The return address for the interpreter */
3805
24.1k
    //| get_cur_op TMP2;
3806
24.1k
    //| mov aword FRAME:TMP5->return_address, TMP2;
3807
24.1k
    dasm_put(Dst, 3728, Dt21(->interp_cur_op), Dt2(->return_address));
3808
24.1k
#line 2633 "src/jit/x64/emit.dasc"
3809
24.1k
3810
24.1k
    /* Install invoke args */
3811
24.1k
    //| mov TMP5, FRAME:TMP5->args;
3812
24.1k
    dasm_put(Dst, 184, Dt2(->args));
3813
24.1k
#line 2636 "src/jit/x64/emit.dasc"
3814
74.8k
    for (i = 0;  i < invoke->arg_count; i++) {
3815
50.7k
        MVMSpeshIns *ins = invoke->arg_ins[i];
3816
50.7k
        switch (ins->info->opcode) {
3817
47.9k
        case MVM_OP_arg_i:
3818
47.9k
        case MVM_OP_arg_s:
3819
47.9k
        case MVM_OP_arg_n:
3820
47.9k
        case MVM_OP_arg_o: {
3821
47.9k
            MVMint16 dst = ins->operands[0].lit_i16;
3822
47.9k
            MVMint16 src = ins->operands[1].reg.orig;
3823
47.9k
            //| mov TMP4, WORK[src];
3824
47.9k
            //| mov REGISTER:TMP5[dst], TMP4;
3825
47.9k
            dasm_put(Dst, 3740, Dt22([src]), Dt1([dst]));
3826
47.9k
#line 2647 "src/jit/x64/emit.dasc"
3827
47.9k
            break;
3828
47.9k
        }
3829
0
        case MVM_OP_argconst_n:
3830
0
        case MVM_OP_argconst_i: {
3831
0
            MVMint16 dst = ins->operands[0].lit_i16;
3832
0
            MVMint64 val = ins->operands[1].lit_i64;
3833
0
            //| mov64 TMP4, val;
3834
0
            //| mov REGISTER:TMP5[dst], TMP4;
3835
0
            dasm_put(Dst, 3749, (unsigned int)(val), (unsigned int)((val)>>32), Dt1([dst]));
3836
0
#line 2655 "src/jit/x64/emit.dasc"
3837
0
            break;
3838
0
        }
3839
2.77k
        case MVM_OP_argconst_s: {
3840
2.77k
            MVMint16 dst = ins->operands[0].lit_i16;
3841
2.77k
            MVMint32 idx = ins->operands[1].lit_str_idx;
3842
2.77k
            //| get_string TMP4, idx;
3843
2.77k
             MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
3844
2.77k
#line 2661 "src/jit/x64/emit.dasc"
3845
2.77k
            //| mov REGISTER:TMP5[dst], TMP4;
3846
2.77k
            dasm_put(Dst, 3758, Dt23(->body.strings), Dt15([idx]), Dt1([dst]));
3847
2.77k
#line 2662 "src/jit/x64/emit.dasc"
3848
2.77k
            break;
3849
0
        }
3850
0
        default:
3851
0
            MVM_panic(1, "JIT invoke: Can't add arg <%s>",
3852
0
                      ins->info->name);
3853
50.7k
        }
3854
50.7k
    }
3855
24.1k
3856
24.1k
    /* if we're not fast, then we should get the code from multi resolution */
3857
24.1k
    if (!invoke->is_fast) {
3858
17.3k
        /* first, save callsite and args */
3859
17.3k
        //| mov qword [rbp-0x28], TMP5; // args
3860
17.3k
        //| mov qword [rbp-0x30], TMP6; // callsite
3861
17.3k
        dasm_put(Dst, 3771);
3862
17.3k
#line 2675 "src/jit/x64/emit.dasc"
3863
17.3k
        /* setup call MVM_frame_multi_ok(tc, code, &cur_callsite, args); */
3864
17.3k
        //| mov ARG1, TC;
3865
17.3k
        //| mov ARG2, WORK[invoke->code_register]; // code object
3866
17.3k
        //| lea ARG3, [rbp-0x30];                  // &cur_callsite
3867
17.3k
        //| mov ARG4, TMP5;                        // args
3868
17.3k
        //|.if WIN32;
3869
17.3k
        //| mov qword [rsp+0x20], 0
3870
17.3k
        //|.else;
3871
17.3k
        //| mov ARG5, 0;                           // NULL to &was_multi
3872
17.3k
        //|.endif
3873
17.3k
        //| callp &MVM_frame_find_invokee_multi_ok;
3874
17.3k
        dasm_put(Dst, 3780, Dt22([invoke->code_register]));
3875
17.3k
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee_multi_ok)), (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee_multi_ok) >> 32));
3876
17.3k
        dasm_put(Dst, 216);
3877
17.3k
#line 2686 "src/jit/x64/emit.dasc"
3878
17.3k
        /* restore callsite, args, RV now holds code object */
3879
17.3k
        //| mov TMP6, [rbp-0x30]; // callsite
3880
17.3k
        //| mov TMP5, [rbp-0x28]; // args
3881
17.3k
        dasm_put(Dst, 3804);
3882
17.3k
#line 2689 "src/jit/x64/emit.dasc"
3883
17.3k
        /* setup args for call to invoke(tc, code, cur_callsite, args) */
3884
17.3k
        //| mov ARG1, TC;
3885
17.3k
        //| mov ARG2, RV;   // code object
3886
17.3k
        //| mov ARG3, TMP6; // callsite
3887
17.3k
        //| mov ARG4, TMP5; // args
3888
17.3k
        dasm_put(Dst, 3813);
3889
17.3k
#line 2694 "src/jit/x64/emit.dasc"
3890
17.3k
        /* get the actual function */
3891
17.3k
        //| mov FUNCTION, OBJECT:RV->st;
3892
17.3k
        //| mov FUNCTION, STABLE:FUNCTION->invoke;
3893
17.3k
        //| call FUNCTION;
3894
17.3k
        dasm_put(Dst, 3827, DtE(->st), Dt12(->invoke));
3895
17.3k
#line 2698 "src/jit/x64/emit.dasc"
3896
6.77k
    } else {
3897
6.77k
        /* call MVM_frame_invoke_code */
3898
6.77k
        //| mov ARG1, TC;
3899
6.77k
        //| mov ARG2, WORK[invoke->code_register];
3900
6.77k
        //| mov ARG3, TMP6; // this is the callsite object
3901
6.77k
        //| mov ARG4, invoke->spesh_cand;
3902
6.77k
        //| callp &MVM_frame_invoke_code;
3903
6.77k
        dasm_put(Dst, 3840, Dt22([invoke->code_register]), invoke->spesh_cand);
3904
6.77k
        dasm_put(Dst, 210, (MVMuint32)((uintptr_t)(&MVM_frame_invoke_code)), (MVMuint32)((uintptr_t)(&MVM_frame_invoke_code) >> 32));
3905
6.77k
        dasm_put(Dst, 216);
3906
6.77k
#line 2705 "src/jit/x64/emit.dasc"
3907
6.77k
    }
3908
24.1k
}
3909
3910
void MVM_jit_emit_jumplist(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitGraph *jg,
3911
577
                           MVMJitJumpList *jumplist) {
3912
577
    MVMint32 i;
3913
577
    MVM_jit_log(tc, "Emit jumplist (%"PRId64" labels)\n", jumplist->num_labels);
3914
577
    //| mov TMP1, WORK[jumplist->reg];
3915
577
    //| cmp TMP1, 0;
3916
577
    //| jl >2;
3917
577
    //| cmp TMP1, jumplist->num_labels;
3918
577
    //| jge >2;
3919
577
    //| imul TMP1, 0x8; // 8 bytes per goto
3920
577
    //| lea TMP2, [>1];
3921
577
    //| add TMP2, TMP1;
3922
577
    //| jmp TMP2;
3923
577
    //|.align 8;
3924
577
    //|1:
3925
577
    dasm_put(Dst, 3857, Dt22([jumplist->reg]), jumplist->num_labels);
3926
577
#line 2723 "src/jit/x64/emit.dasc"
3927
5.64k
    for (i = 0; i < jumplist->num_labels; i++) {
3928
5.06k
        //|=>(jumplist->in_labels[i]):
3929
5.06k
        //| jmp =>(jumplist->out_labels[i]);
3930
5.06k
        //|.align 8;
3931
5.06k
        dasm_put(Dst, 3899, (jumplist->in_labels[i]), (jumplist->out_labels[i]));
3932
5.06k
#line 2727 "src/jit/x64/emit.dasc"
3933
5.06k
    }
3934
577
    //|2:
3935
577
    dasm_put(Dst, 298);
3936
577
#line 2729 "src/jit/x64/emit.dasc"
3937
577
}
3938
3939
void MVM_jit_emit_control(MVMThreadContext *tc, MVMJitCompiler *compiler,
3940
0
                          MVMJitControl *ctrl, MVMJitTile *tile) {
3941
0
    MVMJitControlType type = (tile != NULL ? tile->args[0] : ctrl->type);
3942
0
    if (type == MVM_JIT_CONTROL_BREAKPOINT) {
3943
0
        /* Debug breakpoint */
3944
0
        //| int 3;
3945
0
        dasm_put(Dst, 3906);
3946
0
#line 2737 "src/jit/x64/emit.dasc"
3947
0
    } else {
3948
0
        MVM_panic(1, "Unknown control code: <%s>", ctrl->ins->info->name);
3949
0
    }
3950
0
}
3951
3952
3953
void MVM_jit_emit_load(MVMThreadContext *tc, MVMJitCompiler *compiler,
3954
                       MVMint32 reg_cls, MVMint8 reg_dst,
3955
427k
                       MVMint32 mem_cls, MVMint32 mem_src, MVMint32 size) {
3956
427k
    MVMint8 mem_base;
3957
427k
    if (mem_cls == MVM_JIT_STORAGE_LOCAL) {
3958
427k
        mem_base = MVM_JIT_REG(RBX);
3959
0
    } else if (mem_cls == MVM_JIT_STORAGE_STACK) {
3960
0
        mem_base = MVM_JIT_REG(RSP);
3961
0
    } else {
3962
0
        MVM_panic(1, "Cannot refer to this memory class: %d", mem_cls);
3963
0
    }
3964
427k
    if (reg_cls == MVM_JIT_STORAGE_GPR) {
3965
427k
        switch(size) {
3966
0
        case 1:
3967
0
            //| mov Rb(reg_dst), byte [Rq(mem_base)+mem_src];
3968
0
            dasm_put(Dst, 3909, (reg_dst), (mem_base), mem_src);
3969
0
#line 2758 "src/jit/x64/emit.dasc"
3970
0
            break;
3971
0
        case 2:
3972
0
            //| mov Rw(reg_dst), word [Rq(mem_base)+mem_src];
3973
0
            dasm_put(Dst, 3920, (reg_dst), (mem_base), mem_src);
3974
0
#line 2761 "src/jit/x64/emit.dasc"
3975
0
            break;
3976
0
        case 4:
3977
0
            //| mov Rd(reg_dst), dword [Rq(mem_base)+mem_src];
3978
0
            dasm_put(Dst, 3921, (reg_dst), (mem_base), mem_src);
3979
0
#line 2764 "src/jit/x64/emit.dasc"
3980
0
            break;
3981
427k
        case 8:
3982
427k
            //| mov Rq(reg_dst), qword [Rq(mem_base)+mem_src];
3983
427k
            dasm_put(Dst, 3931, (reg_dst), (mem_base), mem_src);
3984
427k
#line 2767 "src/jit/x64/emit.dasc"
3985
427k
            break;
3986
427k
        }
3987
427k
    }
3988
427k
}
3989
3990
void MVM_jit_emit_store(MVMThreadContext *tc, MVMJitCompiler *compiler,
3991
                        MVMint32 mem_cls, MVMint32 mem_dst,
3992
104k
                        MVMint32 reg_cls, MVMint8 reg_src, MVMint32 size) {
3993
104k
3994
104k
    MVMint8 mem_base;
3995
104k
    if (mem_cls == MVM_JIT_STORAGE_LOCAL) {
3996
79.5k
        mem_base = MVM_JIT_REG(RBX);
3997
24.8k
    } else if (mem_cls == MVM_JIT_STORAGE_STACK) {
3998
24.8k
        mem_base = MVM_JIT_REG(RSP);
3999
0
    } else {
4000
0
        MVM_panic(1, "Cannot refer to this memory class: %d", mem_cls);
4001
0
    }
4002
104k
    if (reg_cls == MVM_JIT_STORAGE_GPR) {
4003
104k
        switch (size) {
4004
0
        case 1:
4005
0
            //| mov byte [Rq(mem_base)+mem_dst], Rb(reg_src);
4006
0
            dasm_put(Dst, 3942, (reg_src), (mem_base), mem_dst);
4007
0
#line 2788 "src/jit/x64/emit.dasc"
4008
0
            break;
4009
0
        case 2:
4010
0
            //| mov word [Rq(mem_base)+mem_dst], Rw(reg_src);
4011
0
            dasm_put(Dst, 3953, (reg_src), (mem_base), mem_dst);
4012
0
#line 2791 "src/jit/x64/emit.dasc"
4013
0
            break;
4014
0
        case 4:
4015
0
            //| mov dword [Rq(mem_base)+mem_dst], Rd(reg_src);
4016
0
            dasm_put(Dst, 3954, (reg_src), (mem_base), mem_dst);
4017
0
#line 2794 "src/jit/x64/emit.dasc"
4018
0
            break;
4019
104k
        case 8:
4020
104k
            //| mov qword [Rq(mem_base)+mem_dst], Rq(reg_src);
4021
104k
            dasm_put(Dst, 3964, (reg_src), (mem_base), mem_dst);
4022
104k
#line 2797 "src/jit/x64/emit.dasc"
4023
104k
            break;
4024
104k
        }
4025
104k
    }
4026
104k
}
4027
4028
void MVM_jit_emit_copy(MVMThreadContext *tc, MVMJitCompiler *compiler,
4029
906k
                       MVMint32 dst_cls,  MVMint8 dst_reg, MVMint32 src_cls, MVMint8 src_reg) {
4030
906k
    if (dst_cls == src_cls) {
4031
906k
        if (dst_cls == MVM_JIT_STORAGE_GPR) {
4032
906k
            //| mov Rq(dst_reg), Rq(src_reg);
4033
906k
            dasm_put(Dst, 3975, (src_reg), (dst_reg));
4034
906k
#line 2807 "src/jit/x64/emit.dasc"
4035
0
        } else {
4036
0
            MVM_oops(tc, "numeric regs nyi");
4037
0
        }
4038
0
    } else {
4039
0
        MVM_oops(tc, "numeric regs nyi");
4040
0
    }
4041
906k
}
4042
4043
4044
0
void MVM_jit_emit_marker(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMint32 num) {
4045
0
    MVMint32 i;
4046
0
    for (i = 0; i < num; i++) {
4047
0
        //| nop;
4048
0
        dasm_put(Dst, 3984);
4049
0
#line 2820 "src/jit/x64/emit.dasc"
4050
0
    }
4051
0
}
4052
4053
4054
0
void MVM_jit_emit_data(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitData *data) {
4055
0
    MVMuint8 *bytes = data->data;
4056
0
    MVMint32 i;
4057
0
    //|.data;
4058
0
    dasm_put(Dst, 208);
4059
0
#line 2828 "src/jit/x64/emit.dasc"
4060
0
    //|=>(data->label):
4061
0
    dasm_put(Dst, 195, (data->label));
4062
0
#line 2829 "src/jit/x64/emit.dasc"
4063
0
    for (i = 0; i < data->size; i++) {
4064
0
        //|.byte bytes[i];
4065
0
        dasm_put(Dst, 2682, bytes[i]);
4066
0
#line 2831 "src/jit/x64/emit.dasc"
4067
0
    }
4068
0
    //|.code
4069
0
    dasm_put(Dst, 0);
4070
0
#line 2833 "src/jit/x64/emit.dasc"
4071
0
}
4072
4073
/* import tiles */
4074
//|.include src/jit/x64/tiles.dasc
4075
#line 1 "src/jit/x64/tiles.dasc"
4076
/* -*-C-*- */
4077
#include "tile_decl.h"
4078
4079
/* NB: The rax/eax/ax/al/ah register is *reserved* for internal use in tiles by
4080
 * the register allocator. Using rax will never overwrite an allocated value */
4081
4082
/* basic memory traffic tiles */
4083
184k
MVM_JIT_TILE_DECL(addr) {
4084
184k
    MVMint8 out  = tile->values[0];
4085
184k
    MVMint8 base = tile->values[1];
4086
184k
    MVMint32 ofs = tile->args[0];
4087
184k
    //| lea Rq(out), [Rq(base)+ofs];
4088
184k
    dasm_put(Dst, 3986, (out), (base), ofs);
4089
184k
#line 13 "src/jit/x64/tiles.dasc"
4090
184k
}
4091
4092
4093
0
MVM_JIT_TILE_DECL(idx) {
4094
0
    MVMint8 out  = tile->values[0];
4095
0
    MVMint8 base = tile->values[1];
4096
0
    MVMint8 idx  = tile->values[2];
4097
0
    MVMint8 scl  = tile->args[0];
4098
0
    if (scl == 8) {
4099
0
        //| lea Rq(out), [Rq(base)+Rq(idx)*8];
4100
0
        dasm_put(Dst, 3997, (out), (idx), (base), 0);
4101
0
#line 23 "src/jit/x64/tiles.dasc"
4102
0
    } else {
4103
0
        MVM_oops(tc, "Scales other than 8 NYI\n");
4104
0
    }
4105
0
}
4106
4107
4108
291k
MVM_JIT_TILE_DECL(const_reg) {
4109
291k
    MVMint8 out = tile->values[0];
4110
291k
    MVMint64 val  = tile->args[0];
4111
291k
    MVMint32 size = tile->args[1];
4112
291k
    if (size == 8 && !fits_in_32_bit(val)) {
4113
777
        //| mov64 Rq(out), val;
4114
777
        dasm_put(Dst, 4011, (out), (unsigned int)(val), (unsigned int)((val)>>32));
4115
777
#line 35 "src/jit/x64/tiles.dasc"
4116
290k
    } else {
4117
290k
        //| mov Rq(out), val;
4118
290k
        dasm_put(Dst, 4019, (out), val);
4119
290k
#line 37 "src/jit/x64/tiles.dasc"
4120
290k
    }
4121
291k
}
4122
4123
4124
22.3k
MVM_JIT_TILE_DECL(load_reg) {
4125
22.3k
    MVMint8 out  = tile->values[0];
4126
22.3k
    MVMint8 base = tile->values[1];
4127
22.3k
    MVMint32 size = tile->args[0];
4128
22.3k
    switch (size) {
4129
0
    case 1:
4130
0
        //| mov Rb(out), [Rq(base)];
4131
0
        dasm_put(Dst, 4027, (out), (base), 0);
4132
0
#line 48 "src/jit/x64/tiles.dasc"
4133
0
        break;
4134
0
    case 2:
4135
0
        //| mov Rw(out), [Rq(base)];
4136
0
        dasm_put(Dst, 3920, (out), (base), 0);
4137
0
#line 51 "src/jit/x64/tiles.dasc"
4138
0
        break;
4139
0
    case 4:
4140
0
        //| mov Rd(out), [Rq(base)];
4141
0
        dasm_put(Dst, 3921, (out), (base), 0);
4142
0
#line 54 "src/jit/x64/tiles.dasc"
4143
0
        break;
4144
22.3k
    case 8:
4145
22.3k
        //| mov Rq(out), [Rq(base)];
4146
22.3k
        dasm_put(Dst, 3931, (out), (base), 0);
4147
22.3k
#line 57 "src/jit/x64/tiles.dasc"
4148
22.3k
        break;
4149
0
    default:
4150
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4151
22.3k
    }
4152
22.3k
}
4153
4154
1.08M
MVM_JIT_TILE_DECL(load_addr) {
4155
1.08M
    MVMint8 out  = tile->values[0];
4156
1.08M
    MVMint8 base = tile->values[1];
4157
1.08M
    MVMint32 ofs  = tile->args[0];
4158
1.08M
    MVMint32 size = tile->args[1];
4159
1.08M
    switch (tile->args[1]) {
4160
0
    case 1:
4161
0
        //| mov Rb(out), byte [Rq(base)+ofs];
4162
0
        dasm_put(Dst, 3909, (out), (base), ofs);
4163
0
#line 71 "src/jit/x64/tiles.dasc"
4164
0
        break;
4165
0
    case 2:
4166
0
        //| mov Rw(out), word [Rq(base)+ofs];
4167
0
        dasm_put(Dst, 3920, (out), (base), ofs);
4168
0
#line 74 "src/jit/x64/tiles.dasc"
4169
0
        break;
4170
6.09k
    case 4:
4171
6.09k
        //| mov Rd(out), dword [Rq(base)+ofs];
4172
6.09k
        dasm_put(Dst, 3921, (out), (base), ofs);
4173
6.09k
#line 77 "src/jit/x64/tiles.dasc"
4174
6.09k
        break;
4175
1.07M
    case 8:
4176
1.07M
        //| mov Rq(out), qword [Rq(base)+ofs];
4177
1.07M
        dasm_put(Dst, 3931, (out), (base), ofs);
4178
1.07M
#line 80 "src/jit/x64/tiles.dasc"
4179
1.07M
        break;
4180
0
    default:
4181
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4182
1.08M
    }
4183
1.08M
}
4184
4185
108k
MVM_JIT_TILE_DECL(load_idx) {
4186
108k
    MVMint8 out  = tile->values[0];
4187
108k
    MVMint8 base = tile->values[1];
4188
108k
    MVMint8 idx  = tile->values[2];
4189
108k
    MVMint8 scl  = tile->args[0];
4190
108k
    MVMint32 size = tile->args[1];
4191
108k
    if (scl != 8) {
4192
0
        MVM_oops(tc, "Unsupported scale size: %d\n", scl);
4193
0
    }
4194
108k
    switch (size) {
4195
0
    case 1:
4196
0
        //| mov Rb(out), byte [Rq(base)+Rq(idx)*8];
4197
0
        dasm_put(Dst, 4037, (out), (idx), (base), 0);
4198
0
#line 98 "src/jit/x64/tiles.dasc"
4199
0
        break;
4200
0
    case 2:
4201
0
        //| mov Rw(out), word [Rq(base)+Rq(idx)*8];
4202
0
        dasm_put(Dst, 4051, (out), (idx), (base), 0);
4203
0
#line 101 "src/jit/x64/tiles.dasc"
4204
0
        break;
4205
0
    case 4:
4206
0
        //| mov Rd(out), dword [Rq(base)+Rq(idx)*8];
4207
0
        dasm_put(Dst, 4052, (out), (idx), (base), 0);
4208
0
#line 104 "src/jit/x64/tiles.dasc"
4209
0
        break;
4210
108k
    case 8:
4211
108k
        //| mov Rq(out), qword [Rq(base)+Rq(idx)*8];
4212
108k
        dasm_put(Dst, 4065, (out), (idx), (base), 0);
4213
108k
#line 107 "src/jit/x64/tiles.dasc"
4214
108k
        break;
4215
0
    default:
4216
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4217
108k
    }
4218
108k
}
4219
4220
4221
26.6k
MVM_JIT_TILE_DECL(store) {
4222
26.6k
    MVMint8 base  = tile->values[1];
4223
26.6k
    MVMint8 value = tile->values[2];
4224
26.6k
    MVMint32 size = tile->args[0];
4225
26.6k
    switch (size) {
4226
0
    case 1:
4227
0
        //| mov byte [Rq(base)], Rb(value);
4228
0
        dasm_put(Dst, 3942, (value), (base), 0);
4229
0
#line 121 "src/jit/x64/tiles.dasc"
4230
0
        break;
4231
0
    case 2:
4232
0
        //| mov word [Rq(base)], Rw(value);
4233
0
        dasm_put(Dst, 3953, (value), (base), 0);
4234
0
#line 124 "src/jit/x64/tiles.dasc"
4235
0
        break;
4236
0
    case 4:
4237
0
        //| mov dword [Rq(base)], Rd(value);
4238
0
        dasm_put(Dst, 3954, (value), (base), 0);
4239
0
#line 127 "src/jit/x64/tiles.dasc"
4240
0
        break;
4241
26.6k
    case 8:
4242
26.6k
        //| mov qword [Rq(base)], Rq(value);
4243
26.6k
        dasm_put(Dst, 3964, (value), (base), 0);
4244
26.6k
#line 130 "src/jit/x64/tiles.dasc"
4245
26.6k
        break;
4246
0
    default:
4247
0
        MVM_oops(tc, "Unsupported store size: %d\n", size);
4248
26.6k
    }
4249
26.6k
}
4250
4251
446k
MVM_JIT_TILE_DECL(store_addr) {
4252
446k
    MVMint8 base  = tile->values[1];
4253
446k
    MVMint8 value = tile->values[2];
4254
446k
    MVMint32 ofs  = tile->args[0];
4255
446k
    MVMint32 size = tile->args[1];
4256
446k
    switch (size) {
4257
0
    case 1:
4258
0
        //| mov byte [Rq(base)+ofs], Rb(value);
4259
0
        dasm_put(Dst, 3942, (value), (base), ofs);
4260
0
#line 144 "src/jit/x64/tiles.dasc"
4261
0
        break;
4262
5.52k
    case 2:
4263
5.52k
        //| mov word [Rq(base)+ofs], Rw(value);
4264
5.52k
        dasm_put(Dst, 3953, (value), (base), ofs);
4265
5.52k
#line 147 "src/jit/x64/tiles.dasc"
4266
5.52k
        break;
4267
5.52k
    case 4:
4268
5.52k
        //| mov dword [Rq(base)+ofs], Rd(value);
4269
5.52k
        dasm_put(Dst, 3954, (value), (base), ofs);
4270
5.52k
#line 150 "src/jit/x64/tiles.dasc"
4271
5.52k
        break;
4272
435k
    case 8:
4273
435k
        //| mov qword [Rq(base)+ofs], Rq(value);
4274
435k
        dasm_put(Dst, 3964, (value), (base), ofs);
4275
435k
#line 153 "src/jit/x64/tiles.dasc"
4276
435k
        break;
4277
0
    default:
4278
0
        MVM_oops(tc, "Unsupported store size: %d\n", size);
4279
446k
    }
4280
446k
}
4281
4282
0
MVM_JIT_TILE_DECL(store_idx) {
4283
0
    MVMint8 base = tile->values[1];
4284
0
    MVMint8 idx  = tile->values[2];
4285
0
    MVMint8 scl  = tile->args[0];
4286
0
    MVMint32 size = tile->args[1];
4287
0
    MVMint8 value = tile->values[3];
4288
0
    if (scl != 8)
4289
0
        MVM_oops(tc, "Scale %d NYI\n", scl);
4290
0
    switch (size) {
4291
0
    case 1:
4292
0
        //| mov byte [Rq(base)+Rq(idx)*8], Rb(value);
4293
0
        dasm_put(Dst, 4079, (value), (idx), (base), 0);
4294
0
#line 170 "src/jit/x64/tiles.dasc"
4295
0
        break;
4296
0
    case 2:
4297
0
        //| mov word [Rq(base)+Rq(idx)*8], Rw(value);
4298
0
        dasm_put(Dst, 4093, (value), (idx), (base), 0);
4299
0
#line 173 "src/jit/x64/tiles.dasc"
4300
0
        break;
4301
0
    case 4:
4302
0
        //| mov dword [Rq(base)+Rq(idx)*8], Rd(value);
4303
0
        dasm_put(Dst, 4094, (value), (idx), (base), 0);
4304
0
#line 176 "src/jit/x64/tiles.dasc"
4305
0
        break;
4306
0
    case 8:
4307
0
        //| mov qword [Rq(base)+Rq(idx)*8], Rq(value);
4308
0
        dasm_put(Dst, 4107, (value), (idx), (base), 0);
4309
0
#line 179 "src/jit/x64/tiles.dasc"
4310
0
        break;
4311
0
    default:
4312
0
        MVM_oops(tc, "Unsupported store size: %d\n", size);
4313
0
    }
4314
0
}
4315
4316
4317
3.91k
MVM_JIT_TILE_DECL(cast) {
4318
3.91k
    MVMint32 to_size   = tile->args[0];
4319
3.91k
    MVMint32 from_size = tile->args[1];
4320
3.91k
    MVMint32 is_signed = tile->args[2];
4321
3.91k
4322
3.91k
    MVMint8  to_reg    = tile->values[0];
4323
3.91k
    MVMint8  from_reg  = tile->values[1];
4324
3.91k
4325
3.91k
    /* possible combinations: 1 -> 2, 4, 8; 2 -> 4, 8; 4 -> 8
4326
3.91k
     * Hence we can combine from_size | (to_size << 3) to get
4327
3.91k
     * the following options:
4328
3.91k
     * 1 + 2<<3 == 17
4329
3.91k
     * 1 + 4<<3 == 33
4330
3.91k
     * 1 + 8<<3 == 65
4331
3.91k
     * 2 + 4<<3 == 34
4332
3.91k
     * 2 + 8<<3 == 66
4333
3.91k
     * 4 + 8<<3 == 68
4334
3.91k
     */
4335
3.91k
    MVMint32 size_conv = (from_size) | (to_size << 3);
4336
3.91k
    if (is_signed == MVM_JIT_SIGNED) {
4337
3.91k
        switch (size_conv) {
4338
0
        case 17:
4339
0
            //| movsx Rw(to_reg), Rb(from_reg);
4340
0
            dasm_put(Dst, 4121, (to_reg), (from_reg));
4341
0
#line 209 "src/jit/x64/tiles.dasc"
4342
0
            break;
4343
0
        case 33:
4344
0
            //| movsx Rd(to_reg), Rb(from_reg);
4345
0
            dasm_put(Dst, 4122, (to_reg), (from_reg));
4346
0
#line 212 "src/jit/x64/tiles.dasc"
4347
0
            break;
4348
0
        case 34:
4349
0
            //| movsx Rd(to_reg), Rw(from_reg);
4350
0
            dasm_put(Dst, 4132, (to_reg), (from_reg));
4351
0
#line 215 "src/jit/x64/tiles.dasc"
4352
0
            break;
4353
0
        case 65:
4354
0
            //| movsx Rq(to_reg), Rb(from_reg);
4355
0
            dasm_put(Dst, 4141, (to_reg), (from_reg));
4356
0
#line 218 "src/jit/x64/tiles.dasc"
4357
0
            break;
4358
3.91k
        case 66:
4359
3.91k
            //| movsx Rq(to_reg), Rw(from_reg);
4360
3.91k
            dasm_put(Dst, 4151, (to_reg), (from_reg));
4361
3.91k
#line 221 "src/jit/x64/tiles.dasc"
4362
3.91k
            break;
4363
0
        case 68:
4364
0
            /* movsx is apparantly not defined for double-to-quadword conversions,
4365
0
             * which forces us to use the rax register like it's 1978. It might be easier
4366
0
             * to bithack the sign-extension manually, but I'm not sure how.. */
4367
0
            //| mov eax, Rd(from_reg);
4368
0
            //| cdqe;
4369
0
            //| mov Rq(to_reg), rax;
4370
0
            dasm_put(Dst, 4161, (from_reg), (to_reg));
4371
0
#line 229 "src/jit/x64/tiles.dasc"
4372
0
            break;
4373
0
        default:
4374
0
            MVM_oops(tc, "Unsupported signed cast %d -> %d\n", from_size, to_size);
4375
3.91k
        }
4376
0
    } else {
4377
0
        switch (size_conv) {
4378
0
        case 17:
4379
0
            //| movzx Rw(to_reg), Rb(from_reg);
4380
0
            dasm_put(Dst, 4175, (to_reg), (from_reg));
4381
0
#line 237 "src/jit/x64/tiles.dasc"
4382
0
            break;
4383
0
        case 33:
4384
0
            //| movzx Rd(to_reg), Rb(from_reg);
4385
0
            dasm_put(Dst, 4176, (to_reg), (from_reg));
4386
0
#line 240 "src/jit/x64/tiles.dasc"
4387
0
            break;
4388
0
        case 34:
4389
0
            //| movzx Rd(to_reg), Rw(from_reg);
4390
0
            dasm_put(Dst, 4186, (to_reg), (from_reg));
4391
0
#line 243 "src/jit/x64/tiles.dasc"
4392
0
            break;
4393
0
        case 65:
4394
0
            //| movzx Rq(to_reg), Rb(from_reg);
4395
0
            dasm_put(Dst, 4195, (to_reg), (from_reg));
4396
0
#line 246 "src/jit/x64/tiles.dasc"
4397
0
            break;
4398
0
        case 66:
4399
0
            //| movzx Rq(to_reg), Rw(from_reg);
4400
0
            dasm_put(Dst, 4205, (to_reg), (from_reg));
4401
0
#line 249 "src/jit/x64/tiles.dasc"
4402
0
            break;
4403
0
        case 68:
4404
0
            /* In contrast, nothing special is necessary to cast unsigned
4405
0
             * doublewords to quadwords, because using the lower 4 bytes
4406
0
             * automatically clears the upper 4 */
4407
0
            //| mov Rd(to_reg), Rd(from_reg);
4408
0
            dasm_put(Dst, 4215, (from_reg), (to_reg));
4409
0
#line 255 "src/jit/x64/tiles.dasc"
4410
0
            break;
4411
0
        default:
4412
0
            MVM_oops(tc, "Unsupported unsigned cast %d -> %d\n", from_size, to_size);
4413
0
        }
4414
0
    }
4415
3.91k
}
4416
4417
4418
0
MVM_JIT_TILE_DECL(cast_load_addr) {
4419
0
    MVM_oops(tc, "NYI");
4420
0
}
4421
4422
/* binary operations have special requirements because x86 is two-operand form, e.g:
4423
 * r0 = r0 <op> r1
4424
 * whereas the JIT uses a three-operand model:
4425
 * r0 = r1 <op> r2 */
4426
4427
8.61k
static void ensure_two_operand_pre(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitTile *tile, MVMint8 reg[2]) {
4428
8.61k
    MVMint8 out = tile->values[0], in1 = tile->values[1], in2 = tile->values[2];
4429
8.61k
    if (out == in1) {
4430
0
        reg[0] = in1;
4431
0
        reg[1] = in2;
4432
8.61k
    } else if (out == in2) {
4433
0
        if (MVM_jit_expr_op_is_binary_noncommutative(tc, tile->op)) {
4434
0
            //| mov rax, Rq(in1);
4435
0
            dasm_put(Dst, 4223, (in1));
4436
0
#line 280 "src/jit/x64/tiles.dasc"
4437
0
            reg[0] = MVM_JIT_ARCH_X64_RAX;
4438
0
            reg[1] = in2;
4439
0
        } else {
4440
0
            /* in this case, r2 <op> r1 == r0 <op> r1 */
4441
0
            reg[0] = out;
4442
0
            reg[1] = in1;
4443
0
        }
4444
8.61k
    } else {
4445
8.61k
        /* insert a copy */
4446
8.61k
        //| mov Rq(out), Rq(in1);
4447
8.61k
        dasm_put(Dst, 3975, (in1), (out));
4448
8.61k
#line 290 "src/jit/x64/tiles.dasc"
4449
8.61k
        /* use r0, r2 */
4450
8.61k
        reg[0] = out;
4451
8.61k
        reg[1] = in2;
4452
8.61k
    }
4453
8.61k
}
4454
4455
8.61k
static void ensure_two_operand_post(MVMThreadContext *tc, MVMJitCompiler *compiler, MVMJitTile *tile, MVMint8 reg[2]) {
4456
8.61k
    MVMint8 out = tile->values[0];
4457
8.61k
    if (out != reg[0]) {
4458
0
        /* insert a copy afterwards */
4459
0
        //| mov Rq(out), Rq(reg[0]);
4460
0
        dasm_put(Dst, 3975, (reg[0]), (out));
4461
0
#line 301 "src/jit/x64/tiles.dasc"
4462
0
    }
4463
8.61k
}
4464
4465
4466
2.09k
MVM_JIT_TILE_DECL(add_reg) {
4467
2.09k
    MVMint8 reg[2];
4468
2.09k
    ensure_two_operand_pre(tc, compiler, tile, reg);
4469
2.09k
    //| add Rq(reg[0]), Rq(reg[1]);
4470
2.09k
    dasm_put(Dst, 4230, (reg[1]), (reg[0]));
4471
2.09k
#line 309 "src/jit/x64/tiles.dasc"
4472
2.09k
    ensure_two_operand_post(tc, compiler, tile, reg);
4473
2.09k
}
4474
4475
38.7k
MVM_JIT_TILE_DECL(add_const) {
4476
38.7k
    MVMint8 out = tile->values[0];
4477
38.7k
    MVMint8 in1  = tile->values[1];
4478
38.7k
    MVMint64 val = tile->args[0];
4479
38.7k
    MVMint32 sz  = tile->args[1];
4480
38.7k
    if (out == in1) {
4481
2
        if (sz == 8 && !fits_in_32_bit(val)) {
4482
0
            //| mov64 rax, val;
4483
0
            //| add Rq(out), rax;
4484
0
            dasm_put(Dst, 4239, (unsigned int)(val), (unsigned int)((val)>>32), (out));
4485
0
#line 321 "src/jit/x64/tiles.dasc"
4486
2
        } else {
4487
2
            //| add Rq(in1), val;
4488
2
            dasm_put(Dst, 4250, (in1), val);
4489
2
#line 323 "src/jit/x64/tiles.dasc"
4490
2
        }
4491
38.7k
    } else {
4492
38.7k
        if (sz == 8 && !fits_in_32_bit(val)) {
4493
0
            //| mov64 Rq(out), val;
4494
0
            //| add Rq(out), Rq(in1);
4495
0
            dasm_put(Dst, 4258, (out), (unsigned int)(val), (unsigned int)((val)>>32), (in1), (out));
4496
0
#line 328 "src/jit/x64/tiles.dasc"
4497
38.7k
        } else {
4498
38.7k
            //| mov Rq(out), Rq(in1);
4499
38.7k
            //| add Rq(out), val;
4500
38.7k
            dasm_put(Dst, 4274, (in1), (out), (out), val);
4501
38.7k
#line 331 "src/jit/x64/tiles.dasc"
4502
38.7k
        }
4503
38.7k
    }
4504
38.7k
}
4505
4506
815
MVM_JIT_TILE_DECL(add_load_addr) {
4507
815
    MVMint8 out   = tile->values[0];
4508
815
    MVMint8 in1   = tile->values[1];
4509
815
    MVMint8 base  = tile->values[2];
4510
815
    MVMint32 ofs  = tile->args[0];
4511
815
    MVMint32 size = tile->args[1];
4512
815
    if (in1 != out) {
4513
815
        //| mov Rq(out), Rq(in1);
4514
815
        dasm_put(Dst, 3975, (in1), (out));
4515
815
#line 343 "src/jit/x64/tiles.dasc"
4516
815
    }
4517
815
    switch (size) {
4518
0
    case 1:
4519
0
        //| add Rb(out), byte [Rq(base)+ofs];
4520
0
        dasm_put(Dst, 4290, (out), (base), ofs);
4521
0
#line 347 "src/jit/x64/tiles.dasc"
4522
0
        break;
4523
0
    case 2:
4524
0
        //| add Rw(out), word [Rq(base)+ofs];
4525
0
        dasm_put(Dst, 4301, (out), (base), ofs);
4526
0
#line 350 "src/jit/x64/tiles.dasc"
4527
0
        break;
4528
0
    case 4:
4529
0
        //| add Rd(out), dword [Rq(base)+ofs];
4530
0
        dasm_put(Dst, 4302, (out), (base), ofs);
4531
0
#line 353 "src/jit/x64/tiles.dasc"
4532
0
        break;
4533
815
    case 8:
4534
815
        //| add Rq(out), qword [Rq(base)+ofs];
4535
815
        dasm_put(Dst, 4312, (out), (base), ofs);
4536
815
#line 356 "src/jit/x64/tiles.dasc"
4537
815
        break;
4538
0
    default:
4539
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4540
815
    }
4541
815
}
4542
4543
0
MVM_JIT_TILE_DECL(add_load_idx) {
4544
0
    MVMint8 out  = tile->values[0];
4545
0
    MVMint8 in1  = tile->values[1];
4546
0
    MVMint8 base = tile->values[2];
4547
0
    MVMint8 idx  = tile->values[3];
4548
0
    MVMint32 scl  = tile->args[0];
4549
0
    MVMint32 size = tile->args[1];
4550
0
    if (in1 != out) {
4551
0
        //| mov Rq(out), Rq(in1);
4552
0
        dasm_put(Dst, 3975, (in1), (out));
4553
0
#line 371 "src/jit/x64/tiles.dasc"
4554
0
    }
4555
0
    if (scl != 8)
4556
0
        MVM_oops(tc, "IDX Scale %d NYI\n", scl);
4557
0
    switch (size) {
4558
0
    case 1:
4559
0
        //| add Rb(out), byte [Rq(base)+Rq(idx)*8];
4560
0
        dasm_put(Dst, 4323, (out), (idx), (base), 0);
4561
0
#line 377 "src/jit/x64/tiles.dasc"
4562
0
        break;
4563
0
    case 2:
4564
0
        //| add Rw(out), word [Rq(base)+Rq(idx)*8];
4565
0
        dasm_put(Dst, 4337, (out), (idx), (base), 0);
4566
0
#line 380 "src/jit/x64/tiles.dasc"
4567
0
        break;
4568
0
    case 4:
4569
0
        //| add Rd(out), dword [Rq(base)+Rq(idx)*8];
4570
0
        dasm_put(Dst, 4338, (out), (idx), (base), 0);
4571
0
#line 383 "src/jit/x64/tiles.dasc"
4572
0
        break;
4573
0
    case 8:
4574
0
        //| add Rq(out), qword [Rq(base)+Rq(idx)*8];
4575
0
        dasm_put(Dst, 4351, (out), (idx), (base), 0);
4576
0
#line 386 "src/jit/x64/tiles.dasc"
4577
0
        break;
4578
0
    default:
4579
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4580
0
    }
4581
0
}
4582
4583
4584
0
MVM_JIT_TILE_DECL(and_reg) {
4585
0
    MVMint8 reg[2];
4586
0
    ensure_two_operand_pre(tc, compiler, tile, reg);
4587
0
    //| and Rq(reg[0]), Rq(reg[1]);
4588
0
    dasm_put(Dst, 4365, (reg[1]), (reg[0]));
4589
0
#line 397 "src/jit/x64/tiles.dasc"
4590
0
    ensure_two_operand_post(tc, compiler, tile, reg);
4591
0
}
4592
4593
0
MVM_JIT_TILE_DECL(and_const) {
4594
0
    MVMint8 out = tile->values[0];
4595
0
    MVMint8 in1  = tile->values[1];
4596
0
    MVMint64 val = tile->args[0];
4597
0
    MVMint32 sz  = tile->args[1];
4598
0
    if (out == in1) {
4599
0
        if (sz == 8 && !fits_in_32_bit(val)) {
4600
0
            //| mov64 rax, val;
4601
0
            //| and Rq(in1), rax;
4602
0
            dasm_put(Dst, 4374, (unsigned int)(val), (unsigned int)((val)>>32), (in1));
4603
0
#line 409 "src/jit/x64/tiles.dasc"
4604
0
        } else {
4605
0
            //| and Rq(in1), val;
4606
0
            dasm_put(Dst, 4385, (in1), val);
4607
0
#line 411 "src/jit/x64/tiles.dasc"
4608
0
        }
4609
0
    } else {
4610
0
        if (sz == 8 && !fits_in_32_bit(val)) {
4611
0
            //| mov64 Rq(out), val;
4612
0
            //| and Rq(out), Rq(in1);
4613
0
            dasm_put(Dst, 4393, (out), (unsigned int)(val), (unsigned int)((val)>>32), (in1), (out));
4614
0
#line 416 "src/jit/x64/tiles.dasc"
4615
0
        } else {
4616
0
            //| mov Rq(out), Rq(in1);
4617
0
            //| and Rq(out), val;
4618
0
            dasm_put(Dst, 4409, (in1), (out), (out), val);
4619
0
#line 419 "src/jit/x64/tiles.dasc"
4620
0
        }
4621
0
    }
4622
0
}
4623
4624
0
MVM_JIT_TILE_DECL(and_load_addr) {
4625
0
    MVMint8 out   = tile->values[0];
4626
0
    MVMint8 in1   = tile->values[1];
4627
0
    MVMint8 base  = tile->values[2];
4628
0
    MVMint32 ofs  = tile->args[0];
4629
0
    MVMint32 size = tile->args[1];
4630
0
    if (in1 != out) {
4631
0
        //| mov Rq(out), Rq(in1);
4632
0
        dasm_put(Dst, 3975, (in1), (out));
4633
0
#line 431 "src/jit/x64/tiles.dasc"
4634
0
    }
4635
0
    switch (size) {
4636
0
    case 1:
4637
0
        //| and Rb(out), byte [Rq(base)+ofs];
4638
0
        dasm_put(Dst, 4425, (out), (base), ofs);
4639
0
#line 435 "src/jit/x64/tiles.dasc"
4640
0
        break;
4641
0
    case 2:
4642
0
        //| and Rw(out), word [Rq(base)+ofs];
4643
0
        dasm_put(Dst, 4436, (out), (base), ofs);
4644
0
#line 438 "src/jit/x64/tiles.dasc"
4645
0
        break;
4646
0
    case 4:
4647
0
        //| and Rd(out), dword [Rq(base)+ofs];
4648
0
        dasm_put(Dst, 4437, (out), (base), ofs);
4649
0
#line 441 "src/jit/x64/tiles.dasc"
4650
0
        break;
4651
0
    case 8:
4652
0
        //| and Rq(out), qword [Rq(base)+ofs];
4653
0
        dasm_put(Dst, 4447, (out), (base), ofs);
4654
0
#line 444 "src/jit/x64/tiles.dasc"
4655
0
        break;
4656
0
    default:
4657
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4658
0
    }
4659
0
}
4660
4661
0
MVM_JIT_TILE_DECL(and_load_idx) {
4662
0
    MVMint8 out  = tile->values[0];
4663
0
    MVMint8 in1  = tile->values[1];
4664
0
    MVMint8 base = tile->values[2];
4665
0
    MVMint8 idx  = tile->values[3];
4666
0
    MVMint32 scl  = tile->args[0];
4667
0
    MVMint32 size = tile->args[1];
4668
0
4669
0
    if (out != in1) {
4670
0
        //| mov Rq(out), Rq(in1);
4671
0
        dasm_put(Dst, 3975, (in1), (out));
4672
0
#line 460 "src/jit/x64/tiles.dasc"
4673
0
    }
4674
0
    if (scl != 8)
4675
0
        MVM_oops(tc, "IDX Scale %d NYI\n", scl);
4676
0
    switch (size) {
4677
0
    case 1:
4678
0
        //| and Rb(out), byte [Rq(base)+Rq(idx)*8];
4679
0
        dasm_put(Dst, 4458, (out), (idx), (base), 0);
4680
0
#line 466 "src/jit/x64/tiles.dasc"
4681
0
        break;
4682
0
    case 2:
4683
0
        //| and Rw(out), word [Rq(base)+Rq(idx)*8];
4684
0
        dasm_put(Dst, 4472, (out), (idx), (base), 0);
4685
0
#line 469 "src/jit/x64/tiles.dasc"
4686
0
        break;
4687
0
    case 4:
4688
0
        //| and Rd(out), dword [Rq(base)+Rq(idx)*8];
4689
0
        dasm_put(Dst, 4473, (out), (idx), (base), 0);
4690
0
#line 472 "src/jit/x64/tiles.dasc"
4691
0
        break;
4692
0
    case 8:
4693
0
        //| and Rq(out), qword [Rq(base)+Rq(idx)*8];
4694
0
        dasm_put(Dst, 4486, (out), (idx), (base), 0);
4695
0
#line 475 "src/jit/x64/tiles.dasc"
4696
0
        break;
4697
0
    default:
4698
0
        MVM_oops(tc, "Unsupported load size: %d\n", size);
4699
0
    }
4700
0
}
4701
4702
3.47k
MVM_JIT_TILE_DECL(or_reg) {
4703
3.47k
    MVMint8 reg[2];
4704
3.47k
    ensure_two_operand_pre(tc, compiler, tile, reg);
4705
3.47k
    //| or Rq(reg[0]), Rq(reg[1]);
4706
3.47k
    dasm_put(Dst, 4500, (reg[1]), (reg[0]));
4707
3.47k
#line 485 "src/jit/x64/tiles.dasc"
4708
3.47k
    ensure_two_operand_post(tc, compiler, tile, reg);
4709
3.47k
}
4710
4711
0
MVM_JIT_TILE_DECL(xor_reg) {
4712
0
    MVMint8 reg[2];
4713
0
    ensure_two_operand_pre(tc, compiler, tile, reg);
4714
0
    //| xor Rq(reg[0]), Rq(reg[1]);
4715
0
    dasm_put(Dst, 4509, (reg[1]), (reg[0]));
4716
0
#line 492 "src/jit/x64/tiles.dasc"
4717
0
    ensure_two_operand_post(tc, compiler, tile, reg);
4718
0
}
4719
4720
0
MVM_JIT_TILE_DECL(not_reg) {
4721
0
    MVMint8 out = tile->values[0];
4722
0
    MVMint8 in  = tile->values[1];
4723
0
    if (out != in) {
4724
0
        //| mov Rq(out), Rq(in);
4725
0
        dasm_put(Dst, 3975, (in), (out));
4726
0
#line 500 "src/jit/x64/tiles.dasc"
4727
0
    }
4728
0
    //| not Rq(out);
4729
0
    dasm_put(Dst, 4518, (out));
4730
0
#line 502 "src/jit/x64/tiles.dasc"
4731
0
}
4732
4733
3.04k
MVM_JIT_TILE_DECL(sub_reg) {
4734
3.04k
    MVMint8 reg[2];
4735
3.04k
    ensure_two_operand_pre(tc, compiler, tile, reg);
4736
3.04k
    //| sub Rq(reg[0]), Rq(reg[1]);
4737
3.04k
    dasm_put(Dst, 4526, (reg[1]), (reg[0]));
4738
3.04k
#line 508 "src/jit/x64/tiles.dasc"
4739
3.04k
    ensure_two_operand_post(tc, compiler, tile, reg);
4740
3.04k
}
4741
4742
4.36k
MVM_JIT_TILE_DECL(sub_const) {
4743
4.36k
    MVMint8 out = tile->values[0];
4744
4.36k
    MVMint8 in1  = tile->values[1];
4745
4.36k
    MVMint64 val = tile->args[0];
4746
4.36k
    MVMint32 sz  = tile->args[1];
4747
4.36k
    if (out == in1) {
4748
0
        if (sz == 8 && !fits_in_32_bit(val)) {
4749
0
            //| mov64 rax, val;
4750
0
            //| sub Rq(in1), rax;
4751
0
            dasm_put(Dst, 4535, (unsigned int)(val), (unsigned int)((val)>>32), (in1));
4752
0
#line 520 "src/jit/x64/tiles.dasc"
4753
0
        } else {
4754
0
            //| sub Rq(in1), val;
4755
0
            dasm_put(Dst, 4546, (in1), val);
4756
0
#line 522 "src/jit/x64/tiles.dasc"
4757
0
        }
4758
4.36k
    } else {
4759
4.36k
        if (sz == 8 && !fits_in_32_bit(val)) {
4760
0
            //| mov64 rax, val;
4761
0
            //| mov Rq(out), Rq(in1);
4762
0
            //| sub Rq(out), rax;
4763
0
            dasm_put(Dst, 4555, (unsigned int)(val), (unsigned int)((val)>>32), (in1), (out), (out));
4764
0
#line 528 "src/jit/x64/tiles.dasc"
4765
4.36k
        } else {
4766
4.36k
            //| mov Rq(out), Rq(in1);
4767
4.36k
            //| sub Rq(out), val;
4768
4.36k
            dasm_put(Dst, 4574, (in1), (out), (out), val);
4769
4.36k
#line 531 "src/jit/x64/tiles.dasc"
4770
4.36k
        }
4771
4.36k
    }
4772
4.36k
}
4773
4774
0
MVM_JIT_TILE_DECL(sub_load_addr) {
4775
0
    MVMint8 out   = tile->values[0];