Coverage Report

Created: 2017-09-04 06:32

/home/travis/build/MoarVM/MoarVM/src/jit/emit_posix_x64.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/emit_x64.dasc".
6
*/
7
8
#line 1 "src/jit/emit_x64.dasc"
9
#include "moar.h"
10
#include <dasm_proto.h>
11
#include <dasm_x86.h>
12
#include "emit.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. You are allowed to use in a snippet
64
 * the local labels 1-5; the labels 6-9 are reserved by special constructs like
65
 * THROWISH_PRE and INVOKISH.
66
67
 * WRITE BARRIERS:
68
69
 * Use of write barriers is tricky, because they may involve a function call, and
70
 * that may or may not mean you have to store your temporaries on the stack.
71
 * Hence, a write barrier (MVM_ASSIGN_REF) is split into two parts:
72
73
 * + check_wb (root, value, label)
74
 * + hit_wb (root)
75
76
 * You should have the label parameter point somewhere after hit_wb, and save
77
 * and restore your temporaries around the hib_wb.
78
 **/
79
80
81
//|.arch x64
82
#if DASM_VERSION != 10300
83
#error "Version mismatch between DynASM and included encoding engine"
84
#endif
85
#line 74 "src/jit/emit_x64.dasc"
86
//|.actionlist actions
87
static const unsigned char actions[3526] = {
88
  254,0,85,72,137,229,255,72,129,252,236,0,1,0,0,255,76,137,117,252,248,76,
89
  137,109,252,240,72,137,93,232,255,68,139,159,233,68,137,93,224,255,73,137,
90
  252,254,73,137,252,245,77,139,158,233,73,139,155,233,255,252,255,226,255,
91
  248,10,72,199,192,0,0,0,0,248,11,255,76,139,117,252,248,76,139,109,252,240,
92
  72,139,93,232,255,72,137,252,236,93,195,255,72,185,237,237,72,137,139,233,
93
  255,72,199,131,233,237,255,73,139,141,233,72,139,137,233,72,137,139,233,255,
94
  73,139,142,233,72,139,137,233,72,137,139,233,255,72,139,139,233,72,139,137,
95
  233,255,72,139,137,233,73,139,150,233,72,139,146,233,72,133,201,72,15,68,
96
  202,255,77,139,158,233,255,77,139,155,233,255,77,139,147,233,255,77,139,146,
97
  233,255,77,133,210,15,133,244,247,255,76,137,252,247,76,137,222,72,199,194,
98
  237,254,1,248,5,237,237,254,0,252,255,21,244,5,255,73,137,194,248,1,255,76,
99
  137,147,233,255,76,139,155,233,77,139,155,233,255,76,137,252,247,255,73,139,
100
  181,233,72,139,182,233,72,199,194,237,254,1,252,255,21,244,5,72,133,192,15,
101
  132,244,247,72,139,0,248,1,72,137,131,233,255,73,139,142,233,255,72,139,145,
102
  233,76,139,131,233,76,137,130,233,255,102,252,247,129,233,236,15,132,244,
103
  248,77,133,192,15,132,244,248,102,65,252,247,128,233,236,15,133,244,248,72,
104
  137,206,76,137,252,247,254,1,252,255,21,244,5,248,2,255,73,139,142,233,72,
105
  139,137,233,72,139,137,233,72,137,139,233,255,72,139,139,233,72,141,145,233,
106
  76,139,137,233,77,141,145,233,77,133,201,73,15,69,210,255,76,139,2,77,133,
107
  192,255,15,133,244,249,255,77,139,134,233,77,139,128,233,248,3,255,76,139,
108
  2,255,77,133,192,15,133,244,250,255,77,139,134,233,77,139,128,233,77,139,
109
  128,233,255,102,252,247,129,233,236,15,132,244,249,77,133,192,15,132,244,
110
  249,102,65,252,247,128,233,236,15,133,244,249,72,137,85,216,76,137,69,208,
111
  72,139,179,233,76,137,252,247,254,1,252,255,21,244,5,76,139,69,208,72,139,
112
  85,216,248,3,255,76,137,2,248,4,255,76,139,2,77,133,192,15,133,244,250,255,
113
  76,137,252,247,73,139,182,233,72,139,182,233,72,139,182,233,254,1,252,255,
114
  21,244,5,73,137,192,255,252,255,21,244,5,76,139,69,208,72,139,85,216,248,
115
  3,76,137,2,255,76,137,131,233,255,72,139,139,233,72,139,147,233,255,102,252,
116
  247,129,233,236,15,132,244,248,72,133,210,15,132,244,248,102,252,247,130,
117
  233,236,15,133,244,248,255,252,255,21,244,5,72,139,139,233,72,139,147,233,
118
  248,2,255,72,137,145,233,255,72,139,139,233,72,139,145,233,72,137,147,233,
119
  255,72,139,139,233,72,139,147,233,72,139,137,233,72,137,17,255,72,139,139,
120
  233,76,139,129,233,73,139,16,72,137,147,233,255,72,139,139,233,72,139,147,
121
  233,76,141,129,233,73,131,184,233,0,15,132,244,247,77,139,128,233,248,1,255,
122
  102,252,247,129,233,236,15,132,244,248,72,133,210,15,132,244,248,102,252,
123
  247,130,233,236,15,133,244,248,72,137,85,216,76,137,69,208,72,139,179,233,
124
  76,137,252,247,254,1,252,255,21,244,5,76,139,69,208,72,139,85,216,248,2,255,
125
  73,137,144,233,255,72,139,139,233,72,137,139,233,255,72,139,139,233,73,137,
126
  142,233,255,73,139,142,233,72,131,252,249,0,15,132,244,248,73,139,150,233,
127
  72,131,252,250,0,15,132,244,247,77,139,134,233,77,139,128,233,76,57,194,15,
128
  133,244,248,248,1,72,137,139,233,73,199,134,233,237,252,233,244,249,248,2,
129
  73,139,142,233,72,139,137,233,72,137,139,233,248,3,255,73,139,142,233,72,
130
  139,137,233,72,133,201,15,132,244,247,72,139,137,233,248,1,72,137,139,233,
131
  255,73,139,141,233,255,72,199,131,233,0,0,0,0,255,72,139,139,233,72,133,201,
132
  15,148,210,72,15,182,210,72,137,147,233,255,72,129,131,233,239,255,72,129,
133
  171,233,239,255,72,129,139,233,239,255,72,129,163,233,239,255,72,129,179,
134
  233,239,255,72,139,131,233,255,72,1,131,233,255,72,41,131,233,255,72,9,131,
135
  233,255,72,33,131,233,255,72,49,131,233,255,72,129,192,239,255,72,129,232,
136
  239,255,72,129,200,239,255,72,129,224,239,255,72,129,252,240,239,255,72,3,
137
  131,233,255,72,43,131,233,255,72,11,131,233,255,72,35,131,233,255,72,51,131,
138
  233,255,72,15,175,131,233,255,138,139,233,72,211,224,255,138,139,233,72,211,
139
  232,255,72,139,131,233,72,139,139,233,72,131,252,249,0,15,133,244,247,76,
140
  137,252,247,72,190,237,237,254,1,252,255,21,244,5,248,1,255,15,156,214,72,
141
  131,252,248,0,15,156,210,48,252,242,68,15,182,194,72,153,72,252,247,252,249,
142
  72,133,210,15,149,209,65,32,200,255,76,41,192,72,137,131,233,255,252,255,
143
  21,244,5,248,1,72,153,72,252,247,252,249,72,137,147,233,255,72,131,131,233,
144
  1,255,72,131,171,233,1,255,72,139,139,233,72,252,247,209,72,137,139,233,255,
145
  72,139,139,233,72,252,247,217,72,137,139,233,255,72,139,131,233,72,152,72,
146
  137,131,233,255,72,139,139,233,255,137,202,72,137,147,233,255,252,242,15,
147
  16,131,233,255,252,242,15,88,131,233,255,252,242,15,92,131,233,255,252,242,
148
  15,89,131,233,255,252,242,15,94,131,233,255,252,242,15,17,131,233,255,252,
149
  242,72,15,42,131,233,252,242,15,17,131,233,255,252,242,72,15,44,131,233,72,
150
  137,131,233,255,72,199,193,1,0,0,0,72,193,225,63,72,139,147,233,72,49,202,
151
  72,137,147,233,255,72,59,131,233,255,15,148,208,255,15,149,208,255,15,156,
152
  208,255,15,158,208,255,15,159,208,255,15,157,208,255,72,15,182,192,72,137,
153
  131,233,255,72,59,139,233,255,15,159,210,72,15,182,210,65,15,156,208,77,15,
154
  182,192,76,41,194,72,137,147,233,255,72,199,194,1,0,0,0,255,72,199,194,252,
155
  255,252,255,252,255,252,255,255,72,199,194,0,0,0,0,255,72,59,147,233,255,
156
  72,199,193,0,0,0,0,255,72,199,193,1,0,0,0,255,252,242,15,16,131,233,102,15,
157
  46,131,233,255,15,147,209,255,15,155,210,72,15,68,202,255,15,154,210,72,15,
158
  68,202,255,15,151,209,255,72,15,182,201,72,137,139,233,255,252,242,15,16,
159
  131,233,252,242,15,16,139,233,102,15,46,193,15,151,209,72,15,182,193,102,
160
  15,46,200,15,151,209,72,15,182,201,72,41,200,72,137,131,233,255,72,199,199,
161
  237,72,139,179,233,72,139,147,233,254,1,72,129,252,248,239,15,148,208,255,
162
  72,129,252,248,239,15,149,208,255,72,139,139,233,72,133,201,15,132,244,247,
163
  72,139,137,233,72,139,137,233,72,129,185,233,239,15,133,244,247,72,199,131,
164
  233,1,0,0,0,252,233,244,248,248,1,72,199,131,233,0,0,0,0,248,2,255,72,139,
165
  139,233,72,139,145,233,72,131,194,1,76,139,129,233,255,76,57,194,15,156,209,
166
  72,15,182,201,72,137,139,233,255,72,139,139,233,72,139,145,233,72,133,210,
167
  15,149,210,72,15,182,210,72,137,147,233,255,76,139,155,233,77,133,219,15,
168
  132,244,247,73,139,179,233,76,139,150,233,77,139,146,233,76,137,252,247,65,
169
  252,255,210,76,15,183,152,233,248,1,76,137,155,233,255,76,139,155,233,77,
170
  133,219,15,132,244,247,73,139,179,233,76,139,150,233,77,139,146,233,76,137,
171
  252,247,65,252,255,210,76,15,183,152,233,77,133,219,15,132,244,247,76,15,
172
  183,152,233,248,1,76,137,155,233,255,72,139,139,233,72,133,201,15,149,210,
173
  77,139,134,233,77,139,128,233,76,57,193,65,15,149,208,68,32,194,72,15,182,
174
  210,72,137,147,233,255,72,139,139,233,72,133,201,15,148,210,77,139,134,233,
175
  77,139,128,233,76,57,193,65,15,148,208,68,8,194,72,15,182,210,72,137,147,
176
  233,255,76,137,252,247,72,199,198,237,254,1,252,255,21,244,5,73,139,142,233,
177
  72,139,137,233,72,139,137,233,72,137,136,233,102,199,128,233,236,65,139,142,
178
  233,137,136,233,72,137,131,233,255,76,139,147,233,77,133,210,255,15,132,244,
179
  247,102,65,252,247,130,233,236,255,15,133,244,247,77,139,154,233,77,139,155,
180
  233,77,133,219,255,15,132,244,247,76,137,252,247,76,137,214,72,141,147,233,
181
  77,139,147,233,65,252,255,210,252,233,244,248,248,1,255,76,137,147,233,248,
182
  2,255,72,139,139,233,72,133,201,15,132,244,247,72,139,137,233,72,139,137,
183
  233,72,133,201,248,1,15,149,209,72,15,182,201,72,137,139,233,255,73,139,142,
184
  233,72,139,137,233,72,139,137,233,72,139,147,233,72,139,146,233,72,57,209,
185
  15,133,244,247,77,139,134,233,77,139,128,233,77,139,128,233,76,137,131,233,
186
  252,233,244,248,248,1,255,73,139,134,233,76,141,29,244,248,76,137,152,233,
187
  255,76,137,252,247,72,139,179,233,255,73,139,149,233,72,139,146,233,72,199,
188
  193,237,76,141,155,233,77,137,216,254,1,252,255,21,244,5,72,133,192,255,15,
189
  133,244,11,248,2,255,72,139,139,233,72,133,201,15,132,244,247,102,252,247,
190
  129,233,236,15,133,244,247,72,199,131,233,1,0,0,0,252,233,244,248,248,1,72,
191
  199,131,233,0,0,0,0,248,2,255,73,139,142,233,72,137,139,233,73,199,134,233,
192
  0,0,0,0,255,73,139,142,233,72,133,201,15,132,244,247,72,139,137,233,72,137,
193
  139,233,252,233,244,248,248,1,73,139,142,233,72,139,137,233,72,137,139,233,
194
  248,2,255,65,139,142,233,131,193,1,65,137,142,233,72,137,139,233,255,65,139,
195
  142,233,131,252,233,1,65,137,142,233,72,137,139,233,255,72,139,179,233,76,
196
  139,150,233,77,139,146,233,77,133,210,15,133,244,247,76,137,252,247,72,190,
197
  237,237,254,1,252,255,21,244,5,248,1,76,137,252,247,72,139,147,233,255,65,
198
  252,255,210,255,76,137,252,247,72,139,179,233,72,199,194,237,254,1,73,139,
199
  182,233,72,141,182,233,102,68,139,150,233,102,68,59,150,233,15,132,244,247,
200
  76,137,252,247,254,1,72,139,139,233,72,133,201,15,133,244,247,76,137,252,
201
  247,254,1,76,137,252,247,73,139,182,233,72,139,182,233,72,199,194,237,254,
202
  1,76,137,252,247,73,139,182,233,72,139,182,233,72,139,182,233,72,199,194,
203
  237,254,1,72,139,139,233,139,145,233,77,49,192,131,252,250,0,15,142,244,247,
204
  77,139,134,233,77,139,128,233,77,139,4,208,77,139,128,233,248,1,76,137,131,
205
  233,255,102,252,247,129,233,236,15,133,244,247,72,139,145,233,72,139,146,
206
  233,129,186,233,239,15,132,244,248,248,1,255,76,137,252,247,72,139,179,233,
207
  72,49,210,254,1,72,137,198,255,72,141,187,233,77,139,158,233,73,137,187,233,
208
  255,65,198,131,233,235,255,73,139,190,233,72,139,63,73,137,187,233,255,76,
209
  137,252,247,72,139,147,233,72,139,138,233,72,139,145,233,72,139,137,233,76,
210
  139,150,233,77,139,146,233,65,252,255,210,255,252,255,21,244,5,248,2,72,139,
211
  145,233,72,15,183,146,233,72,137,147,233,255,252,255,21,244,5,248,2,72,139,
212
  145,233,102,68,139,130,233,102,139,146,233,102,68,57,194,15,149,208,72,15,
213
  182,192,72,137,131,233,255,77,139,134,233,255,252,255,21,244,5,72,137,131,
214
  233,255,72,139,145,233,72,139,146,233,129,186,233,239,15,132,244,247,255,
215
  252,255,21,244,5,248,1,72,139,147,233,72,137,145,233,255,77,139,134,233,76,
216
  137,131,233,255,76,137,252,247,72,139,183,233,72,141,182,233,72,199,194,237,
217
  254,1,76,137,252,247,72,139,183,233,72,141,182,233,254,1,76,137,252,247,72,
218
  139,179,233,72,139,147,233,72,139,139,233,76,141,131,233,76,139,150,233,77,
219
  139,146,233,77,139,146,233,65,252,255,210,255,76,137,252,247,72,139,179,233,
220
  76,139,150,233,77,139,146,233,77,139,146,233,65,252,255,210,72,137,131,233,
221
  255,76,137,252,247,72,139,179,233,72,139,147,233,76,139,150,233,77,139,146,
222
  233,77,139,146,233,65,252,255,210,255,77,137,252,243,255,77,137,252,235,255,
223
  77,139,158,233,77,141,155,233,255,77,139,158,233,77,139,155,233,255,76,139,
224
  155,233,255,76,141,155,233,255,77,139,157,233,77,139,155,233,255,73,199,195,
225
  237,255,73,187,237,237,255,76,139,155,233,77,141,155,233,255,76,141,29,245,
226
  255,76,137,223,255,76,137,222,255,76,137,218,255,76,137,217,255,77,137,216,
227
  255,77,137,217,255,102,73,15,110,195,255,102,73,15,110,203,255,102,73,15,
228
  110,211,255,102,73,15,110,219,255,102,73,15,110,227,255,102,73,15,110,252,
229
  235,255,102,73,15,110,252,243,255,102,73,15,110,252,251,255,68,136,156,253,
230
  36,233,255,102,68,137,156,253,36,233,255,76,137,156,253,36,233,255,72,139,
231
  8,72,137,139,233,255,72,139,139,233,72,137,8,255,73,131,190,233,0,15,132,
232
  244,247,76,137,252,247,254,1,252,233,244,10,255,252,233,245,255,72,139,131,
233
  233,72,133,192,15,133,245,255,72,139,131,233,72,133,192,15,132,245,255,102,
234
  72,15,110,131,233,102,15,87,201,102,15,46,193,15,138,245,15,133,245,255,102,
235
  72,15,110,131,233,102,15,87,201,102,15,46,193,15,138,244,247,15,133,244,247,
236
  252,233,245,248,1,255,76,137,252,247,72,139,179,233,254,1,72,139,139,233,
237
  72,133,201,15,132,244,247,73,139,150,233,72,139,146,233,72,57,209,15,132,
238
  244,247,252,233,245,248,1,255,76,137,252,247,72,139,179,233,72,139,147,233,
239
  255,73,139,141,233,72,139,137,233,254,1,72,131,252,248,252,255,255,15,142,
240
  245,255,72,139,139,233,73,139,150,233,72,139,146,233,72,139,146,233,255,72,
241
  133,201,15,132,244,247,255,72,59,145,233,15,133,244,247,255,102,252,247,129,
242
  233,236,255,102,252,247,129,233,236,15,133,244,247,255,76,139,129,233,77,
243
  139,128,233,73,129,184,233,239,15,133,244,247,72,59,145,233,15,133,244,247,
244
  255,76,137,252,247,72,199,198,237,72,199,194,237,254,1,72,199,192,237,252,
245
  233,244,11,248,2,255,77,139,150,233,77,137,154,233,255,65,198,130,233,235,
246
  255,73,199,130,233,237,255,72,141,147,233,73,137,146,233,255,73,139,150,233,
247
  72,139,18,73,137,146,233,255,72,141,21,245,73,137,146,233,255,76,139,139,
248
  233,77,137,138,233,255,73,185,237,237,77,137,138,233,255,77,139,141,233,77,
249
  139,137,233,77,137,138,233,255,76,137,85,216,76,137,93,208,255,76,137,252,
250
  247,72,139,179,233,72,141,85,208,76,137,209,73,199,192,0,0,0,0,254,1,76,139,
251
  93,208,76,139,85,216,255,76,137,252,247,72,137,198,76,137,218,76,137,209,
252
  255,76,139,144,233,77,139,146,233,65,252,255,210,255,76,137,252,247,72,139,
253
  179,233,76,137,218,72,199,193,237,254,1,72,199,192,1,0,0,0,252,233,244,11,
254
  255,72,139,139,233,72,131,252,249,0,15,140,244,248,72,129,252,249,239,15,
255
  141,244,248,72,107,201,8,72,141,21,244,247,72,1,202,252,255,226,250,7,248,
256
  1,255,249,252,233,245,250,7,255,65,139,134,233,59,69,224,15,132,244,255,72,
257
  199,192,1,0,0,0,252,233,244,11,248,9,255,72,141,13,244,247,73,139,150,233,
258
  72,137,138,233,248,1,255,72,141,13,244,255,73,139,150,233,72,137,138,233,
259
  255,65,139,142,233,59,77,224,15,133,244,254,255,73,139,142,233,252,255,161,
260
  233,255,248,8,72,199,192,1,0,0,0,252,233,244,11,255,205,3,255
261
};
262
263
#line 75 "src/jit/emit_x64.dasc"
264
//|.section code, data
265
#define DASM_SECTION_CODE 0
266
#define DASM_SECTION_DATA 1
267
#define DASM_MAXSECTION   2
268
#line 76 "src/jit/emit_x64.dasc"
269
//|.globals MVM_JIT_LABEL_
270
enum {
271
  MVM_JIT_LABEL_exit,
272
  MVM_JIT_LABEL_out,
273
  MVM_JIT_LABEL__MAX
274
};
275
#line 77 "src/jit/emit_x64.dasc"
276
277
/* type declarations */
278
//|.type REGISTER, MVMRegister
279
66.8k
#define Dt1(_V) (int)(ptrdiff_t)&(((MVMRegister *)0)_V)
280
#line 80 "src/jit/emit_x64.dasc"
281
//|.type FRAME, MVMFrame
282
607k
#define Dt2(_V) (int)(ptrdiff_t)&(((MVMFrame *)0)_V)
283
#line 81 "src/jit/emit_x64.dasc"
284
//|.type ARGCTX, MVMArgProcContext
285
260
#define Dt3(_V) (int)(ptrdiff_t)&(((MVMArgProcContext *)0)_V)
286
#line 82 "src/jit/emit_x64.dasc"
287
//|.type CALLSITEPTR, MVMCallsite*
288
16.7k
#define Dt4(_V) (int)(ptrdiff_t)&(((MVMCallsite* *)0)_V)
289
#line 83 "src/jit/emit_x64.dasc"
290
//|.type CAPTURE, MVMCallCapture
291
0
#define Dt5(_V) (int)(ptrdiff_t)&(((MVMCallCapture *)0)_V)
292
#line 84 "src/jit/emit_x64.dasc"
293
//|.type CAPTUREBODY, MVMCallCaptureBody
294
#define Dt6(_V) (int)(ptrdiff_t)&(((MVMCallCaptureBody *)0)_V)
295
#line 85 "src/jit/emit_x64.dasc"
296
//|.type ARGPROCCONTEXT, MVMArgProcContext
297
0
#define Dt7(_V) (int)(ptrdiff_t)&(((MVMArgProcContext *)0)_V)
298
#line 86 "src/jit/emit_x64.dasc"
299
//|.type STATICFRAME, MVMStaticFrame
300
#define Dt8(_V) (int)(ptrdiff_t)&(((MVMStaticFrame *)0)_V)
301
#line 87 "src/jit/emit_x64.dasc"
302
//|.type P6OPAQUE, MVMP6opaque
303
39.9k
#define Dt9(_V) (int)(ptrdiff_t)&(((MVMP6opaque *)0)_V)
304
#line 88 "src/jit/emit_x64.dasc"
305
//|.type P6OBODY, MVMP6opaqueBody
306
28.9k
#define DtA(_V) (int)(ptrdiff_t)&(((MVMP6opaqueBody *)0)_V)
307
#line 89 "src/jit/emit_x64.dasc"
308
//|.type MVMITER, MVMIter
309
0
#define DtB(_V) (int)(ptrdiff_t)&(((MVMIter *)0)_V)
310
#line 90 "src/jit/emit_x64.dasc"
311
//|.type MVMINSTANCE, MVMInstance
312
38.2k
#define DtC(_V) (int)(ptrdiff_t)&(((MVMInstance *)0)_V)
313
#line 91 "src/jit/emit_x64.dasc"
314
//|.type MVMACTIVEHANDLERS, MVMActiveHandler
315
0
#define DtD(_V) (int)(ptrdiff_t)&(((MVMActiveHandler *)0)_V)
316
#line 92 "src/jit/emit_x64.dasc"
317
//|.type OBJECT, MVMObject
318
175k
#define DtE(_V) (int)(ptrdiff_t)&(((MVMObject *)0)_V)
319
#line 93 "src/jit/emit_x64.dasc"
320
//|.type STOOGE, MVMObjectStooge
321
33.8k
#define DtF(_V) (int)(ptrdiff_t)&(((MVMObjectStooge *)0)_V)
322
#line 94 "src/jit/emit_x64.dasc"
323
//|.type COLLECTABLE, MVMCollectable
324
53.1k
#define Dt10(_V) (int)(ptrdiff_t)&(((MVMCollectable *)0)_V)
325
#line 95 "src/jit/emit_x64.dasc"
326
//|.type STABLE, MVMSTable
327
46.9k
#define Dt11(_V) (int)(ptrdiff_t)&(((MVMSTable *)0)_V)
328
#line 96 "src/jit/emit_x64.dasc"
329
//|.type REPR, MVMREPROps
330
5.74k
#define Dt12(_V) (int)(ptrdiff_t)&(((MVMREPROps *)0)_V)
331
#line 97 "src/jit/emit_x64.dasc"
332
//|.type STRING, MVMString*
333
16.9k
#define Dt13(_V) (int)(ptrdiff_t)&(((MVMString* *)0)_V)
334
#line 98 "src/jit/emit_x64.dasc"
335
//|.type OBJECTPTR, MVMObject*
336
103k
#define Dt14(_V) (int)(ptrdiff_t)&(((MVMObject* *)0)_V)
337
#line 99 "src/jit/emit_x64.dasc"
338
//|.type CONTAINERSPEC, MVMContainerSpec
339
28.3k
#define Dt15(_V) (int)(ptrdiff_t)&(((MVMContainerSpec *)0)_V)
340
#line 100 "src/jit/emit_x64.dasc"
341
//|.type STORAGESPEC, MVMStorageSpec
342
0
#define Dt16(_V) (int)(ptrdiff_t)&(((MVMStorageSpec *)0)_V)
343
#line 101 "src/jit/emit_x64.dasc"
344
//|.type HLLCONFIG, MVMHLLConfig;
345
6.08k
#define Dt17(_V) (int)(ptrdiff_t)&(((MVMHLLConfig *)0)_V)
346
#line 102 "src/jit/emit_x64.dasc"
347
//|.type SCREFBODY, MVMSerializationContextBody
348
5
#define Dt18(_V) (int)(ptrdiff_t)&(((MVMSerializationContextBody *)0)_V)
349
#line 103 "src/jit/emit_x64.dasc"
350
//|.type NFGSYNTH, MVMNFGSynthetic
351
#define Dt19(_V) (int)(ptrdiff_t)&(((MVMNFGSynthetic *)0)_V)
352
#line 104 "src/jit/emit_x64.dasc"
353
//|.type CODE, MVMCode
354
5.43k
#define Dt1A(_V) (int)(ptrdiff_t)&(((MVMCode *)0)_V)
355
#line 105 "src/jit/emit_x64.dasc"
356
//|.type U8, MVMuint8
357
#define Dt1B(_V) (int)(ptrdiff_t)&(((MVMuint8 *)0)_V)
358
#line 106 "src/jit/emit_x64.dasc"
359
//|.type U16, MVMuint16
360
#define Dt1C(_V) (int)(ptrdiff_t)&(((MVMuint16 *)0)_V)
361
#line 107 "src/jit/emit_x64.dasc"
362
//|.type U32, MVMuint32
363
#define Dt1D(_V) (int)(ptrdiff_t)&(((MVMuint32 *)0)_V)
364
#line 108 "src/jit/emit_x64.dasc"
365
//|.type U64, MVMuint64
366
#define Dt1E(_V) (int)(ptrdiff_t)&(((MVMuint64 *)0)_V)
367
#line 109 "src/jit/emit_x64.dasc"
368
369
370
/* Static allocation of relevant types to registers. I pick
371
 * callee-save registers for efficiency. It is likely we'll be calling
372
 * quite a C functions, and this saves us the trouble of storing
373
 * them. Moreover, C compilers preferentially do not use callee-saved
374
 * registers, and so in most cases, these won't be touched at all. */
375
//|.type TC, MVMThreadContext, r14
376
743k
#define Dt1F(_V) (int)(ptrdiff_t)&(((MVMThreadContext *)0)_V)
377
#line 117 "src/jit/emit_x64.dasc"
378
/* Alternative base pointer. I'll be using this often, so picking rbx
379
 * here rather than the extended registers will lead to smaller
380
 * bytecode */
381
//|.type WORK, MVMRegister, rbx
382
1.28M
#define Dt20(_V) (int)(ptrdiff_t)&(((MVMRegister *)0)_V)
383
#line 121 "src/jit/emit_x64.dasc"
384
//|.type CU, MVMCompUnit, r13
385
40.1k
#define Dt21(_V) (int)(ptrdiff_t)&(((MVMCompUnit *)0)_V)
386
#line 122 "src/jit/emit_x64.dasc"
387
388
389
390
391
12.5k
const MVMint32 MVM_jit_support(void) {
392
12.5k
#ifdef __i386__
393
    /* Usually, this file should only be compiled only on a amd64
394
       platform; but when compiling 'fat' or 'universal' binaries, we
395
       may compile it for other platform. In this case we use the
396
       runtime check to disable the JIT */
397
    return 0;
398
#else
399
12.5k
    return 1;
400
12.5k
#endif
401
12.5k
}
402
403
11.2k
const unsigned char * MVM_jit_actions(void) {
404
11.2k
    return actions;
405
11.2k
}
406
407
11.2k
const unsigned int MVM_jit_num_globals(void) {
408
11.2k
    return MVM_JIT_LABEL__MAX;
409
11.2k
}
410
411
412
/* C Call argument registers */
413
//|.if WIN32
414
//|.define ARG1, rcx
415
//|.define ARG2, rdx
416
//|.define ARG3, r8
417
//|.define ARG4, r9
418
//|.else
419
//|.define ARG1, rdi
420
//|.define ARG2, rsi
421
//|.define ARG3, rdx
422
//|.define ARG4, rcx
423
//|.define ARG5, r8
424
//|.define ARG6, r9
425
//|.endif
426
427
/* C call argument registers for floating point */
428
//|.if WIN32
429
//|.define ARG1F, xmm0
430
//|.define ARG2F, xmm1
431
//|.define ARG3F, xmm2
432
//|.define ARG4F, xmm3
433
//|.else
434
//|.define ARG1F, xmm0
435
//|.define ARG2F, xmm1
436
//|.define ARG3F, xmm2
437
//|.define ARG4F, xmm3
438
//|.define ARG5F, xmm4
439
//|.define ARG6F, xmm5
440
//|.define ARG7F, xmm6
441
//|.define ARG8F, xmm7
442
//|.endif
443
444
/* Special register for the function to be invoked
445
 * (chosen because it isn't involved in argument passing
446
 *  and volatile) */
447
//|.define FUNCTION, r10
448
/* all-purpose temporary registers */
449
//|.define TMP1, rcx
450
//|.define TMP2, rdx
451
//|.define TMP3, r8
452
//|.define TMP4, r9
453
//|.define TMP5, r10
454
//|.define TMP6, r11
455
/* same, but 32 bits wide */
456
//|.define TMP1d, ecx
457
//|.define TMP2d, edx
458
//|.define TMP3d, r8d
459
//|.define TMP4d, r9d
460
//|.define TMP5d, r10d
461
//|.define TMP6d, r11d
462
/* and 16 bits wide */
463
//|.define TMP1w, cx
464
//|.define TMP2w, dx
465
//|.define TMP3w, r8w
466
//|.define TMP4w, r9w
467
//|.define TMP5w, r10w
468
//|.define TMP6w, r11w
469
/* and 8 bits for good measure */
470
//|.define TMP1b, cl
471
//|.define TMP2b, dl
472
//|.define TMP3b, r8b
473
//|.define TMP4b, r9b
474
//|.define TMP5b, r10b
475
//|.define TMP6b, r11b
476
477
478
/* return value */
479
//|.define RV, rax
480
//|.define RVd, eax
481
//|.define RVF, xmm0
482
483
484
//|.macro callp, funcptr
485
//|.data
486
//|5:
487
//|.dword (MVMuint32)((uintptr_t)(funcptr)), (MVMuint32)((uintptr_t)(funcptr) >> 32);
488
//|.code
489
//| call qword [<5];
490
//|.endmacro
491
492
493
//|.macro check_wb, root, ref, lbl;
494
//| test word COLLECTABLE:root->flags, MVM_CF_SECOND_GEN;
495
//| jz lbl;
496
//| test ref, ref;
497
//| jz lbl;
498
//| test word COLLECTABLE:ref->flags, MVM_CF_SECOND_GEN;
499
//| jnz lbl;
500
//|.endmacro;
501
502
//|.macro hit_wb, obj
503
//| mov ARG2, obj;
504
//| mov ARG1, TC;
505
//| callp &MVM_gc_write_barrier_hit;
506
//|.endmacro
507
508
//|.macro get_spesh_slot, reg, idx;
509
//| mov reg, TC->cur_frame;
510
//| mov reg, FRAME:reg->effective_spesh_slots;
511
//| mov reg, OBJECTPTR:reg[idx];
512
//|.endmacro
513
514
//|.macro get_vmnull, reg
515
//| mov reg, TC->instance;
516
//| mov reg, MVMINSTANCE:reg->VMNull;
517
//|.endmacro
518
519
//|.macro get_cur_op, reg
520
//| mov reg, TC->interp_cur_op
521
//| mov reg, [reg]
522
//|.endmacro
523
524
//|.macro get_string, reg, idx
525
//|| MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
526
//| mov reg, CU->body.strings;
527
//| mov reg, STRING:reg[idx];
528
//|.endmacro
529
530
//|.macro is_type_object, reg
531
//| test word OBJECT:reg->header.flags, MVM_CF_TYPE_OBJECT
532
//|.endmacro
533
534
//|.macro gc_sync_point
535
//| cmp qword TC->gc_status, 0;
536
//| je >1;
537
//| mov ARG1, TC;
538
//| callp &MVM_gc_enter_from_interrupt;
539
//|1:
540
//|.endmacro
541
542
//|.macro throw_adhoc, msg
543
//| mov ARG1, TC;
544
//| mov64 ARG2, (uintptr_t)(msg);
545
//| callp &MVM_exception_throw_adhoc;
546
//|.endmacro
547
548
//|.define FRAME_NR, dword [rbp-0x20]
549
550
/* A function prologue is always the same in x86 / x64, because
551
 * we do not provide variable arguments, instead arguments are provided
552
 * via a frame. All JIT entry points receive a prologue. */
553
void MVM_jit_emit_prologue(MVMThreadContext *tc, MVMJitGraph *jg,
554
11.2k
                           dasm_State **Dst) {
555
11.2k
    //|.code
556
11.2k
    dasm_put(Dst, 0);
557
11.2k
#line 291 "src/jit/emit_x64.dasc"
558
11.2k
    /* Setup stack */
559
11.2k
    //| push rbp; // nb, this aligns the stack to 16 bytes again
560
11.2k
    //| mov rbp, rsp;
561
11.2k
    dasm_put(Dst, 2);
562
11.2k
#line 294 "src/jit/emit_x64.dasc"
563
11.2k
    /* allocate stack space: 0x100 bytes = 256 bytes
564
11.2k
     *
565
11.2k
     * layout: [ a: 0x20 | b: 0x40 | c: 0xa0 | d: 0x20 ]
566
11.2k
     * a: space for 4 callee-save registers
567
11.2k
     * b: small scratch space
568
11.2k
     * c: space for stack arguments to c calls
569
11.2k
     * d: reserve space for GPR registers to c calls (win64) or more space for
570
11.2k
     * stack arguments (posix) */
571
11.2k
    //| sub rsp, 0x100;
572
11.2k
    dasm_put(Dst, 7);
573
11.2k
#line 303 "src/jit/emit_x64.dasc"
574
11.2k
    /* save callee-save registers */
575
11.2k
    //| mov [rbp-0x8],  TC;
576
11.2k
    //| mov [rbp-0x10], CU;
577
11.2k
    //| mov [rbp-0x18], WORK;
578
11.2k
    dasm_put(Dst, 16);
579
11.2k
#line 307 "src/jit/emit_x64.dasc"
580
11.2k
    /* store the current frame number for cheap comparisons */
581
11.2k
    //| mov TMP6d, dword TC:ARG1->current_frame_nr;
582
11.2k
    //| mov FRAME_NR, TMP6d;
583
11.2k
    dasm_put(Dst, 31, Dt1F(->current_frame_nr));
584
11.2k
#line 310 "src/jit/emit_x64.dasc"
585
11.2k
    /* setup special frame variables */
586
11.2k
    //| mov TC,   ARG1;
587
11.2k
    //| mov CU,   ARG2;
588
11.2k
    //| mov TMP6, TC->cur_frame;
589
11.2k
    //| mov WORK, FRAME:TMP6->work;
590
11.2k
    dasm_put(Dst, 40, Dt1F(->cur_frame), Dt2(->work));
591
11.2k
#line 315 "src/jit/emit_x64.dasc"
592
11.2k
    /* ARG3 contains our 'entry label' */
593
11.2k
    //| jmp ARG3
594
11.2k
    dasm_put(Dst, 57);
595
11.2k
#line 317 "src/jit/emit_x64.dasc"
596
11.2k
}
597
598
/* And a function epilogue is also always the same */
599
void MVM_jit_emit_epilogue(MVMThreadContext *tc, MVMJitGraph *jg,
600
11.2k
                           dasm_State **Dst) {
601
11.2k
    //| ->exit:
602
11.2k
    //| mov RV, 0;
603
11.2k
    //| ->out:
604
11.2k
    dasm_put(Dst, 61);
605
11.2k
#line 325 "src/jit/emit_x64.dasc"
606
11.2k
    /* restore callee-save registers */
607
11.2k
    //| mov TC, [rbp-0x8];
608
11.2k
    //| mov CU, [rbp-0x10];
609
11.2k
    //| mov WORK, [rbp-0x18];
610
11.2k
    dasm_put(Dst, 73);
611
11.2k
#line 329 "src/jit/emit_x64.dasc"
612
11.2k
    /* Restore stack */
613
11.2k
    //| mov rsp, rbp;
614
11.2k
    //| pop rbp;
615
11.2k
    //| ret;
616
11.2k
    dasm_put(Dst, 88);
617
11.2k
#line 333 "src/jit/emit_x64.dasc"
618
11.2k
}
619
620
static MVMuint64 try_emit_gen2_ref(MVMThreadContext *tc, MVMJitGraph *jg,
621
                                   MVMObject *obj, MVMint16 reg,
622
21.6k
                                   dasm_State **Dst) {
623
21.6k
    if (!(obj->header.flags & MVM_CF_SECOND_GEN))
624
0
        return 0;
625
21.6k
    //| mov64 TMP1, (uintptr_t)obj;
626
21.6k
    //| mov WORK[reg], TMP1;
627
21.6k
    dasm_put(Dst, 95, (unsigned int)((uintptr_t)obj), (unsigned int)(((uintptr_t)obj)>>32), Dt20([reg]));
628
21.6k
#line 342 "src/jit/emit_x64.dasc"
629
21.6k
    return 1;
630
21.6k
}
631
632
4.81k
static MVMint64 fits_in_32_bit(MVMint64 number) {
633
4.81k
    /* Used to determine if a 64 bit integer can be safely used as a
634
4.81k
     * 32 bit constant for immediate mode access */
635
4.81k
    return (number >= INT32_MIN) && (number <= INT32_MAX);
636
4.81k
}
637
638
/* compile per instruction, can't really do any better yet */
639
void MVM_jit_emit_primitive(MVMThreadContext *tc, MVMJitGraph *jg,
640
413k
                            MVMJitPrimitive * prim, dasm_State **Dst) {
641
413k
    MVMSpeshIns *ins = prim->ins;
642
413k
    MVMuint16 op = ins->info->opcode;
643
413k
    MVM_jit_log(tc, "emit opcode: <%s>\n", ins->info->name);
644
413k
    /* Quite a few of these opcodes are copies. Ultimately, I want to
645
413k
     * move copies to their own node (MVMJitCopy or such), and reduce
646
413k
     * the number of copies (and thereby increase the efficiency), but
647
413k
     * currently that isn't really feasible. */
648
413k
    switch (op) {
649
22.8k
    case MVM_OP_const_i64_16:
650
22.8k
    case MVM_OP_const_i64_32: {
651
22.8k
        MVMint32 reg = ins->operands[0].reg.orig;
652
22.8k
        /* Upgrade to 64 bit */
653
22.8k
        MVMint64 val = (op == MVM_OP_const_i64_16 ? (MVMint64)ins->operands[1].lit_i16 :
654
1
                        (MVMint64)ins->operands[1].lit_i32);
655
22.8k
        //| mov qword WORK[reg], val;
656
22.8k
        dasm_put(Dst, 104, Dt20([reg]), val);
657
22.8k
#line 369 "src/jit/emit_x64.dasc"
658
22.8k
        break;
659
22.8k
    }
660
0
    case MVM_OP_const_i64: {
661
0
        MVMint32 reg = ins->operands[0].reg.orig;
662
0
        MVMint64 val = ins->operands[1].lit_i64;
663
0
        //| mov64 TMP1, val;
664
0
        //| mov WORK[reg], TMP1;
665
0
        dasm_put(Dst, 95, (unsigned int)(val), (unsigned int)((val)>>32), Dt20([reg]));
666
0
#line 376 "src/jit/emit_x64.dasc"
667
0
        break;
668
22.8k
    }
669
1.12k
    case MVM_OP_const_n64: {
670
1.12k
        MVMint16 reg = ins->operands[0].reg.orig;
671
1.12k
        MVMint64 valbytes = ins->operands[1].lit_i64;
672
1.12k
        MVM_jit_log(tc, "store const %f\n", ins->operands[1].lit_n64);
673
1.12k
        //| mov64 TMP1, valbytes;
674
1.12k
        //| mov WORK[reg], TMP1;
675
1.12k
        dasm_put(Dst, 95, (unsigned int)(valbytes), (unsigned int)((valbytes)>>32), Dt20([reg]));
676
1.12k
#line 384 "src/jit/emit_x64.dasc"
677
1.12k
        break;
678
22.8k
    }
679
0
    case MVM_OP_inf:
680
0
    case MVM_OP_neginf:
681
0
    case MVM_OP_nan: {
682
0
        MVMint16 reg = ins->operands[0].reg.orig;
683
0
        MVMRegister tmp;
684
0
        if (op == MVM_OP_nan)
685
0
            tmp.n64 = MVM_num_nan(tc);
686
0
        else if (op == MVM_OP_inf)
687
0
            tmp.n64 = MVM_num_posinf(tc);
688
0
        else if (op == MVM_OP_neginf)
689
0
            tmp.n64 = MVM_num_neginf(tc);
690
0
        //| mov64 TMP1, tmp.i64;
691
0
        //| mov WORK[reg], TMP1;
692
0
        dasm_put(Dst, 95, (unsigned int)(tmp.i64), (unsigned int)((tmp.i64)>>32), Dt20([reg]));
693
0
#line 399 "src/jit/emit_x64.dasc"
694
0
        break;
695
0
    }
696
21.6k
    case MVM_OP_const_s: {
697
21.6k
         MVMint16 reg = ins->operands[0].reg.orig;
698
21.6k
         MVMuint32 idx = ins->operands[1].lit_str_idx;
699
21.6k
         MVMStaticFrame *sf = jg->sg->sf;
700
21.6k
         MVMString * s = MVM_cu_string(tc, sf->body.cu, idx);
701
21.6k
         if (!try_emit_gen2_ref(tc, jg, (MVMObject*)s, reg, Dst)) {
702
0
             //| get_string TMP1, idx;
703
0
              MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
704
0
#line 408 "src/jit/emit_x64.dasc"
705
0
             //| mov WORK[reg], TMP1;
706
0
             dasm_put(Dst, 110, Dt21(->body.strings), Dt13([idx]), Dt20([reg]));
707
0
#line 409 "src/jit/emit_x64.dasc"
708
0
         }
709
21.6k
         break;
710
0
    }
711
23.2k
    case MVM_OP_null: {
712
23.2k
        MVMint16 reg = ins->operands[0].reg.orig;
713
23.2k
        //| get_vmnull TMP1;
714
23.2k
        //| mov WORK[reg], TMP1;
715
23.2k
        dasm_put(Dst, 123, Dt1F(->instance), DtC(->VMNull), Dt20([reg]));
716
23.2k
#line 416 "src/jit/emit_x64.dasc"
717
23.2k
        break;
718
0
    }
719
1.60k
    case MVM_OP_getwhat:
720
1.60k
    case MVM_OP_getwho: {
721
1.60k
        MVMint16 dst = ins->operands[0].reg.orig;
722
1.60k
        MVMint16 obj = ins->operands[1].reg.orig;
723
1.60k
        //| mov TMP1, WORK[obj];
724
1.60k
        //| mov TMP1, OBJECT:TMP1->st;
725
1.60k
        dasm_put(Dst, 136, Dt20([obj]), DtE(->st));
726
1.60k
#line 424 "src/jit/emit_x64.dasc"
727
1.60k
        if (op == MVM_OP_getwho) {
728
1.50k
            //| mov TMP1, STABLE:TMP1->WHO;
729
1.50k
            //| get_vmnull TMP2;
730
1.50k
            //| test TMP1, TMP1;
731
1.50k
            //| cmovz TMP1, TMP2;
732
1.50k
            dasm_put(Dst, 145, Dt11(->WHO), Dt1F(->instance), DtC(->VMNull));
733
1.50k
#line 429 "src/jit/emit_x64.dasc"
734
99
        } else {
735
99
            //| mov TMP1, STABLE:TMP1->WHAT;
736
99
            dasm_put(Dst, 140, Dt11(->WHAT));
737
99
#line 431 "src/jit/emit_x64.dasc"
738
99
        }
739
1.60k
        //| mov WORK[dst], TMP1;
740
1.60k
        dasm_put(Dst, 99, Dt20([dst]));
741
1.60k
#line 433 "src/jit/emit_x64.dasc"
742
1.60k
        break;
743
1.60k
    }
744
7.77k
    case MVM_OP_getlex:
745
7.77k
    case MVM_OP_sp_getlex_o:
746
7.77k
    case MVM_OP_sp_getlex_ins: {
747
7.77k
        MVMuint16 *lexical_types;
748
7.77k
        MVMStaticFrame * sf = jg->sg->sf;
749
7.77k
        MVMint16 dst = ins->operands[0].reg.orig;
750
7.77k
        MVMint16 idx = ins->operands[1].lex.idx;
751
7.77k
        MVMint16 out = ins->operands[1].lex.outers;
752
7.77k
        MVMint16 i;
753
7.77k
        //| mov TMP6, TC->cur_frame;
754
7.77k
        dasm_put(Dst, 165, Dt1F(->cur_frame));
755
7.77k
#line 445 "src/jit/emit_x64.dasc"
756
15.5k
        for (i = 0; i < out; i++) {
757
7.80k
            /* I'm going to skip compiling the check whether the outer
758
7.80k
             * node really exists, because if the code has run N times
759
7.80k
             * correctly, then the outer frame must have existed then,
760
7.80k
             * and since this chain is static, it should still exist
761
7.80k
             * now.  If it doesn't exist, that means we crash.
762
7.80k
             *
763
7.80k
             * NB: inlining /might/ make this all wrong! But, if that
764
7.80k
             * happens, the interpreter will panic even without JIT */
765
7.80k
            //| mov TMP6, FRAME:TMP6->outer;
766
7.80k
            dasm_put(Dst, 170, Dt2(->outer));
767
7.80k
#line 455 "src/jit/emit_x64.dasc"
768
7.80k
            sf = sf->body.outer;
769
7.80k
        }
770
7.77k
        /* get array of lexicals */
771
7.77k
        //| mov TMP5, FRAME:TMP6->env;
772
7.77k
        dasm_put(Dst, 175, Dt2(->env));
773
7.77k
#line 459 "src/jit/emit_x64.dasc"
774
7.77k
        /* read value */
775
7.77k
        //| mov TMP5, REGISTER:TMP5[idx];
776
7.77k
        dasm_put(Dst, 180, Dt1([idx]));
777
7.77k
#line 461 "src/jit/emit_x64.dasc"
778
7.77k
        /* it seems that if at runtime, if the outer frame has been inlined,
779
7.77k
         * this /could/ be wrong. But if that is so, the interpreted instruction
780
7.77k
         * would also be wrong, because it'd refer to the wrong lexical. */
781
2.56k
        lexical_types = (!out && jg->sg->lexical_types ?
782
2.03k
                         jg->sg->lexical_types :
783
5.74k
                         sf->body.lexical_types);
784
7.77k
        MVM_jit_log(tc, "Lexical type of register: %d\n", lexical_types[idx]);
785
7.77k
        if (lexical_types[idx] == MVM_reg_obj) {
786
5.83k
            MVM_jit_log(tc, "Emit lex vifivy check\n");
787
5.83k
            /* if it is zero, check if we need to auto-vivify */
788
5.83k
            //| test TMP5, TMP5;
789
5.83k
            //| jnz >1;
790
5.83k
            dasm_put(Dst, 185);
791
5.83k
#line 473 "src/jit/emit_x64.dasc"
792
5.83k
            /* setup args */
793
5.83k
            //| mov ARG1, TC;
794
5.83k
            //| mov ARG2, TMP6;
795
5.83k
            //| mov ARG3, idx;
796
5.83k
            //| callp &MVM_frame_vivify_lexical;
797
5.83k
            dasm_put(Dst, 193, idx);
798
5.83k
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical)), (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical) >> 32));
799
5.83k
            dasm_put(Dst, 212);
800
5.83k
#line 478 "src/jit/emit_x64.dasc"
801
5.83k
            /* use return value for the result */
802
5.83k
            //| mov TMP5, RV;
803
5.83k
            //|1:
804
5.83k
            dasm_put(Dst, 218);
805
5.83k
#line 481 "src/jit/emit_x64.dasc"
806
5.83k
        }
807
7.77k
        /* store the value */
808
7.77k
        //| mov WORK[dst], TMP5;
809
7.77k
        dasm_put(Dst, 224, Dt20([dst]));
810
7.77k
#line 484 "src/jit/emit_x64.dasc"
811
7.77k
        break;
812
7.77k
    }
813
401
    case MVM_OP_sp_getlexvia_o:
814
401
    case MVM_OP_sp_getlexvia_ins: {
815
401
        MVMint16 dst = ins->operands[0].reg.orig;
816
401
        MVMint16 idx = ins->operands[1].lit_ui16;
817
401
        MVMint16 out = ins->operands[2].lit_ui16;
818
401
        MVMint16 via = ins->operands[3].reg.orig;
819
401
        MVMint16 i;
820
401
        /* Resolve the frame. */
821
401
        //| mov TMP6, WORK[via];
822
401
        //| mov TMP6, CODE:TMP6->body.outer;
823
401
        dasm_put(Dst, 229, Dt20([via]), Dt1A(->body.outer));
824
401
#line 496 "src/jit/emit_x64.dasc"
825
729
        for (i = 1; i < out; i++) /* From 1 as we are already at outer */
826
401
            //| mov TMP6, FRAME:TMP6->outer;
827
328
            dasm_put(Dst, 170, Dt2(->outer));
828
401
#line 498 "src/jit/emit_x64.dasc"
829
401
        /* get array of lexicals */
830
401
        //| mov TMP5, FRAME:TMP6->env;
831
401
        dasm_put(Dst, 175, Dt2(->env));
832
401
#line 500 "src/jit/emit_x64.dasc"
833
401
        /* read value */
834
401
        //| mov TMP5, REGISTER:TMP5[idx];
835
401
        dasm_put(Dst, 180, Dt1([idx]));
836
401
#line 502 "src/jit/emit_x64.dasc"
837
401
        if (op == MVM_OP_sp_getlexvia_o) {
838
237
            MVM_jit_log(tc, "Emit lex vifivy check for via code-ref lookup\n");
839
237
            /* if it is zero, check if we need to auto-vivify */
840
237
            //| test TMP5, TMP5;
841
237
            //| jnz >1;
842
237
            dasm_put(Dst, 185);
843
237
#line 507 "src/jit/emit_x64.dasc"
844
237
            /* setup args */
845
237
            //| mov ARG1, TC;
846
237
            //| mov ARG2, TMP6;
847
237
            //| mov ARG3, idx;
848
237
            //| callp &MVM_frame_vivify_lexical;
849
237
            dasm_put(Dst, 193, idx);
850
237
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical)), (MVMuint32)((uintptr_t)(&MVM_frame_vivify_lexical) >> 32));
851
237
            dasm_put(Dst, 212);
852
237
#line 512 "src/jit/emit_x64.dasc"
853
237
            /* use return value for the result */
854
237
            //| mov TMP5, RV;
855
237
            //|1:
856
237
            dasm_put(Dst, 218);
857
237
#line 515 "src/jit/emit_x64.dasc"
858
237
        }
859
401
        /* store the value */
860
401
        //| mov WORK[dst], TMP5;
861
401
        dasm_put(Dst, 224, Dt20([dst]));
862
401
#line 518 "src/jit/emit_x64.dasc"
863
401
        break;
864
401
    }
865
70
    case MVM_OP_getlex_no:
866
70
    case MVM_OP_sp_getlex_no: {
867
70
        MVMint16  dst = ins->operands[0].reg.orig;
868
70
        MVMuint32 idx = ins->operands[1].lit_str_idx;
869
70
        //| mov ARG1, TC;
870
70
        //| get_string ARG2, idx;
871
70
        dasm_put(Dst, 238);
872
70
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
873
70
#line 526 "src/jit/emit_x64.dasc"
874
70
        //| mov ARG3, MVM_reg_obj;
875
70
        //| callp &MVM_frame_find_lexical_by_name;
876
70
        dasm_put(Dst, 243, Dt21(->body.strings), Dt13([idx]), MVM_reg_obj);
877
70
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name)), (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name) >> 32));
878
70
#line 528 "src/jit/emit_x64.dasc"
879
70
        //| test RV, RV;
880
70
        //| jz >1;
881
70
        //| mov RV, [RV];
882
70
        //|1:
883
70
        //| mov WORK[dst], RV;
884
70
        dasm_put(Dst, 257, Dt20([dst]));
885
70
#line 533 "src/jit/emit_x64.dasc"
886
70
        break;
887
70
    }
888
1.93k
    case MVM_OP_bindlex: {
889
1.93k
        MVMuint16 *lexical_types;
890
1.93k
        MVMStaticFrame *sf = jg->sg->sf;
891
1.93k
        MVMint16 idx = ins->operands[0].lex.idx;
892
1.93k
        MVMint16 out = ins->operands[0].lex.outers;
893
1.93k
        MVMint16 src = ins->operands[1].reg.orig;
894
1.93k
        MVMint16 i;
895
1.93k
        //| mov TMP1, TC->cur_frame;
896
1.93k
        dasm_put(Dst, 279, Dt1F(->cur_frame));
897
1.93k
#line 543 "src/jit/emit_x64.dasc"
898
2.02k
        for (i = 0; i < out; i++) {
899
83
            //| mov TMP1, FRAME:TMP1->outer;
900
83
            dasm_put(Dst, 140, Dt2(->outer));
901
83
#line 545 "src/jit/emit_x64.dasc"
902
83
            sf = sf->body.outer;
903
83
        }
904
1.85k
        lexical_types = (!out && jg->sg->lexical_types ?
905
1.46k
                         jg->sg->lexical_types :
906
475
                         sf->body.lexical_types);
907
1.93k
        //| mov TMP2, FRAME:TMP1->env;
908
1.93k
        //| mov TMP3, WORK[src];
909
1.93k
        //| mov REGISTER:TMP2[idx], TMP3;
910
1.93k
        dasm_put(Dst, 284, Dt2(->env), Dt20([src]), Dt1([idx]));
911
1.93k
#line 553 "src/jit/emit_x64.dasc"
912
1.93k
        if (lexical_types[idx] == MVM_reg_obj ||
913
1.87k
            lexical_types[idx] == MVM_reg_str) {
914
1.87k
            //| check_wb TMP1, TMP3, >2;
915
1.87k
            //| hit_wb TMP1;
916
1.87k
            dasm_put(Dst, 297, Dt10(->flags), MVM_CF_SECOND_GEN, Dt10(->flags), MVM_CF_SECOND_GEN);
917
1.87k
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
918
1.87k
#line 557 "src/jit/emit_x64.dasc"
919
1.87k
            //|2:
920
1.87k
            dasm_put(Dst, 334);
921
1.87k
#line 558 "src/jit/emit_x64.dasc"
922
1.87k
        }
923
1.93k
        break;
924
70
    }
925
19.6k
    case MVM_OP_sp_getarg_o:
926
19.6k
    case MVM_OP_sp_getarg_n:
927
19.6k
    case MVM_OP_sp_getarg_s:
928
19.6k
    case MVM_OP_sp_getarg_i: {
929
19.6k
        MVMint32 reg = ins->operands[0].reg.orig;
930
19.6k
        MVMuint16 idx = ins->operands[1].callsite_idx;
931
19.6k
        //| mov TMP1, TC->cur_frame;
932
19.6k
        //| mov TMP1, FRAME:TMP1->params.args;
933
19.6k
        //| mov TMP1, REGISTER:TMP1[idx];
934
19.6k
        //| mov WORK[reg], TMP1;
935
19.6k
        dasm_put(Dst, 342, Dt1F(->cur_frame), Dt2(->params.args), Dt1([idx]), Dt20([reg]));
936
19.6k
#line 571 "src/jit/emit_x64.dasc"
937
19.6k
        break;
938
19.6k
    }
939
25.4k
    case MVM_OP_sp_p6oget_i:
940
25.4k
    case MVM_OP_sp_p6oget_n:
941
25.4k
    case MVM_OP_sp_p6oget_s:
942
25.4k
    case MVM_OP_sp_p6oget_o:
943
25.4k
    case MVM_OP_sp_p6ogetvc_o:
944
25.4k
    case MVM_OP_sp_p6ogetvt_o: {
945
25.4k
        MVMint16 dst    = ins->operands[0].reg.orig;
946
25.4k
        MVMint16 obj    = ins->operands[1].reg.orig;
947
25.4k
        MVMint16 offset = ins->operands[2].lit_i16;
948
25.4k
        MVMint16 body   = offsetof(MVMP6opaque, body);
949
25.4k
        /* load address and object */
950
25.4k
        //| mov TMP1, WORK[obj];
951
25.4k
        //| lea TMP2, [TMP1 + (offset + body)];
952
25.4k
        //| mov TMP4, P6OPAQUE:TMP1->body.replaced;
953
25.4k
        //| lea TMP5, [TMP4 + offset];
954
25.4k
        //| test TMP4, TMP4;
955
25.4k
        //| cmovnz TMP2, TMP5;
956
25.4k
        dasm_put(Dst, 359, Dt20([obj]), (offset + body), Dt9(->body.replaced), offset);
957
25.4k
#line 590 "src/jit/emit_x64.dasc"
958
25.4k
        /* TMP2 now contains address of item */
959
25.4k
        if (op == MVM_OP_sp_p6oget_o) {
960
871
            //| mov TMP3, [TMP2];
961
871
            //| test TMP3, TMP3;
962
871
            dasm_put(Dst, 383);
963
871
#line 594 "src/jit/emit_x64.dasc"
964
871
            /* Check if object doesn't point to NULL */
965
871
            //| jnz >3;
966
871
            dasm_put(Dst, 390);
967
871
#line 596 "src/jit/emit_x64.dasc"
968
871
            /* Otherwise load VMNull */
969
871
            //| get_vmnull TMP3;
970
871
            //|3:
971
871
            dasm_put(Dst, 395, Dt1F(->instance), DtC(->VMNull));
972
871
#line 599 "src/jit/emit_x64.dasc"
973
24.5k
        } else if (op == MVM_OP_sp_p6ogetvt_o) {
974
15.4k
            /* vivify as type object */
975
15.4k
            MVMint16 spesh_idx = ins->operands[3].lit_i16;
976
15.4k
            //| mov TMP3, [TMP2];
977
15.4k
            dasm_put(Dst, 406);
978
15.4k
#line 603 "src/jit/emit_x64.dasc"
979
15.4k
            /* check for null */
980
15.4k
            //| test TMP3, TMP3;
981
15.4k
            //| jnz >4;
982
15.4k
            dasm_put(Dst, 410);
983
15.4k
#line 606 "src/jit/emit_x64.dasc"
984
15.4k
            /* if null, vivify as type object from spesh slot */
985
15.4k
            //| get_spesh_slot TMP3, spesh_idx;
986
15.4k
            dasm_put(Dst, 418, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]));
987
15.4k
#line 608 "src/jit/emit_x64.dasc"
988
15.4k
            /* need to hit write barrier? */
989
15.4k
            //| check_wb TMP1, TMP3, >3;
990
15.4k
            //| mov qword [rbp-0x28], TMP2; // address
991
15.4k
            //| mov qword [rbp-0x30], TMP3; // value
992
15.4k
            //| hit_wb WORK[obj]; // write barrier for header
993
15.4k
            dasm_put(Dst, 431, Dt10(->flags), MVM_CF_SECOND_GEN, Dt10(->flags), MVM_CF_SECOND_GEN, Dt20([obj]));
994
15.4k
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
995
15.4k
#line 613 "src/jit/emit_x64.dasc"
996
15.4k
            //| mov TMP3, qword [rbp-0x30];
997
15.4k
            //| mov TMP2, qword [rbp-0x28];
998
15.4k
            //|3:
999
15.4k
            dasm_put(Dst, 477);
1000
15.4k
#line 616 "src/jit/emit_x64.dasc"
1001
15.4k
            /* store vivified type value in memory location */
1002
15.4k
            //| mov qword [TMP2], TMP3;
1003
15.4k
            //|4:
1004
15.4k
            dasm_put(Dst, 493);
1005
15.4k
#line 619 "src/jit/emit_x64.dasc"
1006
9.14k
        } else if (op == MVM_OP_sp_p6ogetvc_o) {
1007
0
            MVMint16 spesh_idx = ins->operands[3].lit_i16;
1008
0
            //| mov TMP3, [TMP2];
1009
0
            //| test TMP3, TMP3;
1010
0
            //| jnz >4;
1011
0
            dasm_put(Dst, 499);
1012
0
#line 624 "src/jit/emit_x64.dasc"
1013
0
            /* vivify as clone */
1014
0
            //| mov ARG1, TC;
1015
0
            //| get_spesh_slot ARG2, spesh_idx;
1016
0
            //| callp &MVM_repr_clone;
1017
0
            dasm_put(Dst, 510, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]));
1018
0
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_repr_clone)), (MVMuint32)((uintptr_t)(&MVM_repr_clone) >> 32));
1019
0
#line 628 "src/jit/emit_x64.dasc"
1020
0
            //| mov TMP3, RV;
1021
0
            dasm_put(Dst, 528);
1022
0
#line 629 "src/jit/emit_x64.dasc"
1023
0
            /* reload object and address */
1024
0
            //| mov TMP1, WORK[obj];
1025
0
            //| lea TMP2, [TMP1 + (offset + body)];
1026
0
            //| mov TMP4, P6OPAQUE:TMP1->body.replaced;
1027
0
            //| lea TMP5, [TMP4 + offset];
1028
0
            //| test TMP4, TMP4;
1029
0
            //| cmovnz TMP2, TMP5;
1030
0
            dasm_put(Dst, 359, Dt20([obj]), (offset + body), Dt9(->body.replaced), offset);
1031
0
#line 636 "src/jit/emit_x64.dasc"
1032
0
            /* assign with write barrier */
1033
0
            //| check_wb TMP1, TMP3, >3;
1034
0
            //| mov qword [rbp-0x28], TMP2; // address
1035
0
            //| mov qword [rbp-0x30], TMP3; // value
1036
0
            //| hit_wb WORK[obj]; // write barrier for header
1037
0
            dasm_put(Dst, 431, Dt10(->flags), MVM_CF_SECOND_GEN, Dt10(->flags), MVM_CF_SECOND_GEN, Dt20([obj]));
1038
0
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1039
0
#line 641 "src/jit/emit_x64.dasc"
1040
0
            //| mov TMP3, qword [rbp-0x30];
1041
0
            //| mov TMP2, qword [rbp-0x28];
1042
0
            //|3:
1043
0
            //| mov qword [TMP2], TMP3;
1044
0
            dasm_put(Dst, 537);
1045
0
#line 645 "src/jit/emit_x64.dasc"
1046
0
            /* done */
1047
0
            //|4:
1048
0
            dasm_put(Dst, 496);
1049
0
#line 647 "src/jit/emit_x64.dasc"
1050
9.14k
        } else {
1051
9.14k
            /* the regular case */
1052
9.14k
            //| mov TMP3, [TMP2];
1053
9.14k
            dasm_put(Dst, 406);
1054
9.14k
#line 650 "src/jit/emit_x64.dasc"
1055
9.14k
        }
1056
25.4k
        /* store in local register */
1057
25.4k
        //| mov WORK[dst], TMP3;
1058
25.4k
        dasm_put(Dst, 556, Dt20([dst]));
1059
25.4k
#line 653 "src/jit/emit_x64.dasc"
1060
25.4k
        break;
1061
25.4k
    }
1062
0
    case MVM_OP_sp_bind_i64:
1063
0
    case MVM_OP_sp_bind_n:
1064
0
    case MVM_OP_sp_bind_s:
1065
0
    case MVM_OP_sp_bind_o: {
1066
0
        MVMint16 obj    = ins->operands[0].reg.orig;
1067
0
        MVMint16 offset = ins->operands[1].lit_i16;
1068
0
        MVMint16 val    = ins->operands[2].reg.orig;
1069
0
        //| mov TMP1, WORK[obj];            // object
1070
0
        //| mov TMP2, WORK[val];            // value
1071
0
        dasm_put(Dst, 561, Dt20([obj]), Dt20([val]));
1072
0
#line 664 "src/jit/emit_x64.dasc"
1073
0
        if (op == MVM_OP_sp_bind_o || op == MVM_OP_sp_bind_s) {
1074
0
            /* check if we should hit write barrier */
1075
0
            //| check_wb TMP1, TMP2, >2;
1076
0
            dasm_put(Dst, 570, Dt10(->flags), MVM_CF_SECOND_GEN, Dt10(->flags), MVM_CF_SECOND_GEN);
1077
0
#line 667 "src/jit/emit_x64.dasc"
1078
0
            /* note: it is uneccesary to store pointers, because they
1079
0
               can just be loaded from memory */
1080
0
            //| hit_wb WORK[obj];
1081
0
            dasm_put(Dst, 467, Dt20([obj]));
1082
0
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1083
0
#line 670 "src/jit/emit_x64.dasc"
1084
0
            //| mov TMP1, aword WORK[obj]; // reload object
1085
0
            //| mov TMP2, aword WORK[val]; // reload value
1086
0
            //|2: // done
1087
0
            dasm_put(Dst, 598, Dt20([obj]), Dt20([val]));
1088
0
#line 673 "src/jit/emit_x64.dasc"
1089
0
        }
1090
0
        //| mov qword [TMP1+offset], TMP2; // store value into body
1091
0
        dasm_put(Dst, 614, offset);
1092
0
#line 675 "src/jit/emit_x64.dasc"
1093
0
        break;
1094
0
    }
1095
0
    case MVM_OP_sp_get_i64:
1096
0
    case MVM_OP_sp_get_n:
1097
0
    case MVM_OP_sp_get_s:
1098
0
    case MVM_OP_sp_get_o: {
1099
0
        MVMint16 dst    = ins->operands[0].reg.orig;
1100
0
        MVMint16 obj    = ins->operands[1].reg.orig;
1101
0
        MVMint16 offset = ins->operands[2].lit_i16;
1102
0
        //| mov TMP1, WORK[obj];            // object
1103
0
        //| mov TMP2, qword [TMP1+offset];   // get value from body
1104
0
        //| mov WORK[dst], TMP2;
1105
0
        dasm_put(Dst, 619, Dt20([obj]), offset, Dt20([dst]));
1106
0
#line 687 "src/jit/emit_x64.dasc"
1107
0
        break;
1108
0
    }
1109
0
    case MVM_OP_sp_deref_bind_i64:
1110
0
    case MVM_OP_sp_deref_bind_n: {
1111
0
        MVMint16 obj    = ins->operands[0].reg.orig;
1112
0
        MVMint16 val    = ins->operands[1].reg.orig;
1113
0
        MVMint16 offset = ins->operands[2].lit_i16;
1114
0
        //| mov TMP1, WORK[obj];            // object
1115
0
        //| mov TMP2, WORK[val];            // value
1116
0
        //| mov TMP1, qword [TMP1+offset];  // find address of target
1117
0
        //| mov qword [TMP1], TMP2;
1118
0
        dasm_put(Dst, 632, Dt20([obj]), Dt20([val]), offset);
1119
0
#line 698 "src/jit/emit_x64.dasc"
1120
0
        break;
1121
0
    }
1122
0
    case MVM_OP_sp_deref_get_i64:
1123
0
    case MVM_OP_sp_deref_get_n: {
1124
0
        MVMint16 dst    = ins->operands[0].reg.orig;
1125
0
        MVMint16 obj    = ins->operands[1].reg.orig;
1126
0
        MVMint16 offset = ins->operands[2].lit_i16;
1127
0
        //| mov TMP1, WORK[obj];            // object
1128
0
        //| mov TMP3, qword [TMP1+offset];  // get value pointer from body
1129
0
        //| mov TMP2, qword [TMP3];         // deref the pointer
1130
0
        //| mov WORK[dst], TMP2;
1131
0
        dasm_put(Dst, 648, Dt20([obj]), offset, Dt20([dst]));
1132
0
#line 709 "src/jit/emit_x64.dasc"
1133
0
        break;
1134
0
    }
1135
14.4k
    case MVM_OP_sp_p6obind_i:
1136
14.4k
    case MVM_OP_sp_p6obind_n:
1137
14.4k
    case MVM_OP_sp_p6obind_s:
1138
14.4k
    case MVM_OP_sp_p6obind_o: {
1139
14.4k
        MVMint16 obj    = ins->operands[0].reg.orig;
1140
14.4k
        MVMint16 offset = ins->operands[1].lit_i16;
1141
14.4k
        MVMint16 val    = ins->operands[2].reg.orig;
1142
14.4k
        //| mov TMP1, WORK[obj];            // object
1143
14.4k
        //| mov TMP2, WORK[val];            // value
1144
14.4k
        //| lea TMP3, P6OPAQUE:TMP1->body;  // body
1145
14.4k
        //| cmp qword P6OBODY:TMP3->replaced, 0;
1146
14.4k
        //| je >1;
1147
14.4k
        //| mov TMP3, P6OBODY:TMP3->replaced; // replaced object body
1148
14.4k
        //|1:
1149
14.4k
        dasm_put(Dst, 664, Dt20([obj]), Dt20([val]), Dt9(->body), DtA(->replaced), DtA(->replaced));
1150
14.4k
#line 725 "src/jit/emit_x64.dasc"
1151
14.4k
        if (op == MVM_OP_sp_p6obind_o || op == MVM_OP_sp_p6obind_s) {
1152
9.26k
            /* check if we should hit write barrier */
1153
9.26k
            //| check_wb TMP1, TMP2, >2;
1154
9.26k
            //| mov qword [rbp-0x28], TMP2; // store value
1155
9.26k
            //| mov qword [rbp-0x30], TMP3; // store body pointer
1156
9.26k
            //| hit_wb WORK[obj];
1157
9.26k
            dasm_put(Dst, 692, Dt10(->flags), MVM_CF_SECOND_GEN, Dt10(->flags), MVM_CF_SECOND_GEN, Dt20([obj]));
1158
9.26k
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit)), (MVMuint32)((uintptr_t)(&MVM_gc_write_barrier_hit) >> 32));
1159
9.26k
#line 731 "src/jit/emit_x64.dasc"
1160
9.26k
            //| mov TMP3, qword [rbp-0x30]; // restore body pointer
1161
9.26k
            //| mov TMP2, qword [rbp-0x28]; // restore value
1162
9.26k
            //|2: // done
1163
9.26k
            dasm_put(Dst, 737);
1164
9.26k
#line 734 "src/jit/emit_x64.dasc"
1165
9.26k
        }
1166
14.4k
        //| mov [TMP3+offset], TMP2; // store value into body
1167
14.4k
        dasm_put(Dst, 753, offset);
1168
14.4k
#line 736 "src/jit/emit_x64.dasc"
1169
14.4k
        break;
1170
14.4k
    }
1171
123k
    case MVM_OP_getwhere:
1172
123k
    case MVM_OP_set: {
1173
123k
         MVMint32 reg1 = ins->operands[0].reg.orig;
1174
123k
         MVMint32 reg2 = ins->operands[1].reg.orig;
1175
123k
         //| mov TMP1, WORK[reg2];
1176
123k
         //| mov WORK[reg1], TMP1;
1177
123k
         dasm_put(Dst, 758, Dt20([reg2]), Dt20([reg1]));
1178
123k
#line 744 "src/jit/emit_x64.dasc"
1179
123k
         break;
1180
123k
    }
1181
41.3k
    case MVM_OP_sp_getspeshslot: {
1182
41.3k
        MVMint16 dst = ins->operands[0].reg.orig;
1183
41.3k
        MVMint16 spesh_idx = ins->operands[1].lit_i16;
1184
41.3k
        //| get_spesh_slot TMP1, spesh_idx;
1185
41.3k
        //| mov WORK[dst], TMP1;
1186
41.3k
        dasm_put(Dst, 342, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]), Dt20([dst]));
1187
41.3k
#line 751 "src/jit/emit_x64.dasc"
1188
41.3k
        break;
1189
123k
    }
1190
0
    case MVM_OP_setdispatcher: {
1191
0
        MVMint16 src = ins->operands[0].reg.orig;
1192
0
        //| mov TMP1, aword WORK[src];
1193
0
        //| mov aword TC->cur_dispatcher, TMP1;
1194
0
        dasm_put(Dst, 767, Dt20([src]), Dt1F(->cur_dispatcher));
1195
0
#line 757 "src/jit/emit_x64.dasc"
1196
0
        break;
1197
123k
    }
1198
0
    case MVM_OP_takedispatcher: {
1199
0
        MVMint16 dst = ins->operands[0].reg.orig;
1200
0
        //| mov TMP1, aword TC->cur_dispatcher;
1201
0
        //| cmp TMP1, 0;
1202
0
        //| je >2;
1203
0
        //| mov TMP2, aword TC->cur_dispatcher_for;
1204
0
        //| cmp TMP2, 0;
1205
0
        //| je >1;
1206
0
        //| mov TMP3, TC->cur_frame;
1207
0
        //| mov TMP3, FRAME:TMP3->code_ref;
1208
0
        //| cmp TMP2, TMP3;
1209
0
        //| jne >2;
1210
0
        //|1:
1211
0
        //| mov aword WORK[dst], TMP1;
1212
0
        //| mov aword TC->cur_dispatcher, NULL;
1213
0
        //| jmp >3;
1214
0
        //|2:
1215
0
        //| get_vmnull TMP1;
1216
0
        //| mov aword WORK[dst], TMP1;
1217
0
        //|3:
1218
0
        dasm_put(Dst, 776, Dt1F(->cur_dispatcher), Dt1F(->cur_dispatcher_for), Dt1F(->cur_frame), Dt2(->code_ref), Dt20([dst]), Dt1F(->cur_dispatcher), NULL, Dt1F(->instance), DtC(->VMNull), Dt20([dst]));
1219
0
#line 779 "src/jit/emit_x64.dasc"
1220
0
        break;
1221
123k
    }
1222
0
    case MVM_OP_curcode: {
1223
0
        MVMint16 dst = ins->operands[0].reg.orig;
1224
0
        //| mov TMP1, TC->cur_frame;
1225
0
        //| mov TMP1, aword FRAME:TMP1->code_ref;
1226
0
        //| mov aword WORK[dst], TMP1;
1227
0
        dasm_put(Dst, 123, Dt1F(->cur_frame), Dt2(->code_ref), Dt20([dst]));
1228
0
#line 786 "src/jit/emit_x64.dasc"
1229
0
        break;
1230
123k
    }
1231
369
    case MVM_OP_getcode: {
1232
369
        MVMint16 dst = ins->operands[0].reg.orig;
1233
369
        MVMuint16 idx = ins->operands[1].coderef_idx;
1234
369
        //| mov TMP1, aword CU->body.coderefs;
1235
369
        //| mov TMP1, aword OBJECTPTR:TMP1[idx];
1236
369
        //| mov aword WORK[dst], TMP1;
1237
369
        dasm_put(Dst, 110, Dt21(->body.coderefs), Dt14([idx]), Dt20([dst]));
1238
369
#line 794 "src/jit/emit_x64.dasc"
1239
369
        break;
1240
123k
    }
1241
279
    case MVM_OP_callercode: {
1242
279
        MVMint16 dst = ins->operands[0].reg.orig;
1243
279
        //| mov TMP1, TC->cur_frame;
1244
279
        //| mov TMP1, aword FRAME:TMP1->caller;
1245
279
        //| test TMP1, TMP1;
1246
279
        //| jz >1;
1247
279
        //| mov TMP1, aword FRAME:TMP1->code_ref;
1248
279
        //|1:
1249
279
        //| mov aword WORK[dst], TMP1;
1250
279
        dasm_put(Dst, 849, Dt1F(->cur_frame), Dt2(->caller), Dt2(->code_ref), Dt20([dst]));
1251
279
#line 805 "src/jit/emit_x64.dasc"
1252
279
        break;
1253
123k
    }
1254
6.08k
    case MVM_OP_hllboxtype_n:
1255
6.08k
    case MVM_OP_hllboxtype_s:
1256
6.08k
    case MVM_OP_hllboxtype_i: {
1257
6.08k
        MVMint16 dst = ins->operands[0].reg.orig;
1258
6.08k
        //| mov TMP1, CU->body.hll_config;
1259
6.08k
        dasm_put(Dst, 875, Dt21(->body.hll_config));
1260
6.08k
#line 812 "src/jit/emit_x64.dasc"
1261
6.08k
        if (op == MVM_OP_hllboxtype_n) {
1262
245
            //| mov TMP1, aword HLLCONFIG:TMP1->num_box_type;
1263
245
            dasm_put(Dst, 140, Dt17(->num_box_type));
1264
245
#line 814 "src/jit/emit_x64.dasc"
1265
5.83k
        } else if (op == MVM_OP_hllboxtype_s) {
1266
2.01k
            //| mov TMP1, aword HLLCONFIG:TMP1->str_box_type;
1267
2.01k
            dasm_put(Dst, 140, Dt17(->str_box_type));
1268
2.01k
#line 816 "src/jit/emit_x64.dasc"
1269
3.82k
        } else {
1270
3.82k
            //| mov TMP1, aword HLLCONFIG:TMP1->int_box_type;
1271
3.82k
            dasm_put(Dst, 140, Dt17(->int_box_type));
1272
3.82k
#line 818 "src/jit/emit_x64.dasc"
1273
3.82k
        }
1274
6.08k
        //| mov aword WORK[dst], TMP1;
1275
6.08k
        dasm_put(Dst, 99, Dt20([dst]));
1276
6.08k
#line 820 "src/jit/emit_x64.dasc"
1277
6.08k
        break;
1278
6.08k
    }
1279
0
    case MVM_OP_null_s: {
1280
0
        MVMint16 dst = ins->operands[0].reg.orig;
1281
0
        //| mov qword WORK[dst], 0;
1282
0
        dasm_put(Dst, 880, Dt20([dst]));
1283
0
#line 825 "src/jit/emit_x64.dasc"
1284
0
        break;
1285
6.08k
     }
1286
1.21k
    case MVM_OP_isnull_s: {
1287
1.21k
        MVMint16 dst = ins->operands[0].reg.orig;
1288
1.21k
        MVMint16 src = ins->operands[1].reg.orig;
1289
1.21k
        //| mov TMP1, WORK[src];
1290
1.21k
        //| test TMP1, TMP1;
1291
1.21k
        //| setz TMP2b;
1292
1.21k
        //| movzx TMP2, TMP2b;
1293
1.21k
        //| mov qword WORK[dst], TMP2;
1294
1.21k
        dasm_put(Dst, 889, Dt20([src]), Dt20([dst]));
1295
1.21k
#line 835 "src/jit/emit_x64.dasc"
1296
1.21k
        break;
1297
6.08k
    }
1298
6.08k
1299
5.57k
    case MVM_OP_add_i:
1300
5.57k
    case MVM_OP_sub_i:
1301
5.57k
    case MVM_OP_bor_i:
1302
5.57k
    case MVM_OP_band_i:
1303
5.57k
    case MVM_OP_bxor_i: {
1304
5.57k
        MVMint32 reg_a = ins->operands[0].reg.orig;
1305
5.57k
        MVMint32 reg_b = ins->operands[1].reg.orig;
1306
5.57k
        MVMint32 reg_c = ins->operands[2].reg.orig;
1307
5.57k
1308
5.57k
        MVMSpeshFacts *operand_facts = MVM_spesh_get_facts(tc, jg->sg, ins->operands[2]);
1309
5.57k
1310
5.57k
        if (reg_a == reg_b) {
1311
3.19k
            if (operand_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE &&
1312
3.05k
                fits_in_32_bit(operand_facts->value.i)) {
1313
3.05k
                MVMint64 value = operand_facts->value.i;
1314
3.05k
                MVM_jit_log(tc, "accumulator for %s stayed in memory and "
1315
3.05k
                            " constant value %"PRId64" used\n", ins->info->name, value);
1316
3.05k
                switch(ins->info->opcode) {
1317
1.17k
                case MVM_OP_add_i:
1318
1.17k
                    //| add qword WORK[reg_a], qword value;
1319
1.17k
                    dasm_put(Dst, 908, Dt20([reg_a]), value);
1320
1.17k
#line 858 "src/jit/emit_x64.dasc"
1321
1.17k
                    break;
1322
1.88k
                case MVM_OP_sub_i:
1323
1.88k
                    //| sub qword WORK[reg_a], qword value;
1324
1.88k
                    dasm_put(Dst, 914, Dt20([reg_a]), value);
1325
1.88k
#line 861 "src/jit/emit_x64.dasc"
1326
1.88k
                    break;
1327
0
                case MVM_OP_bor_i:
1328
0
                    //| or qword WORK[reg_a], qword value;
1329
0
                    dasm_put(Dst, 920, Dt20([reg_a]), value);
1330
0
#line 864 "src/jit/emit_x64.dasc"
1331
0
                    break;
1332
0
                case MVM_OP_band_i:
1333
0
                    //| and qword WORK[reg_a], qword value;
1334
0
                    dasm_put(Dst, 926, Dt20([reg_a]), value);
1335
0
#line 867 "src/jit/emit_x64.dasc"
1336
0
                    break;
1337
0
                case MVM_OP_bxor_i:
1338
0
                    //| xor qword WORK[reg_a], qword value;
1339
0
                    dasm_put(Dst, 932, Dt20([reg_a]), value);
1340
0
#line 870 "src/jit/emit_x64.dasc"
1341
0
                    break;
1342
3.05k
                }
1343
145
            } else {
1344
145
                MVM_jit_log(tc, "accumulator for %s stayed in memory\n", ins->info->name);
1345
145
                //| mov rax, WORK[reg_c];
1346
145
                dasm_put(Dst, 938, Dt20([reg_c]));
1347
145
#line 875 "src/jit/emit_x64.dasc"
1348
145
                switch(ins->info->opcode) {
1349
120
                case MVM_OP_add_i:
1350
120
                    //| add WORK[reg_a], rax;
1351
120
                    dasm_put(Dst, 943, Dt20([reg_a]));
1352
120
#line 878 "src/jit/emit_x64.dasc"
1353
120
                    break;
1354
25
                case MVM_OP_sub_i:
1355
25
                    //| sub WORK[reg_a], rax;
1356
25
                    dasm_put(Dst, 948, Dt20([reg_a]));
1357
25
#line 881 "src/jit/emit_x64.dasc"
1358
25
                    break;
1359
0
                case MVM_OP_bor_i:
1360
0
                    //| or WORK[reg_a], rax;
1361
0
                    dasm_put(Dst, 953, Dt20([reg_a]));
1362
0
#line 884 "src/jit/emit_x64.dasc"
1363
0
                    break;
1364
0
                case MVM_OP_band_i:
1365
0
                    //| and WORK[reg_a], rax;
1366
0
                    dasm_put(Dst, 958, Dt20([reg_a]));
1367
0
#line 887 "src/jit/emit_x64.dasc"
1368
0
                    break;
1369
0
                case MVM_OP_bxor_i:
1370
0
                    //| xor WORK[reg_a], rax;
1371
0
                    dasm_put(Dst, 963, Dt20([reg_a]));
1372
0
#line 890 "src/jit/emit_x64.dasc"
1373
0
                    break;
1374
145
                }
1375
145
            }
1376
2.38k
        } else {
1377
2.38k
            if (operand_facts->flags & MVM_SPESH_FACT_KNOWN_VALUE &&
1378
1.76k
                fits_in_32_bit(operand_facts->value.i)) {
1379
1.76k
                MVMint64 value = operand_facts->value.i;
1380
1.76k
                MVM_jit_log(tc, "constant value %"PRId64" used for %s\n",
1381
1.76k
                            value, ins->info->name);
1382
1.76k
                //| mov rax, WORK[reg_b];
1383
1.76k
                dasm_put(Dst, 938, Dt20([reg_b]));
1384
1.76k
#line 900 "src/jit/emit_x64.dasc"
1385
1.76k
                switch(ins->info->opcode) {
1386
1.13k
                case MVM_OP_add_i:
1387
1.13k
                    //| add rax, qword value;
1388
1.13k
                    dasm_put(Dst, 968, value);
1389
1.13k
#line 903 "src/jit/emit_x64.dasc"
1390
1.13k
                    break;
1391
620
                case MVM_OP_sub_i:
1392
620
                    //| sub rax, qword value;
1393
620
                    dasm_put(Dst, 973, value);
1394
620
#line 906 "src/jit/emit_x64.dasc"
1395
620
                    break;
1396
0
                case MVM_OP_bor_i:
1397
0
                    //| or rax, qword value;
1398
0
                    dasm_put(Dst, 978, value);
1399
0
#line 909 "src/jit/emit_x64.dasc"
1400
0
                    break;
1401
6
                case MVM_OP_band_i:
1402
6
                    //| and rax, qword value;
1403
6
                    dasm_put(Dst, 983, value);
1404
6
#line 912 "src/jit/emit_x64.dasc"
1405
6
                    break;
1406
0
                case MVM_OP_bxor_i:
1407
0
                    //| xor rax, qword value;
1408
0
                    dasm_put(Dst, 988, value);
1409
0
#line 915 "src/jit/emit_x64.dasc"
1410
0
                    break;
1411
1.76k
                }
1412
1.76k
                //| mov WORK[reg_a], rax;
1413
1.76k
                dasm_put(Dst, 274, Dt20([reg_a]));
1414
1.76k
#line 918 "src/jit/emit_x64.dasc"
1415
615
            } else {
1416
615
                //| mov rax, WORK[reg_b];
1417
615
                dasm_put(Dst, 938, Dt20([reg_b]));
1418
615
#line 920 "src/jit/emit_x64.dasc"
1419
615
                switch(ins->info->opcode) {
1420
75
                case MVM_OP_add_i:
1421
75
                    //| add rax, WORK[reg_c];
1422
75
                    dasm_put(Dst, 994, Dt20([reg_c]));
1423
75
#line 923 "src/jit/emit_x64.dasc"
1424
75
                    break;
1425
268
                case MVM_OP_sub_i:
1426
268
                    //| sub rax, WORK[reg_c];
1427
268
                    dasm_put(Dst, 999, Dt20([reg_c]));
1428
268
#line 926 "src/jit/emit_x64.dasc"
1429
268
                    break;
1430
37
                case MVM_OP_bor_i:
1431
37
                    //| or rax, WORK[reg_c];
1432
37
                    dasm_put(Dst, 1004, Dt20([reg_c]));
1433
37
#line 929 "src/jit/emit_x64.dasc"
1434
37
                    break;
1435
235
                case MVM_OP_band_i:
1436
235
                    //| and rax, WORK[reg_c];
1437
235
                    dasm_put(Dst, 1009, Dt20([reg_c]));
1438
235
#line 932 "src/jit/emit_x64.dasc"
1439
235
                    break;
1440
0
                case MVM_OP_bxor_i:
1441
0
                    //| xor rax, WORK[reg_c];
1442
0
                    dasm_put(Dst, 1014, Dt20([reg_c]));
1443
0
#line 935 "src/jit/emit_x64.dasc"
1444
0
                    break;
1445
615
                }
1446
615
                //| mov WORK[reg_a], rax;
1447
615
                dasm_put(Dst, 274, Dt20([reg_a]));
1448
615
#line 938 "src/jit/emit_x64.dasc"
1449
615
            }
1450
2.38k
        }
1451
5.57k
        break;
1452
5.57k
    }
1453
0
    case MVM_OP_mul_i:
1454
0
    case MVM_OP_blshift_i:
1455
0
    case MVM_OP_brshift_i: {
1456
0
        MVMint32 reg_a = ins->operands[0].reg.orig;
1457
0
        MVMint32 reg_b = ins->operands[1].reg.orig;
1458
0
        MVMint32 reg_c = ins->operands[2].reg.orig;
1459
0
        //| mov rax, WORK[reg_b];
1460
0
        dasm_put(Dst, 938, Dt20([reg_b]));
1461
0
#line 949 "src/jit/emit_x64.dasc"
1462
0
        switch(ins->info->opcode) {
1463
0
        case MVM_OP_mul_i:
1464
0
            //| imul rax, WORK[reg_c];
1465
0
            dasm_put(Dst, 1019, Dt20([reg_c]));
1466
0
#line 952 "src/jit/emit_x64.dasc"
1467
0
            break;
1468
0
        case MVM_OP_blshift_i:
1469
0
            //| mov cl, byte WORK[reg_c];
1470
0
            //| shl rax, cl;
1471
0
            dasm_put(Dst, 1025, Dt20([reg_c]));
1472
0
#line 956 "src/jit/emit_x64.dasc"
1473
0
            break;
1474
0
        case MVM_OP_brshift_i:
1475
0
            //| mov cl, byte WORK[reg_c];
1476
0
            //| shr rax, cl;
1477
0
            dasm_put(Dst, 1032, Dt20([reg_c]));
1478
0
#line 960 "src/jit/emit_x64.dasc"
1479
0
            break;
1480
0
        }
1481
0
        //| mov WORK[reg_a], rax;
1482
0
        dasm_put(Dst, 274, Dt20([reg_a]));
1483
0
#line 963 "src/jit/emit_x64.dasc"
1484
0
        break;
1485
0
    }
1486
68
    case MVM_OP_div_i: {
1487
68
        MVMint16 dst = ins->operands[0].reg.orig;
1488
68
        MVMint16 a   = ins->operands[1].reg.orig;
1489
68
        MVMint16 b   = ins->operands[2].reg.orig;
1490
68
        //| mov rax, WORK[a];
1491
68
        //| mov rcx, WORK[b];
1492
68
        //| cmp rcx, 0;
1493
68
        //| jnz >1;
1494
68
        //| throw_adhoc "Division by zero";
1495
68
        dasm_put(Dst, 1039, Dt20([a]), Dt20([b]), (unsigned int)((uintptr_t)("Division by zero")), (unsigned int)(((uintptr_t)("Division by zero"))>>32));
1496
68
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1497
68
#line 974 "src/jit/emit_x64.dasc"
1498
68
        //|1:
1499
68
        dasm_put(Dst, 1066);
1500
68
#line 975 "src/jit/emit_x64.dasc"
1501
68
        /* either num < 0, or denom < 0, but not both */
1502
68
        //| setl dh;
1503
68
        //| cmp rax, 0;
1504
68
        //| setl dl;
1505
68
        //| xor dl, dh;
1506
68
        //| movzx r8d, dl;
1507
68
        //| cqo;
1508
68
        //| idiv rcx;
1509
68
        //| test rdx, rdx;
1510
68
        //| setnz cl;
1511
68
        //| and r8b, cl;
1512
68
        dasm_put(Dst, 1074);
1513
68
#line 986 "src/jit/emit_x64.dasc"
1514
68
        /* r8 = bias = (modulo != 0) & ((num < 0) ^ (denom < 0)) */
1515
68
        //| sub rax, r8;
1516
68
        //| mov WORK[dst], rax;
1517
68
        dasm_put(Dst, 1109, Dt20([dst]));
1518
68
#line 989 "src/jit/emit_x64.dasc"
1519
68
        break;
1520
0
    }
1521
203
    case MVM_OP_mod_i: {
1522
203
        MVMint16 dst = ins->operands[0].reg.orig;
1523
203
        MVMint16 a   = ins->operands[1].reg.orig;
1524
203
        MVMint16 b   = ins->operands[2].reg.orig;
1525
203
        //| mov rax, WORK[a];
1526
203
        //| mov rcx, WORK[b];
1527
203
        //| cmp rcx, 0;
1528
203
        //| jnz >1;
1529
203
        //| throw_adhoc "Division by zero";
1530
203
        dasm_put(Dst, 1039, Dt20([a]), Dt20([b]), (unsigned int)((uintptr_t)("Division by zero")), (unsigned int)(((uintptr_t)("Division by zero"))>>32));
1531
203
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
1532
203
#line 1000 "src/jit/emit_x64.dasc"
1533
203
        //|1:
1534
203
        //| cqo;
1535
203
        //| idiv rcx;
1536
203
        //| mov WORK[dst], rdx;
1537
203
        dasm_put(Dst, 1117, Dt20([dst]));
1538
203
#line 1004 "src/jit/emit_x64.dasc"
1539
203
        break;
1540
0
    }
1541
3.93k
    case MVM_OP_inc_i: {
1542
3.93k
         MVMint32 reg = ins->operands[0].reg.orig;
1543
3.93k
         //| add qword WORK[reg], 1;
1544
3.93k
         dasm_put(Dst, 1136, Dt20([reg]));
1545
3.93k
#line 1009 "src/jit/emit_x64.dasc"
1546
3.93k
         break;
1547
0
    }
1548
4.38k
    case MVM_OP_dec_i: {
1549
4.38k
        MVMint32 reg = ins->operands[0].reg.orig;
1550
4.38k
        //| sub qword WORK[reg], 1;
1551
4.38k
        dasm_put(Dst, 1142, Dt20([reg]));
1552
4.38k
#line 1014 "src/jit/emit_x64.dasc"
1553
4.38k
        break;
1554
0
    }
1555
0
    case MVM_OP_bnot_i: {
1556
0
        MVMint16 dst = ins->operands[0].reg.orig;
1557
0
        MVMint16 src = ins->operands[1].reg.orig;
1558
0
        //| mov TMP1, WORK[src];
1559
0
        //| not TMP1;
1560
0
        //| mov WORK[dst], TMP1;
1561
0
        dasm_put(Dst, 1148, Dt20([src]), Dt20([dst]));
1562
0
#line 1022 "src/jit/emit_x64.dasc"
1563
0
        break;
1564
0
    }
1565
0
    case MVM_OP_neg_i: {
1566
0
        MVMint16 dst = ins->operands[0].reg.orig;
1567
0
        MVMint16 src = ins->operands[1].reg.orig;
1568
0
        //| mov TMP1, WORK[src];
1569
0
        //| neg TMP1;
1570
0
        //| mov WORK[dst], TMP1;
1571
0
        dasm_put(Dst, 1161, Dt20([src]), Dt20([dst]));
1572
0
#line 1030 "src/jit/emit_x64.dasc"
1573
0
        break;
1574
0
    }
1575
0
    case MVM_OP_extend_i32: {
1576
0
        MVMint16 dst = ins->operands[0].reg.orig;
1577
0
        MVMint16 src = ins->operands[1].reg.orig;
1578
0
        //| mov RV, WORK[src];
1579
0
        //| cdqe
1580
0
        //| mov WORK[dst], RV;
1581
0
        dasm_put(Dst, 1174, Dt20([src]), Dt20([dst]));
1582
0
#line 1038 "src/jit/emit_x64.dasc"
1583
0
        break;
1584
0
    }
1585
0
    case MVM_OP_trunc_i32: {
1586
0
        MVMint16 dst = ins->operands[0].reg.orig;
1587
0
        MVMint16 src = ins->operands[1].reg.orig;
1588
0
        //| mov TMP1, WORK[src];
1589
0
        dasm_put(Dst, 1185, Dt20([src]));
1590
0
#line 1044 "src/jit/emit_x64.dasc"
1591
0
        /* x86-64 auto-truncates the upper 32 bits when using registers in 32
1592
0
         * bit mode */
1593
0
        //| mov TMP2d, TMP1d;
1594
0
        //| mov WORK[dst], TMP2;
1595
0
        dasm_put(Dst, 1190, Dt20([dst]));
1596
0
#line 1048 "src/jit/emit_x64.dasc"
1597
0
        break;
1598
0
    }
1599
357
    case MVM_OP_add_n:
1600
357
    case MVM_OP_sub_n:
1601
357
    case MVM_OP_mul_n:
1602
357
    case MVM_OP_div_n: {
1603
357
        MVMint16 reg_a = ins->operands[0].reg.orig;
1604
357
        MVMint16 reg_b = ins->operands[1].reg.orig;
1605
357
        MVMint16 reg_c = ins->operands[2].reg.orig;
1606
357
        /* Copying data to xmm (floating point) registers requires
1607
357
         * a special move instruction */
1608
357
        //| movsd xmm0, qword WORK[reg_b];
1609
357
        dasm_put(Dst, 1197, Dt20([reg_b]));
1610
357
#line 1060 "src/jit/emit_x64.dasc"
1611
357
        switch(ins->info->opcode) {
1612
111
        case MVM_OP_add_n:
1613
111
            //| addsd xmm0, qword WORK[reg_c];
1614
111
            dasm_put(Dst, 1204, Dt20([reg_c]));
1615
111
#line 1063 "src/jit/emit_x64.dasc"
1616
111
            break;
1617
29
        case MVM_OP_sub_n:
1618
29
            //| subsd xmm0, qword WORK[reg_c];
1619
29
            dasm_put(Dst, 1211, Dt20([reg_c]));
1620
29
#line 1066 "src/jit/emit_x64.dasc"
1621
29
            break;
1622
1
        case MVM_OP_mul_n:
1623
1
            //| mulsd xmm0, qword WORK[reg_c];
1624
1
            dasm_put(Dst, 1218, Dt20([reg_c]));
1625
1
#line 1069 "src/jit/emit_x64.dasc"
1626
1
            break;
1627
216
        case MVM_OP_div_n:
1628
216
            //| divsd xmm0, qword WORK[reg_c];
1629
216
            dasm_put(Dst, 1225, Dt20([reg_c]));
1630
216
#line 1072 "src/jit/emit_x64.dasc"
1631
216
            break;
1632
357
        }
1633
357
        //| movsd qword WORK[reg_a], xmm0;
1634
357
        dasm_put(Dst, 1232, Dt20([reg_a]));
1635
357
#line 1075 "src/jit/emit_x64.dasc"
1636
357
        break;
1637
357
    }
1638
2.12k
    case MVM_OP_coerce_in: {
1639
2.12k
        MVMint16 dst = ins->operands[0].reg.orig;
1640
2.12k
        MVMint16 src = ins->operands[1].reg.orig;
1641
2.12k
        /* convert simple integer to double precision */
1642
2.12k
        //| cvtsi2sd xmm0, qword WORK[src];
1643
2.12k
        //| movsd qword WORK[dst], xmm0;
1644
2.12k
        dasm_put(Dst, 1239, Dt20([src]), Dt20([dst]));
1645
2.12k
#line 1083 "src/jit/emit_x64.dasc"
1646
2.12k
        break;
1647
357
    }
1648
3.60k
    case MVM_OP_coerce_ni: {
1649
3.60k
        MVMint16 dst = ins->operands[0].reg.orig;
1650
3.60k
        MVMint16 src = ins->operands[1].reg.orig;
1651
3.60k
        /* convert double precision to simple intege */
1652
3.60k
        //| cvttsd2si rax, qword WORK[src];
1653
3.60k
        //| mov WORK[dst], rax;
1654
3.60k
        dasm_put(Dst, 1253, Dt20([src]), Dt20([dst]));
1655
3.60k
#line 1091 "src/jit/emit_x64.dasc"
1656
3.60k
        break;
1657
357
    }
1658
6
    case MVM_OP_neg_n: {
1659
6
        /* Negation is xor-ing the highest byte. Pretty simple right */
1660
6
        MVMint16 dst = ins->operands[0].reg.orig;
1661
6
        MVMint16 src = ins->operands[1].reg.orig;
1662
6
        //| mov TMP1, 1;
1663
6
        //| sal TMP1, 63;
1664
6
        //| mov TMP2, qword WORK[src];
1665
6
        //| xor TMP2, TMP1;
1666
6
        //| mov qword WORK[dst], TMP2;
1667
6
        dasm_put(Dst, 1265, Dt20([src]), Dt20([dst]));
1668
6
#line 1102 "src/jit/emit_x64.dasc"
1669
6
        break;
1670
357
    }
1671
20.3k
    case MVM_OP_eq_i:
1672
20.3k
    case MVM_OP_eqaddr:
1673
20.3k
    case MVM_OP_ne_i:
1674
20.3k
    case MVM_OP_lt_i:
1675
20.3k
    case MVM_OP_le_i:
1676
20.3k
    case MVM_OP_gt_i:
1677
20.3k
    case MVM_OP_ge_i: {
1678
20.3k
        MVMint32 reg_a = ins->operands[0].reg.orig;
1679
20.3k
        MVMint32 reg_b = ins->operands[1].reg.orig;
1680
20.3k
        MVMint32 reg_c = ins->operands[2].reg.orig;
1681
20.3k
        //| mov rax, WORK[reg_b];
1682
20.3k
        dasm_put(Dst, 938, Dt20([reg_b]));
1683
20.3k
#line 1115 "src/jit/emit_x64.dasc"
1684
20.3k
        /* comparison result in the setting bits in the rflags register */
1685
20.3k
        //| cmp rax, WORK[reg_c];
1686
20.3k
        dasm_put(Dst, 1288, Dt20([reg_c]));
1687
20.3k
#line 1117 "src/jit/emit_x64.dasc"
1688
20.3k
        /* copy the right comparison bit to the lower byte of the rax
1689
20.3k
           register */
1690
20.3k
        switch(ins->info->opcode) {
1691
5.44k
        case MVM_OP_eqaddr:
1692
5.44k
        case MVM_OP_eq_i:
1693
5.44k
            //| sete al;
1694
5.44k
            dasm_put(Dst, 1293);
1695
5.44k
#line 1123 "src/jit/emit_x64.dasc"
1696
5.44k
            break;
1697
667
        case MVM_OP_ne_i:
1698
667
            //| setne al;
1699
667
            dasm_put(Dst, 1297);
1700
667
#line 1126 "src/jit/emit_x64.dasc"
1701
667
            break;
1702
6.38k
        case MVM_OP_lt_i:
1703
6.38k
            //| setl al;
1704
6.38k
            dasm_put(Dst, 1301);
1705
6.38k
#line 1129 "src/jit/emit_x64.dasc"
1706
6.38k
            break;
1707
524
        case MVM_OP_le_i:
1708
524
            //| setle al;
1709
524
            dasm_put(Dst, 1305);
1710
524
#line 1132 "src/jit/emit_x64.dasc"
1711
524
            break;
1712
5.79k
        case MVM_OP_gt_i:
1713
5.79k
            //| setg al;
1714
5.79k
            dasm_put(Dst, 1309);
1715
5.79k
#line 1135 "src/jit/emit_x64.dasc"
1716
5.79k
            break;
1717
1.48k
        case MVM_OP_ge_i:
1718
1.48k
            //| setge al;
1719
1.48k
            dasm_put(Dst, 1313);
1720
1.48k
#line 1138 "src/jit/emit_x64.dasc"
1721
1.48k
            break;
1722
20.3k
        }
1723
20.3k
        /* zero extend al (lower byte) to rax (whole register) */
1724
20.3k
        //| movzx rax, al;
1725
20.3k
        //| mov WORK[reg_a], rax;
1726
20.3k
        dasm_put(Dst, 1317, Dt20([reg_a]));
1727
20.3k
#line 1143 "src/jit/emit_x64.dasc"
1728
20.3k
        break;
1729
20.3k
    }
1730
0
    case MVM_OP_cmp_i : {
1731
0
        MVMint32 reg_a = ins->operands[0].reg.orig;
1732
0
        MVMint32 reg_b = ins->operands[1].reg.orig;
1733
0
        MVMint32 reg_c = ins->operands[2].reg.orig;
1734
0
        //| mov TMP1, WORK[reg_b];
1735
0
        dasm_put(Dst, 1185, Dt20([reg_b]));
1736
0
#line 1150 "src/jit/emit_x64.dasc"
1737
0
        /* comparison result in the setting bits in the rflags register */
1738
0
        //| cmp TMP1, WORK[reg_c];
1739
0
        dasm_put(Dst, 1326, Dt20([reg_c]));
1740
0
#line 1152 "src/jit/emit_x64.dasc"
1741
0
        /* copy the right comparison bit to the lower byte of the rax
1742
0
           register */
1743
0
        //| setg TMP2b;
1744
0
        //| movzx TMP2, TMP2b;
1745
0
        //| setl TMP3b;
1746
0
        //| movzx TMP3, TMP3b;
1747
0
        //| sub TMP2, TMP3;
1748
0
        //| mov WORK[reg_a], TMP2;
1749
0
        dasm_put(Dst, 1331, Dt20([reg_a]));
1750
0
#line 1160 "src/jit/emit_x64.dasc"
1751
0
        break;
1752
20.3k
    }
1753
28
    case MVM_OP_gt_s:
1754
28
    case MVM_OP_ge_s:
1755
28
    case MVM_OP_lt_s:
1756
28
    case MVM_OP_le_s: {
1757
28
        /* src/jit/graph.c already put a call to the MVM_string_compare
1758
28
           function into the graph, so here we just have to deal with the
1759
28
           returned integers. */
1760
28
        MVMint32 reg = ins->operands[0].reg.orig;
1761
28
        switch(ins->info->opcode) {
1762
28
            case MVM_OP_gt_s:
1763
28
                //| mov TMP2, 1;
1764
28
                dasm_put(Dst, 1354);
1765
28
#line 1173 "src/jit/emit_x64.dasc"
1766
28
                break;
1767
0
            case MVM_OP_lt_s:
1768
0
                //| mov TMP2, -1;
1769
0
                dasm_put(Dst, 1362);
1770
0
#line 1176 "src/jit/emit_x64.dasc"
1771
0
                break;
1772
0
            case MVM_OP_ge_s: case MVM_OP_le_s:
1773
0
                //| mov TMP2, 0;
1774
0
                dasm_put(Dst, 1374);
1775
0
#line 1179 "src/jit/emit_x64.dasc"
1776
0
                break;
1777
28
        }
1778
28
        //| cmp TMP2, WORK[reg];
1779
28
        dasm_put(Dst, 1382, Dt20([reg]));
1780
28
#line 1182 "src/jit/emit_x64.dasc"
1781
28
        /* Mind the reversedness of the constant and the value as compared to
1782
28
         * interp.c */
1783
28
        switch(ins->info->opcode) {
1784
28
            case MVM_OP_gt_s:
1785
28
                //| sete al;
1786
28
                dasm_put(Dst, 1293);
1787
28
#line 1187 "src/jit/emit_x64.dasc"
1788
28
                break;
1789
0
            case MVM_OP_ge_s:
1790
0
                //| setle al;
1791
0
                dasm_put(Dst, 1305);
1792
0
#line 1190 "src/jit/emit_x64.dasc"
1793
0
                break;
1794
0
            case MVM_OP_lt_s:
1795
0
                //| sete al;
1796
0
                dasm_put(Dst, 1293);
1797
0
#line 1193 "src/jit/emit_x64.dasc"
1798
0
                break;
1799
0
            case MVM_OP_le_s:
1800
0
                //| setge al;
1801
0
                dasm_put(Dst, 1313);
1802
0
#line 1196 "src/jit/emit_x64.dasc"
1803
0
                break;
1804
28
        }
1805
28
        //| movzx rax, al;
1806
28
        //| mov WORK[reg], rax;
1807
28
        dasm_put(Dst, 1317, Dt20([reg]));
1808
28
#line 1200 "src/jit/emit_x64.dasc"
1809
28
        break;
1810
28
    }
1811
3.51k
    case MVM_OP_not_i: {
1812
3.51k
        MVMint16 dst = ins->operands[0].reg.orig;
1813
3.51k
        MVMint16 src = ins->operands[1].reg.orig;
1814
3.51k
        //| mov TMP1, WORK[src];
1815
3.51k
        //| test TMP1, TMP1;
1816
3.51k
        //| setz TMP2b;
1817
3.51k
        //| movzx TMP2, TMP2b;
1818
3.51k
        //| mov WORK[dst], TMP2;
1819
3.51k
        dasm_put(Dst, 889, Dt20([src]), Dt20([dst]));
1820
3.51k
#line 1210 "src/jit/emit_x64.dasc"
1821
3.51k
        break;
1822
28
    }
1823
2.53k
    case MVM_OP_eq_n:
1824
2.53k
    case MVM_OP_ne_n:
1825
2.53k
    case MVM_OP_le_n:
1826
2.53k
    case MVM_OP_lt_n:
1827
2.53k
    case MVM_OP_ge_n:
1828
2.53k
    case MVM_OP_gt_n: {
1829
2.53k
        MVMint16 dst = ins->operands[0].reg.orig;
1830
2.53k
        MVMint16 a   = ins->operands[1].reg.orig;
1831
2.53k
        MVMint16 b   = ins->operands[2].reg.orig;
1832
2.53k
        if (op == MVM_OP_eq_n) {
1833
1.13k
            //| mov TMP1, 0;
1834
1.13k
            dasm_put(Dst, 1387);
1835
1.13k
#line 1223 "src/jit/emit_x64.dasc"
1836
1.39k
        } else if (op == MVM_OP_ne_n) {
1837
316
            //| mov TMP1, 1;
1838
316
            dasm_put(Dst, 1395);
1839
316
#line 1225 "src/jit/emit_x64.dasc"
1840
316
        }
1841
2.53k
        if (op == MVM_OP_lt_n || op == MVM_OP_le_n) {
1842
492
            //| movsd xmm0, qword WORK[b];
1843
492
            //| ucomisd xmm0, qword WORK[a];
1844
492
            dasm_put(Dst, 1403, Dt20([b]), Dt20([a]));
1845
492
#line 1229 "src/jit/emit_x64.dasc"
1846
2.03k
        } else {
1847
2.03k
            //| movsd xmm0, qword WORK[a];
1848
2.03k
            //| ucomisd xmm0, qword WORK[b];
1849
2.03k
            dasm_put(Dst, 1403, Dt20([a]), Dt20([b]));
1850
2.03k
#line 1232 "src/jit/emit_x64.dasc"
1851
2.03k
        }
1852
2.53k
1853
2.53k
        if (op == MVM_OP_le_n || op == MVM_OP_ge_n) {
1854
568
            //| setae TMP1b;
1855
568
            dasm_put(Dst, 1415);
1856
568
#line 1236 "src/jit/emit_x64.dasc"
1857
1.96k
        } else if (op == MVM_OP_eq_n) {
1858
1.13k
            //| setnp TMP2b; // zero if either is NaN, 1 otherwise
1859
1.13k
            //| cmove TMP1, TMP2; // if equal, overwrite 0 with 1
1860
1.13k
            dasm_put(Dst, 1419);
1861
1.13k
#line 1239 "src/jit/emit_x64.dasc"
1862
831
        } else if (op == MVM_OP_ne_n) {
1863
316
            //| setp TMP2b; // 1 if either is NaN (in which case they can't be equal)
1864
316
            //| cmove TMP1, TMP2; // if equal, overwrite 1 with IsNan(a) | IsNaN(b)
1865
316
            dasm_put(Dst, 1427);
1866
316
#line 1242 "src/jit/emit_x64.dasc"
1867
515
        } else {
1868
515
            //| seta TMP1b;
1869
515
            dasm_put(Dst, 1435);
1870
515
#line 1244 "src/jit/emit_x64.dasc"
1871
515
        }
1872
2.53k
        //| movzx TMP1, TMP1b;
1873
2.53k
        //| mov WORK[dst], TMP1;
1874
2.53k
        dasm_put(Dst, 1439, Dt20([dst]));
1875
2.53k
#line 1247 "src/jit/emit_x64.dasc"
1876
2.53k
        break;
1877
2.53k
    }
1878
0
    case MVM_OP_cmp_n: {
1879
0
        MVMint16 dst = ins->operands[0].reg.orig;
1880
0
        MVMint16 a   = ins->operands[1].reg.orig;
1881
0
        MVMint16 b   = ins->operands[2].reg.orig;
1882
0
        //| movsd xmm0, qword WORK[a];
1883
0
        //| movsd xmm1, qword WORK[b];
1884
0
        //| ucomisd xmm0, xmm1
1885
0
        //| seta TMP1b;
1886
0
        //| movzx rax, TMP1b;
1887
0
        //| ucomisd xmm1, xmm0
1888
0
        //| seta TMP1b;
1889
0
        //| movzx TMP1, TMP1b;
1890
0
        //| sub rax, TMP1;
1891
0
        //| mov WORK[dst], rax;
1892
0
        dasm_put(Dst, 1448, Dt20([a]), Dt20([b]), Dt20([dst]));
1893
0
#line 1263 "src/jit/emit_x64.dasc"
1894
0
        break;
1895
2.53k
    }
1896
0
    case MVM_OP_eq_I:
1897
0
    case MVM_OP_ne_I:
1898
0
    case MVM_OP_lt_I:
1899
0
    case MVM_OP_le_I:
1900
0
    case MVM_OP_gt_I:
1901
0
    case MVM_OP_ge_I: {
1902
0
        MVMint32 reg_a = ins->operands[0].reg.orig;
1903
0
        MVMint32 reg_b = ins->operands[1].reg.orig;
1904
0
        MVMint32 reg_c = ins->operands[2].reg.orig;
1905
0
        /* Call the bigint comparison function. */
1906
0
        //| mov ARG1, tc;
1907
0
        //| mov ARG2, WORK[reg_b];
1908
0
        //| mov ARG3, WORK[reg_c];
1909
0
        //| callp &MVM_bigint_cmp;
1910
0
        dasm_put(Dst, 1490, tc, Dt20([reg_b]), Dt20([reg_c]));
1911
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_bigint_cmp)), (MVMuint32)((uintptr_t)(&MVM_bigint_cmp) >> 32));
1912
0
        dasm_put(Dst, 212);
1913
0
#line 1279 "src/jit/emit_x64.dasc"
1914
0
        /* Handle result by opcode. */
1915
0
        switch(ins->info->opcode) {
1916
0
        case MVM_OP_eq_I:
1917
0
            //| cmp RV, MP_EQ
1918
0
            //| sete al;
1919
0
            dasm_put(Dst, 1504, MP_EQ);
1920
0
#line 1284 "src/jit/emit_x64.dasc"
1921
0
            break;
1922
0
        case MVM_OP_ne_I:
1923
0
            //| cmp RV, MP_EQ
1924
0
            //| setne al;
1925
0
            dasm_put(Dst, 1513, MP_EQ);
1926
0
#line 1288 "src/jit/emit_x64.dasc"
1927
0
            break;
1928
0
        case MVM_OP_lt_I:
1929
0
            //| cmp RV, MP_LT
1930
0
            //| sete al;
1931
0
            dasm_put(Dst, 1504, MP_LT);
1932
0
#line 1292 "src/jit/emit_x64.dasc"
1933
0
            break;
1934
0
        case MVM_OP_le_I:
1935
0
            //| cmp RV, MP_GT
1936
0
            //| setne al;
1937
0
            dasm_put(Dst, 1513, MP_GT);
1938
0
#line 1296 "src/jit/emit_x64.dasc"
1939
0
            break;
1940
0
        case MVM_OP_gt_I:
1941
0
            //| cmp RV, MP_GT
1942
0
            //| sete al;
1943
0
            dasm_put(Dst, 1504, MP_GT);
1944
0
#line 1300 "src/jit/emit_x64.dasc"
1945
0
            break;
1946
0
        case MVM_OP_ge_I:
1947
0
            //| cmp RV, MP_LT
1948
0
            //| setne al;
1949
0
            dasm_put(Dst, 1513, MP_LT);
1950
0
#line 1304 "src/jit/emit_x64.dasc"
1951
0
            break;
1952
0
        }
1953
0
        /* zero extend al (lower byte) to rax (whole register) */
1954
0
        //| movzx rax, al;
1955
0
        //| mov WORK[reg_a], rax;
1956
0
        dasm_put(Dst, 1317, Dt20([reg_a]));
1957
0
#line 1309 "src/jit/emit_x64.dasc"
1958
0
        break;
1959
0
    }
1960
714
    case MVM_OP_isint:
1961
714
    case MVM_OP_isnum:
1962
714
    case MVM_OP_isstr:
1963
714
    case MVM_OP_islist:
1964
714
    case MVM_OP_ishash: {
1965
714
        MVMint16 dst = ins->operands[0].reg.orig;
1966
714
        MVMint16 obj = ins->operands[1].reg.orig;
1967
714
        MVMint32 reprid = op == MVM_OP_isint ? MVM_REPR_ID_P6int :
1968
714
                          op == MVM_OP_isnum ? MVM_REPR_ID_P6num :
1969
714
                          op == MVM_OP_isstr ? MVM_REPR_ID_P6str :
1970
701
                          op == MVM_OP_islist ? MVM_REPR_ID_VMArray :
1971
177
                     /*  op == MVM_OP_ishash */ MVM_REPR_ID_MVMHash;
1972
714
        //| mov TMP1, aword WORK[obj];
1973
714
        //| test TMP1, TMP1;
1974
714
        //| jz >1;
1975
714
        //| mov TMP1, OBJECT:TMP1->st;
1976
714
        //| mov TMP1, STABLE:TMP1->REPR;
1977
714
        //| cmp qword REPR:TMP1->ID, reprid;
1978
714
        //| jne >1;
1979
714
        //| mov qword WORK[dst], 1;
1980
714
        //| jmp >2;
1981
714
        //|1:
1982
714
        //| mov qword WORK[dst], 0;
1983
714
        //|2:
1984
714
        dasm_put(Dst, 1522, Dt20([obj]), DtE(->st), Dt11(->REPR), Dt12(->ID), reprid, Dt20([dst]), Dt20([dst]));
1985
714
#line 1335 "src/jit/emit_x64.dasc"
1986
714
        break;
1987
714
    }
1988
0
    case MVM_OP_sp_boolify_iter_arr: {
1989
0
        MVMint16 dst = ins->operands[0].reg.orig;
1990
0
        MVMint16 obj = ins->operands[1].reg.orig;
1991
0
        //| mov TMP1, aword WORK[obj];
1992
0
        //| mov TMP2, MVMITER:TMP1->body.array_state.index;
1993
0
        //| add TMP2, 1;
1994
0
        //| mov TMP3, MVMITER:TMP1->body.array_state.limit;
1995
0
        dasm_put(Dst, 1575, Dt20([obj]), DtB(->body.array_state.index), DtB(->body.array_state.limit));
1996
0
#line 1344 "src/jit/emit_x64.dasc"
1997
0
        /* index - limit will give a carry flag when index < limit */
1998
0
        //| cmp TMP2, TMP3;
1999
0
        //| setl TMP1b;
2000
0
        //| movzx TMP1, TMP1b;
2001
0
        //| mov aword WORK[dst], TMP1;
2002
0
        dasm_put(Dst, 1592, Dt20([dst]));
2003
0
#line 1349 "src/jit/emit_x64.dasc"
2004
0
        break;
2005
714
    }
2006
0
    case MVM_OP_sp_boolify_iter_hash: {
2007
0
        MVMint16 dst = ins->operands[0].reg.orig;
2008
0
        MVMint16 obj = ins->operands[1].reg.orig;
2009
0
        //| mov TMP1, aword WORK[obj];
2010
0
        //| mov TMP2, MVMITER:TMP1->body.hash_state.next;
2011
0
        //| test TMP2, TMP2;
2012
0
        //| setnz TMP2b;
2013
0
        //| movzx TMP2, TMP2b;
2014
0
        //| mov aword WORK[dst], TMP2;
2015
0
        dasm_put(Dst, 1607, Dt20([obj]), DtB(->body.hash_state.next), Dt20([dst]));
2016
0
#line 1360 "src/jit/emit_x64.dasc"
2017
0
        break;
2018
714
    }
2019
0
    case MVM_OP_objprimspec: {
2020
0
        MVMint16 dst  = ins->operands[0].reg.orig;
2021
0
        MVMint16 type = ins->operands[1].reg.orig;
2022
0
        //| mov TMP6, aword WORK[type];
2023
0
        //| test TMP6, TMP6;
2024
0
        //| jz >1;
2025
0
        //| mov ARG2, OBJECT:TMP6->st;
2026
0
        //| mov FUNCTION, STABLE:ARG2->REPR;
2027
0
        //| mov FUNCTION, REPR:FUNCTION->get_storage_spec;
2028
0
        //| mov ARG1, TC;
2029
0
        //| call FUNCTION;
2030
0
        //| movzx TMP6, word STORAGESPEC:RV->boxed_primitive;
2031
0
        //|1:
2032
0
        //| mov aword WORK[dst], TMP6;
2033
0
        dasm_put(Dst, 1630, Dt20([type]), DtE(->st), Dt11(->REPR), Dt12(->get_storage_spec), Dt16(->boxed_primitive), Dt20([dst]));
2034
0
#line 1376 "src/jit/emit_x64.dasc"
2035
0
        break;
2036
714
    }
2037
0
    case MVM_OP_objprimbits: {
2038
0
        MVMint16 dst  = ins->operands[0].reg.orig;
2039
0
        MVMint16 type = ins->operands[1].reg.orig;
2040
0
        //| mov TMP6, aword WORK[type];
2041
0
        //| test TMP6, TMP6;
2042
0
        //| jz >1;
2043
0
        //| mov ARG2, OBJECT:TMP6->st;
2044
0
        //| mov FUNCTION, STABLE:ARG2->REPR;
2045
0
        //| mov FUNCTION, REPR:FUNCTION->get_storage_spec;
2046
0
        //| mov ARG1, TC;
2047
0
        //| call FUNCTION;
2048
0
        //| movzx TMP6, word STORAGESPEC:RV->boxed_primitive;
2049
0
        //| test TMP6, TMP6;
2050
0
        //| jz >1;
2051
0
        //| movzx TMP6, word STORAGESPEC:RV->bits;
2052
0
        //|1:
2053
0
        //| mov aword WORK[dst], TMP6;
2054
0
        dasm_put(Dst, 1673, Dt20([type]), DtE(->st), Dt11(->REPR), Dt12(->get_storage_spec), Dt16(->boxed_primitive), Dt16(->bits), Dt20([dst]));
2055
0
#line 1395 "src/jit/emit_x64.dasc"
2056
0
        break;
2057
714
    }
2058
623
    case MVM_OP_isnonnull: {
2059
623
        MVMint16 dst = ins->operands[0].reg.orig;
2060
623
        MVMint16 obj = ins->operands[1].reg.orig;
2061
623
        //| mov TMP1, WORK[obj];
2062
623
        //| test TMP1, TMP1;
2063
623
        //| setnz TMP2b;
2064
623
        //| get_vmnull TMP3;
2065
623
        //| cmp TMP1, TMP3;
2066
623
        //| setne TMP3b;
2067
623
        //| and TMP2b, TMP3b;
2068
623
        //| movzx TMP2, TMP2b;
2069
623
        //| mov WORK[dst], TMP2;
2070
623
        dasm_put(Dst, 1728, Dt20([obj]), Dt1F(->instance), DtC(->VMNull), Dt20([dst]));
2071
623
#line 1409 "src/jit/emit_x64.dasc"
2072
623
        break;
2073
714
    }
2074
3.91k
    case MVM_OP_isnull: {
2075
3.91k
        MVMint16 dst = ins->operands[0].reg.orig;
2076
3.91k
        MVMint16 obj = ins->operands[1].reg.orig;
2077
3.91k
        //| mov TMP1, WORK[obj];
2078
3.91k
        //| test TMP1, TMP1;
2079
3.91k
        //| setz TMP2b;
2080
3.91k
        //| get_vmnull TMP3;
2081
3.91k
        //| cmp TMP1, TMP3;
2082
3.91k
        //| sete TMP3b;
2083
3.91k
        //| or TMP2b, TMP3b;
2084
3.91k
        //| movzx TMP2, TMP2b;
2085
3.91k
        //| mov WORK[dst], TMP2;
2086
3.91k
        dasm_put(Dst, 1765, Dt20([obj]), Dt1F(->instance), DtC(->VMNull), Dt20([dst]));
2087
3.91k
#line 1423 "src/jit/emit_x64.dasc"
2088
3.91k
        break;
2089
714
    }
2090
4.69k
    case MVM_OP_sp_fastcreate: {
2091
4.69k
        MVMint16 dst       = ins->operands[0].reg.orig;
2092
4.69k
        MVMuint16 size     = ins->operands[1].lit_i16;
2093
4.69k
        MVMint16 spesh_idx = ins->operands[2].lit_i16;
2094
4.69k
        //| mov ARG1, TC;
2095
4.69k
        //| mov ARG2, size;
2096
4.69k
        //| callp &MVM_gc_allocate_zeroed;
2097
4.69k
        dasm_put(Dst, 1802, size);
2098
4.69k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_allocate_zeroed)), (MVMuint32)((uintptr_t)(&MVM_gc_allocate_zeroed) >> 32));
2099
4.69k
#line 1432 "src/jit/emit_x64.dasc"
2100
4.69k
        //| get_spesh_slot TMP1, spesh_idx;
2101
4.69k
        //| mov aword OBJECT:RV->st, TMP1;  // st is 64 bit (pointer)
2102
4.69k
        //| mov word OBJECT:RV->header.size, size; // object size is 16 bit
2103
4.69k
        //| mov TMP1d, dword TC->thread_id;  // thread id is 32 bit
2104
4.69k
        //| mov dword OBJECT:RV->header.owner, TMP1d; // does this even work?
2105
4.69k
        //| mov aword WORK[dst], RV; // store in local register
2106
4.69k
        dasm_put(Dst, 1812, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]), DtE(->st), DtE(->header.size), size, Dt1F(->thread_id), DtE(->header.owner), Dt20([dst]));
2107
4.69k
#line 1438 "src/jit/emit_x64.dasc"
2108
4.69k
        break;
2109
714
    }
2110
28.3k
    case MVM_OP_decont:
2111
28.3k
    case MVM_OP_sp_decont: {
2112
28.3k
        MVMint16 dst = ins->operands[0].reg.orig;
2113
28.3k
        MVMint16 src = ins->operands[1].reg.orig;
2114
28.3k
        //| mov TMP5, WORK[src];
2115
28.3k
        //| test TMP5, TMP5;
2116
28.3k
        dasm_put(Dst, 1850, Dt20([src]));
2117
28.3k
#line 1446 "src/jit/emit_x64.dasc"
2118
28.3k
        // obj is null
2119
28.3k
        //| jz >1;
2120
28.3k
        //| is_type_object TMP5;
2121
28.3k
        dasm_put(Dst, 1858, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
2122
28.3k
#line 1449 "src/jit/emit_x64.dasc"
2123
28.3k
        // object is type object (not concrete)
2124
28.3k
        //| jnz >1;
2125
28.3k
        //| mov TMP6, OBJECT:TMP5->st;
2126
28.3k
        //| mov TMP6, STABLE:TMP6->container_spec;
2127
28.3k
        //| test TMP6, TMP6;
2128
28.3k
        dasm_put(Dst, 1870, DtE(->st), Dt11(->container_spec));
2129
28.3k
#line 1454 "src/jit/emit_x64.dasc"
2130
28.3k
        // container spec is zero
2131
28.3k
        //| jz >1;
2132
28.3k
        //| mov ARG1, TC;
2133
28.3k
        //| mov ARG2, TMP5;      // object
2134
28.3k
        //| lea ARG3, WORK[dst]; // destination register
2135
28.3k
        //| mov FUNCTION, CONTAINERSPEC:TMP6->fetch; // get function pointer
2136
28.3k
        //| call FUNCTION;
2137
28.3k
        //| jmp >2;
2138
28.3k
        //|1:
2139
28.3k
        dasm_put(Dst, 1886, Dt20([dst]), Dt15(->fetch));
2140
28.3k
#line 1463 "src/jit/emit_x64.dasc"
2141
28.3k
        // otherwise just move the object into the register
2142
28.3k
        //| mov WORK[dst], TMP5;
2143
28.3k
        //|2:
2144
28.3k
        dasm_put(Dst, 1916, Dt20([dst]));
2145
28.3k
#line 1466 "src/jit/emit_x64.dasc"
2146
28.3k
        break;
2147
28.3k
    }
2148
26
    case MVM_OP_iscont: {
2149
26
        MVMint16 dst = ins->operands[0].reg.orig;
2150
26
        MVMint16 obj = ins->operands[1].reg.orig;
2151
26
        //| mov TMP1, aword WORK[obj];
2152
26
        //| test TMP1, TMP1;
2153
26
        //| jz >1;
2154
26
        //| mov TMP1, OBJECT:TMP1->st;
2155
26
        //| mov TMP1, STABLE:TMP1->container_spec;
2156
26
        //| test TMP1, TMP1;
2157
26
        //|1:
2158
26
        //| setnz TMP1b;
2159
26
        //| movzx TMP1, TMP1b;
2160
26
        //| mov qword WORK[dst], TMP1;
2161
26
        dasm_put(Dst, 1923, Dt20([obj]), DtE(->st), Dt11(->container_spec), Dt20([dst]));
2162
26
#line 1481 "src/jit/emit_x64.dasc"
2163
26
        break;
2164
28.3k
    }
2165
7.79k
    case MVM_OP_sp_findmeth: {
2166
7.79k
        MVMint16 dst = ins->operands[0].reg.orig;
2167
7.79k
        MVMint16 obj = ins->operands[1].reg.orig;
2168
7.79k
        MVMint32 str_idx = ins->operands[2].lit_str_idx;
2169
7.79k
        MVMuint16 ss_idx = ins->operands[3].lit_i16;
2170
7.79k
        //| get_spesh_slot TMP1, ss_idx;
2171
7.79k
        //| mov TMP2, WORK[obj];
2172
7.79k
        //| mov TMP2, OBJECT:TMP2->st;
2173
7.79k
        //| cmp TMP1, TMP2;
2174
7.79k
        //| jne >1;
2175
7.79k
        //| get_spesh_slot TMP3, ss_idx + 1;
2176
7.79k
        //| mov WORK[dst], TMP3;
2177
7.79k
        //| jmp >2;
2178
7.79k
        //|1:
2179
7.79k
        dasm_put(Dst, 1959, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([ss_idx]), Dt20([obj]), DtE(->st), Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([ss_idx + 1]), Dt20([dst]));
2180
7.79k
#line 1497 "src/jit/emit_x64.dasc"
2181
7.79k
        /* assign invokish label first */
2182
7.79k
        //| mov rax, TC->cur_frame;
2183
7.79k
        //| lea TMP6, [>2];
2184
7.79k
        //| mov aword FRAME:rax->jit_entry_label, TMP6;
2185
7.79k
        dasm_put(Dst, 2009, Dt1F(->cur_frame), Dt2(->jit_entry_label));
2186
7.79k
#line 1501 "src/jit/emit_x64.dasc"
2187
7.79k
        /* call find_method_spesh */
2188
7.79k
        //| mov ARG1, TC;
2189
7.79k
        //| mov ARG2, WORK[obj];
2190
7.79k
        //| get_string ARG3, str_idx;
2191
7.79k
        dasm_put(Dst, 2023, Dt20([obj]));
2192
7.79k
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, str_idx);
2193
7.79k
#line 1505 "src/jit/emit_x64.dasc"
2194
7.79k
        //| mov ARG4, ss_idx;
2195
7.79k
        //| lea TMP6, WORK[dst];
2196
7.79k
        //|.if WIN32;
2197
7.79k
        //| mov qword [rsp+0x20], TMP6;
2198
7.79k
        //|.else;
2199
7.79k
        //| mov ARG5, TMP6;
2200
7.79k
        //|.endif
2201
7.79k
        //| callp &MVM_6model_find_method_spesh;
2202
7.79k
        dasm_put(Dst, 2032, Dt21(->body.strings), Dt13([str_idx]), ss_idx, Dt20([dst]));
2203
7.79k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_6model_find_method_spesh)), (MVMuint32)((uintptr_t)(&MVM_6model_find_method_spesh) >> 32));
2204
7.79k
#line 1513 "src/jit/emit_x64.dasc"
2205
7.79k
        //| test RV, RV;
2206
7.79k
        dasm_put(Dst, 2053);
2207
7.79k
#line 1514 "src/jit/emit_x64.dasc"
2208
7.79k
        /* fall out to interpreter */
2209
7.79k
        //| jnz ->out;
2210
7.79k
        //|2:
2211
7.79k
        dasm_put(Dst, 2062);
2212
7.79k
#line 1517 "src/jit/emit_x64.dasc"
2213
7.79k
        break;
2214
28.3k
    }
2215
3.09k
    case MVM_OP_isconcrete: {
2216
3.09k
        MVMint16 dst = ins->operands[0].reg.orig;
2217
3.09k
        MVMint16 obj = ins->operands[1].reg.orig;
2218
3.09k
        //| mov TMP1, WORK[obj];
2219
3.09k
        //| test TMP1, TMP1;
2220
3.09k
        //| jz >1;
2221
3.09k
        //| is_type_object TMP1;
2222
3.09k
        //| jnz >1;
2223
3.09k
        //| mov qword WORK[dst], 1;
2224
3.09k
        //| jmp >2;
2225
3.09k
        //|1:
2226
3.09k
        //| mov qword WORK[dst], 0;
2227
3.09k
        //|2:
2228
3.09k
        dasm_put(Dst, 2069, Dt20([obj]), DtE(->header.flags), MVM_CF_TYPE_OBJECT, Dt20([dst]), Dt20([dst]));
2229
3.09k
#line 1532 "src/jit/emit_x64.dasc"
2230
3.09k
        break;
2231
28.3k
    }
2232
6
    case MVM_OP_takehandlerresult: {
2233
6
        MVMint16 dst = ins->operands[0].reg.orig;
2234
6
        //| mov TMP1, aword TC->last_handler_result;
2235
6
        //| mov aword WORK[dst], TMP1;
2236
6
        //| mov aword TC->last_handler_result, 0;
2237
6
        dasm_put(Dst, 2115, Dt1F(->last_handler_result), Dt20([dst]), Dt1F(->last_handler_result));
2238
6
#line 1539 "src/jit/emit_x64.dasc"
2239
6
        break;
2240
28.3k
    }
2241
0
    case MVM_OP_exception: {
2242
0
        MVMint16 dst = ins->operands[0].reg.orig;
2243
0
        //| mov TMP1, TC->active_handlers;
2244
0
        //| test TMP1, TMP1;
2245
0
        //| jz >1;
2246
0
        //| mov TMP1, MVMACTIVEHANDLERS:TMP1->ex_obj;
2247
0
        //| mov WORK[dst], TMP1;
2248
0
        //| jmp >2;
2249
0
        //|1:
2250
0
        //| get_vmnull TMP1;
2251
0
        //| mov WORK[dst], TMP1;
2252
0
        //|2:
2253
0
        dasm_put(Dst, 2132, Dt1F(->active_handlers), DtD(->ex_obj), Dt20([dst]), Dt1F(->instance), DtC(->VMNull), Dt20([dst]));
2254
0
#line 1553 "src/jit/emit_x64.dasc"
2255
0
        break;
2256
28.3k
    }
2257
600
    case MVM_OP_scwbdisable: {
2258
600
        MVMint16 dst = ins->operands[0].reg.orig;
2259
600
        //| mov TMP1d, dword TC->sc_wb_disable_depth;
2260
600
        //| add TMP1d, 1;
2261
600
        //| mov dword TC->sc_wb_disable_depth, TMP1d;
2262
600
        //| mov qword WORK[dst], TMP1;
2263
600
        dasm_put(Dst, 2172, Dt1F(->sc_wb_disable_depth), Dt1F(->sc_wb_disable_depth), Dt20([dst]));
2264
600
#line 1561 "src/jit/emit_x64.dasc"
2265
600
        break;
2266
28.3k
    }
2267
600
    case MVM_OP_scwbenable: {
2268
600
        MVMint16 dst = ins->operands[0].reg.orig;
2269
600
        //| mov TMP1d, dword TC->sc_wb_disable_depth; // should do zero-extension
2270
600
        //| sub TMP1d, 1;
2271
600
        //| mov dword TC->sc_wb_disable_depth, TMP1d;
2272
600
        //| mov qword WORK[dst], TMP1;
2273
600
        dasm_put(Dst, 2188, Dt1F(->sc_wb_disable_depth), Dt1F(->sc_wb_disable_depth), Dt20([dst]));
2274
600
#line 1569 "src/jit/emit_x64.dasc"
2275
600
        break;
2276
28.3k
    }
2277
0
    case MVM_OP_assign:
2278
0
    case MVM_OP_assignunchecked: {
2279
0
        MVMint16 cont = ins->operands[0].reg.orig;
2280
0
        MVMint16 obj  = ins->operands[1].reg.orig;
2281
0
        //| mov ARG2, aword WORK[cont];
2282
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2283
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2284
0
        //| test FUNCTION, FUNCTION;
2285
0
        //| jnz >1;
2286
0
        //| throw_adhoc "Cannot assign to an immutable value";
2287
0
        dasm_put(Dst, 2205, Dt20([cont]), DtE(->st), Dt11(->container_spec), (unsigned int)((uintptr_t)("Cannot assign to an immutable value")), (unsigned int)(((uintptr_t)("Cannot assign to an immutable value"))>>32));
2288
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2289
0
#line 1581 "src/jit/emit_x64.dasc"
2290
0
        //|1:
2291
0
        //| mov ARG1, TC;
2292
0
        //| mov ARG3, aword WORK[obj];
2293
0
        dasm_put(Dst, 2234, Dt20([obj]));
2294
0
#line 1584 "src/jit/emit_x64.dasc"
2295
0
        if (op == MVM_OP_assign) {
2296
0
            //| mov FUNCTION, CONTAINERSPEC:FUNCTION->store;
2297
0
            dasm_put(Dst, 180, Dt15(->store));
2298
0
#line 1586 "src/jit/emit_x64.dasc"
2299
0
        } else {
2300
0
            //| mov FUNCTION, CONTAINERSPEC:FUNCTION->store_unchecked;
2301
0
            dasm_put(Dst, 180, Dt15(->store_unchecked));
2302
0
#line 1588 "src/jit/emit_x64.dasc"
2303
0
        }
2304
0
        //| call FUNCTION;
2305
0
        dasm_put(Dst, 2250);
2306
0
#line 1590 "src/jit/emit_x64.dasc"
2307
0
        break;
2308
0
    }
2309
1.64k
    case MVM_OP_getlexstatic_o:
2310
1.64k
    case MVM_OP_getlexperinvtype_o: {
2311
1.64k
        MVMint16 dst  = ins->operands[0].reg.orig;
2312
1.64k
        MVMint16 name = ins->operands[1].reg.orig;
2313
1.64k
        //| mov ARG1, TC;
2314
1.64k
        //| mov ARG2, aword WORK[name];
2315
1.64k
        //| mov ARG3, MVM_reg_obj;
2316
1.64k
        //| callp &MVM_frame_find_lexical_by_name;
2317
1.64k
        dasm_put(Dst, 2255, Dt20([name]), MVM_reg_obj);
2318
1.64k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name)), (MVMuint32)((uintptr_t)(&MVM_frame_find_lexical_by_name) >> 32));
2319
1.64k
#line 1600 "src/jit/emit_x64.dasc"
2320
1.64k
        //| test RV, RV;
2321
1.64k
        //| jz >1;
2322
1.64k
        //| mov RV, [RV];
2323
1.64k
        //|1:
2324
1.64k
        //| mov WORK[dst], RV;
2325
1.64k
        dasm_put(Dst, 257, Dt20([dst]));
2326
1.64k
#line 1605 "src/jit/emit_x64.dasc"
2327
1.64k
        break;
2328
1.64k
    }
2329
130
    case MVM_OP_paramnamesused:
2330
130
        //| mov ARG2, TC->cur_frame;
2331
130
        //| lea ARG2, FRAME:ARG2->params;
2332
130
        //| mov TMP5w, word ARGCTX:ARG2->num_pos;
2333
130
        //| cmp TMP5w, word ARGCTX:ARG2->arg_count;
2334
130
        //| je >1;
2335
130
        //| mov ARG1, TC;
2336
130
        //| callp &MVM_args_assert_nameds_used;
2337
130
        dasm_put(Dst, 2269, Dt1F(->cur_frame), Dt2(->params), Dt3(->num_pos), Dt3(->arg_count));
2338
130
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_args_assert_nameds_used)), (MVMuint32)((uintptr_t)(&MVM_args_assert_nameds_used) >> 32));
2339
130
#line 1615 "src/jit/emit_x64.dasc"
2340
130
        //|1:
2341
130
        dasm_put(Dst, 1066);
2342
130
#line 1616 "src/jit/emit_x64.dasc"
2343
130
        break;
2344
0
    case MVM_OP_assertparamcheck: {
2345
0
        MVMint16 ok = ins->operands[0].reg.orig;
2346
0
        //| mov TMP1, qword WORK[ok];
2347
0
        //| test TMP1, TMP1;
2348
0
        //| jnz >1;
2349
0
        //| mov ARG1, TC;
2350
0
        //| callp &MVM_args_bind_failed;
2351
0
        dasm_put(Dst, 2297, Dt20([ok]));
2352
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_args_bind_failed)), (MVMuint32)((uintptr_t)(&MVM_args_bind_failed) >> 32));
2353
0
#line 1624 "src/jit/emit_x64.dasc"
2354
0
        //|1:
2355
0
        dasm_put(Dst, 1066);
2356
0
#line 1625 "src/jit/emit_x64.dasc"
2357
0
        break;
2358
1.64k
    }
2359
0
    case MVM_OP_prof_enterspesh:
2360
0
        //| mov ARG1, TC;
2361
0
        //| mov ARG2, TC->cur_frame;
2362
0
        //| mov ARG2, aword FRAME:ARG2->static_info;
2363
0
        //| mov ARG3, aword MVM_PROFILE_ENTER_JIT;
2364
0
        //| callp &MVM_profile_log_enter;
2365
0
        dasm_put(Dst, 2314, Dt1F(->cur_frame), Dt2(->static_info), MVM_PROFILE_ENTER_JIT);
2366
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_profile_log_enter)), (MVMuint32)((uintptr_t)(&MVM_profile_log_enter) >> 32));
2367
0
        dasm_put(Dst, 212);
2368
0
#line 1633 "src/jit/emit_x64.dasc"
2369
0
        break;
2370
0
    case MVM_OP_prof_enterinline: {
2371
0
        MVMint16 spesh_idx = ins->operands[0].lit_i16;
2372
0
        //| mov ARG1, TC;
2373
0
        //| get_spesh_slot ARG2, spesh_idx;
2374
0
        //| mov ARG3, aword MVM_PROFILE_ENTER_JIT_INLINE;
2375
0
        //| callp &MVM_profile_log_enter;
2376
0
        dasm_put(Dst, 2332, Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]), MVM_PROFILE_ENTER_JIT_INLINE);
2377
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_profile_log_enter)), (MVMuint32)((uintptr_t)(&MVM_profile_log_enter) >> 32));
2378
0
        dasm_put(Dst, 212);
2379
0
#line 1640 "src/jit/emit_x64.dasc"
2380
0
        break;
2381
1.64k
    }
2382
5
    case MVM_OP_getobjsc: {
2383
5
        MVMint16 dst = ins->operands[0].reg.orig;
2384
5
        MVMint16 obj = ins->operands[1].reg.orig;
2385
5
        //| mov TMP1, aword WORK[obj];
2386
5
        //| mov TMP2d, dword COLLECTABLE:TMP1->sc_forward_u.sc.sc_idx;
2387
5
        //| xor TMP3, TMP3;
2388
5
        //| cmp TMP2d, 0;
2389
5
        //| jle >1;
2390
5
        //| mov TMP3, aword TC->instance;
2391
5
        //| mov TMP3, aword MVMINSTANCE:TMP3->all_scs;
2392
5
        //| mov TMP3, aword [TMP3 + TMP2d * 8];
2393
5
        //| mov TMP3, SCREFBODY:TMP3->sc;
2394
5
        //|1:
2395
5
        //| mov aword WORK[dst], TMP3;
2396
5
        dasm_put(Dst, 2354, Dt20([obj]), Dt10(->sc_forward_u.sc.sc_idx), Dt1F(->instance), DtC(->all_scs), Dt18(->sc), Dt20([dst]));
2397
5
#line 1656 "src/jit/emit_x64.dasc"
2398
5
        break;
2399
1.64k
    }
2400
0
    case MVM_OP_invokewithcapture: {
2401
0
        MVMint16 dest    = ins->operands[0].reg.orig;
2402
0
        MVMint16 code    = ins->operands[1].reg.orig;
2403
0
        MVMint16 capture = ins->operands[2].reg.orig;
2404
0
        //| mov TMP1, aword WORK[capture];
2405
0
        dasm_put(Dst, 1185, Dt20([capture]));
2406
0
#line 1663 "src/jit/emit_x64.dasc"
2407
0
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2408
0
        //| is_type_object TMP1;
2409
0
        //| jnz >1;
2410
0
        //| mov TMP2, OBJECT:TMP1->st;
2411
0
        //| mov TMP2, STABLE:TMP2->REPR;
2412
0
        //| cmp dword REPR:TMP2->ID, MVM_REPR_ID_MVMCallCapture;
2413
0
        //| je >2;
2414
0
        //|1:
2415
0
        dasm_put(Dst, 2395, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt11(->REPR), Dt12(->ID), MVM_REPR_ID_MVMCallCapture);
2416
0
#line 1671 "src/jit/emit_x64.dasc"
2417
0
        /* else throw */
2418
0
        //| throw_adhoc "invokewithcapture needs a MVMCallCapture";
2419
0
        dasm_put(Dst, 1056, (unsigned int)((uintptr_t)("invokewithcapture needs a MVMCallCapture")), (unsigned int)(((uintptr_t)("invokewithcapture needs a MVMCallCapture"))>>32));
2420
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2421
0
#line 1673 "src/jit/emit_x64.dasc"
2422
0
        //|2:
2423
0
        dasm_put(Dst, 334);
2424
0
#line 1674 "src/jit/emit_x64.dasc"
2425
0
        /* code = MVM_frame_find_invokee(tc, code, NULL) */
2426
0
        //| mov ARG1, TC;
2427
0
        //| mov ARG2, WORK[code];
2428
0
        //| xor ARG3, ARG3;
2429
0
        //| callp &MVM_frame_find_invokee;
2430
0
        dasm_put(Dst, 2424, Dt20([code]));
2431
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee)), (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee) >> 32));
2432
0
        dasm_put(Dst, 212);
2433
0
#line 1679 "src/jit/emit_x64.dasc"
2434
0
2435
0
        //| mov ARG2, RV; // ARG2 = code
2436
0
        dasm_put(Dst, 2437);
2437
0
#line 1681 "src/jit/emit_x64.dasc"
2438
0
        /* tc->cur_frame->return_value = &GET_REG(cur_op, 2) */
2439
0
        //| lea ARG1, WORK[dest]; // ARG1 is used as scratch space
2440
0
        //| mov TMP6, aword TC->cur_frame;
2441
0
        //| mov aword FRAME:TMP6->return_value, ARG1;
2442
0
        dasm_put(Dst, 2441, Dt20([dest]), Dt1F(->cur_frame), Dt2(->return_value));
2443
0
#line 1685 "src/jit/emit_x64.dasc"
2444
0
        /* tc->cur_frame->return_type = MVM_RETURN_OBJ */
2445
0
        //| mov byte FRAME:TMP6->return_type, MVM_RETURN_OBJ;
2446
0
        dasm_put(Dst, 2454, Dt2(->return_type), MVM_RETURN_OBJ);
2447
0
#line 1687 "src/jit/emit_x64.dasc"
2448
0
        /* tc->cur_frame->return_address = cur_op */
2449
0
        //| get_cur_op ARG1;
2450
0
        //| mov aword FRAME:TMP6->return_address, ARG1;
2451
0
        dasm_put(Dst, 2460, Dt1F(->interp_cur_op), Dt2(->return_address));
2452
0
#line 1690 "src/jit/emit_x64.dasc"
2453
0
        /* STABLE(code)->invoke(tc, code, capture->body.apc->effective_callsite,
2454
0
           capture->body.apc->arg) */
2455
0
        //| mov ARG1, TC;
2456
0
        //| mov ARG3, WORK[capture];
2457
0
        //| mov ARG4, aword CAPTURE:ARG3->body.apc;
2458
0
        //| mov ARG3, aword ARGCTX:ARG4->callsite;
2459
0
        //| mov ARG4, aword ARGCTX:ARG4->args;
2460
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2461
0
        //| mov FUNCTION, STABLE:FUNCTION->invoke;
2462
0
        //| call FUNCTION;
2463
0
        dasm_put(Dst, 2472, Dt20([capture]), Dt5(->body.apc), Dt3(->callsite), Dt3(->args), DtE(->st), Dt11(->invoke));
2464
0
#line 1700 "src/jit/emit_x64.dasc"
2465
0
        /* jumping out is handled by invokish */
2466
0
        break;
2467
1.64k
    }
2468
0
    case MVM_OP_captureposelems: {
2469
0
        MVMint16 dest    = ins->operands[0].reg.orig;
2470
0
        MVMint16 capture = ins->operands[1].reg.orig;
2471
0
        //| mov TMP1, aword WORK[capture];
2472
0
        dasm_put(Dst, 1185, Dt20([capture]));
2473
0
#line 1707 "src/jit/emit_x64.dasc"
2474
0
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2475
0
        //| is_type_object TMP1;
2476
0
        //| jnz >1;
2477
0
        //| mov TMP2, OBJECT:TMP1->st;
2478
0
        //| mov TMP2, STABLE:TMP2->REPR;
2479
0
        //| cmp dword REPR:TMP2->ID, MVM_REPR_ID_MVMCallCapture;
2480
0
        //| je >2;
2481
0
        //|1:
2482
0
        dasm_put(Dst, 2395, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt11(->REPR), Dt12(->ID), MVM_REPR_ID_MVMCallCapture);
2483
0
#line 1715 "src/jit/emit_x64.dasc"
2484
0
        /* else throw */
2485
0
        //| throw_adhoc "captureposelems needs a concrete MVMCallCapture";
2486
0
        dasm_put(Dst, 1056, (unsigned int)((uintptr_t)("captureposelems needs a concrete MVMCallCapture")), (unsigned int)(((uintptr_t)("captureposelems needs a concrete MVMCallCapture"))>>32));
2487
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2488
0
#line 1717 "src/jit/emit_x64.dasc"
2489
0
        //|2:
2490
0
        //| mov TMP2, aword CAPTURE:TMP1->body.apc;
2491
0
        //| movzx TMP2, word ARGPROCCONTEXT:TMP2->num_pos;
2492
0
        //| mov WORK[dest], TMP2;
2493
0
        dasm_put(Dst, 2505, Dt5(->body.apc), Dt7(->num_pos), Dt20([dest]));
2494
0
#line 1721 "src/jit/emit_x64.dasc"
2495
0
        break;
2496
1.64k
    }
2497
0
    case MVM_OP_capturehasnameds: {
2498
0
        MVMint16 dest    = ins->operands[0].reg.orig;
2499
0
        MVMint16 capture = ins->operands[1].reg.orig;
2500
0
        //| mov TMP1, aword WORK[capture];
2501
0
        dasm_put(Dst, 1185, Dt20([capture]));
2502
0
#line 1727 "src/jit/emit_x64.dasc"
2503
0
        /* if (IS_CONCRETE(capture) && REPR(capture)->ID == MVM_REPR_ID_MVMCallCapture) */
2504
0
        //| is_type_object TMP1;
2505
0
        //| jnz >1;
2506
0
        //| mov TMP2, OBJECT:TMP1->st;
2507
0
        //| mov TMP2, STABLE:TMP2->REPR;
2508
0
        //| cmp dword REPR:TMP2->ID, MVM_REPR_ID_MVMCallCapture;
2509
0
        //| je >2;
2510
0
        //|1:
2511
0
        dasm_put(Dst, 2395, DtE(->header.flags), MVM_CF_TYPE_OBJECT, DtE(->st), Dt11(->REPR), Dt12(->ID), MVM_REPR_ID_MVMCallCapture);
2512
0
#line 1735 "src/jit/emit_x64.dasc"
2513
0
        /* else throw */
2514
0
        //| throw_adhoc "capturehasnameds needs a concrete MVMCallCapture";
2515
0
        dasm_put(Dst, 1056, (unsigned int)((uintptr_t)("capturehasnameds needs a concrete MVMCallCapture")), (unsigned int)(((uintptr_t)("capturehasnameds needs a concrete MVMCallCapture"))>>32));
2516
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2517
0
#line 1737 "src/jit/emit_x64.dasc"
2518
0
        //|2:
2519
0
        //| mov TMP2, CAPTURE:TMP1->body.apc;
2520
0
        //| mov TMP3w, word ARGPROCCONTEXT:TMP2->num_pos;
2521
0
        //| mov TMP2w, word ARGPROCCONTEXT:TMP2->arg_count;
2522
0
        //| cmp TMP2w, TMP3w;
2523
0
        //| setne al;
2524
0
        //| movzx rax, al;
2525
0
        //| mov WORK[dest], rax;
2526
0
        dasm_put(Dst, 2526, Dt5(->body.apc), Dt7(->num_pos), Dt7(->arg_count), Dt20([dest]));
2527
0
#line 1745 "src/jit/emit_x64.dasc"
2528
0
        break;
2529
1.64k
    }
2530
0
    case MVM_OP_getstdin:
2531
0
    case MVM_OP_getstdout:
2532
0
    case MVM_OP_getstderr: {
2533
0
        MVMint16 dst = ins->operands[0].reg.orig;
2534
0
        //| mov TMP3, aword TC->instance;
2535
0
        dasm_put(Dst, 2562, Dt1F(->instance));
2536
0
#line 1752 "src/jit/emit_x64.dasc"
2537
0
        if (ins->info->opcode == MVM_OP_getstdin) {
2538
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stdin_handle;
2539
0
            dasm_put(Dst, 426, DtC(->stdin_handle));
2540
0
#line 1754 "src/jit/emit_x64.dasc"
2541
0
        } else if (ins->info->opcode == MVM_OP_getstdout) {
2542
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stdout_handle;
2543
0
            dasm_put(Dst, 426, DtC(->stdout_handle));
2544
0
#line 1756 "src/jit/emit_x64.dasc"
2545
0
        } else if (ins->info->opcode == MVM_OP_getstderr) {
2546
0
            //| mov TMP3, aword MVMINSTANCE:TMP3->stderr_handle;
2547
0
            dasm_put(Dst, 426, DtC(->stderr_handle));
2548
0
#line 1758 "src/jit/emit_x64.dasc"
2549
0
        }
2550
0
        //| mov aword WORK[dst], TMP3;
2551
0
        dasm_put(Dst, 556, Dt20([dst]));
2552
0
#line 1760 "src/jit/emit_x64.dasc"
2553
0
        break;
2554
0
    }
2555
1.03k
    case MVM_OP_ordat:
2556
1.03k
    case MVM_OP_ordfirst: {
2557
1.03k
        MVMint16 dst = ins->operands[0].reg.orig;
2558
1.03k
        MVMint16 str = ins->operands[1].reg.orig;
2559
1.03k
        //| mov ARG1, TC;
2560
1.03k
        //| mov ARG2, aword WORK[str];
2561
1.03k
        dasm_put(Dst, 2023, Dt20([str]));
2562
1.03k
#line 1768 "src/jit/emit_x64.dasc"
2563
1.03k
        if (op == MVM_OP_ordat) {
2564
159
            MVMint16 idx = ins->operands[2].reg.orig;
2565
159
            //| mov ARG3, qword WORK[idx];
2566
159
            dasm_put(Dst, 565, Dt20([idx]));
2567
159
#line 1771 "src/jit/emit_x64.dasc"
2568
875
        } else {
2569
875
            //| mov ARG3, 0;
2570
875
            dasm_put(Dst, 1374);
2571
875
#line 1773 "src/jit/emit_x64.dasc"
2572
875
        }
2573
1.03k
        //| callp &MVM_string_ord_at;
2574
1.03k
        dasm_put(Dst, 204);
2575
1.03k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_string_ord_at)), (MVMuint32)((uintptr_t)(&MVM_string_ord_at) >> 32));
2576
1.03k
#line 1775 "src/jit/emit_x64.dasc"
2577
1.03k
        //| mov qword WORK[dst], RV;
2578
1.03k
        dasm_put(Dst, 2567, Dt20([dst]));
2579
1.03k
#line 1776 "src/jit/emit_x64.dasc"
2580
1.03k
        break;
2581
1.03k
    }
2582
0
    case MVM_OP_setcodeobj: {
2583
0
        MVMint16 obj  = ins->operands[0].reg.orig;
2584
0
        MVMint16 code = ins->operands[1].reg.orig;
2585
0
        //| mov TMP1, aword WORK[obj];
2586
0
        dasm_put(Dst, 1185, Dt20([obj]));
2587
0
#line 1782 "src/jit/emit_x64.dasc"
2588
0
        /* if (REPR(obj)->ID == MVM_REPR_ID_MVMCode) */
2589
0
        //| mov TMP2, OBJECT:TMP1->st;
2590
0
        //| mov TMP2, STABLE:TMP2->REPR;
2591
0
        //| cmp dword REPR:TMP2->ID, MVM_REPR_ID_MVMCode;
2592
0
        //| je >1;
2593
0
        dasm_put(Dst, 2577, DtE(->st), Dt11(->REPR), Dt12(->ID), MVM_REPR_ID_MVMCode);
2594
0
#line 1787 "src/jit/emit_x64.dasc"
2595
0
        /* else throw */
2596
0
        //| throw_adhoc "setcodeobj needs a code ref";
2597
0
        dasm_put(Dst, 1056, (unsigned int)((uintptr_t)("setcodeobj needs a code ref")), (unsigned int)(((uintptr_t)("setcodeobj needs a code ref"))>>32));
2598
0
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc)), (MVMuint32)((uintptr_t)(&MVM_exception_throw_adhoc) >> 32));
2599
0
#line 1789 "src/jit/emit_x64.dasc"
2600
0
        //|1:
2601
0
        //| mov TMP2, aword WORK[code];
2602
0
        //| mov aword CODE:TMP1->body.code_object, TMP2;
2603
0
        dasm_put(Dst, 2594, Dt20([code]), Dt1A(->body.code_object));
2604
0
#line 1792 "src/jit/emit_x64.dasc"
2605
0
        break;
2606
1.03k
    }
2607
0
    case MVM_OP_lastexpayload: {
2608
0
        MVMint16 dst = ins->operands[0].reg.orig;
2609
0
        //| mov TMP3, aword TC->last_payload;
2610
0
        //| mov aword WORK[dst], TMP3;
2611
0
        dasm_put(Dst, 2610, Dt1F(->last_payload), Dt20([dst]));
2612
0
#line 1798 "src/jit/emit_x64.dasc"
2613
0
        break;
2614
1.03k
    }
2615
114
    case MVM_OP_param_sp: {
2616
114
        MVMuint16 dst = ins->operands[0].reg.orig;
2617
114
        MVMuint16 off = ins->operands[1].lit_ui16;
2618
114
        //| mov ARG1, TC
2619
114
        //| mov ARG2, TC:ARG1->cur_frame
2620
114
        //| lea ARG2, FRAME:ARG2->params
2621
114
        //| mov ARG3, off
2622
114
        //| callp &MVM_args_slurpy_positional;
2623
114
        dasm_put(Dst, 2619, Dt1F(->cur_frame), Dt2(->params), off);
2624
114
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_args_slurpy_positional)), (MVMuint32)((uintptr_t)(&MVM_args_slurpy_positional) >> 32));
2625
114
#line 1808 "src/jit/emit_x64.dasc"
2626
114
        //| mov qword WORK[dst], RV;
2627
114
        dasm_put(Dst, 2567, Dt20([dst]));
2628
114
#line 1809 "src/jit/emit_x64.dasc"
2629
114
        break;
2630
1.03k
    }
2631
100
    case MVM_OP_param_sn: {
2632
100
        MVMuint16 dst = ins->operands[0].reg.orig;
2633
100
        //| mov ARG1, TC
2634
100
        //| mov ARG2, TC:ARG1->cur_frame
2635
100
        //| lea ARG2, FRAME:ARG2->params
2636
100
        //| callp &MVM_args_slurpy_named;
2637
100
        dasm_put(Dst, 2637, Dt1F(->cur_frame), Dt2(->params));
2638
100
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_args_slurpy_named)), (MVMuint32)((uintptr_t)(&MVM_args_slurpy_named) >> 32));
2639
100
#line 1817 "src/jit/emit_x64.dasc"
2640
100
        //| mov qword WORK[dst], RV;
2641
100
        dasm_put(Dst, 2567, Dt20([dst]));
2642
100
#line 1818 "src/jit/emit_x64.dasc"
2643
100
        break;
2644
1.03k
    }
2645
0
    case MVM_OP_sp_cas_o: {
2646
0
        MVMint16 target = ins->operands[1].reg.orig;
2647
0
        MVMint16 expected = ins->operands[2].reg.orig;
2648
0
        MVMint16 value = ins->operands[3].reg.orig;
2649
0
        MVMint16 result = ins->operands[0].reg.orig;
2650
0
        //| mov ARG1, TC;
2651
0
        //| mov ARG2, aword WORK[target];
2652
0
        //| mov ARG3, aword WORK[expected];
2653
0
        //| mov ARG4, aword WORK[value];
2654
0
        //|.if WIN32;
2655
0
        //| lea TMP6, WORK[result]
2656
0
        //| mov qword [rsp+0x20], TMP6
2657
0
        //|.else;
2658
0
        //| lea ARG5, WORK[result]
2659
0
        //|.endif
2660
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2661
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2662
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->cas;
2663
0
        //| call FUNCTION;
2664
0
        dasm_put(Dst, 2651, Dt20([target]), Dt20([expected]), Dt20([value]), Dt20([result]), DtE(->st), Dt11(->container_spec), Dt15(->cas));
2665
0
#line 1839 "src/jit/emit_x64.dasc"
2666
0
        break;
2667
1.03k
    }
2668
0
    case MVM_OP_sp_atomicload_o: {
2669
0
        MVMint16 target = ins->operands[1].reg.orig;
2670
0
        MVMint16 result = ins->operands[0].reg.orig;
2671
0
        //| mov ARG1, TC;
2672
0
        //| mov ARG2, aword WORK[target];
2673
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2674
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2675
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->atomic_load;
2676
0
        //| call FUNCTION;
2677
0
        //| mov WORK[result], RV
2678
0
        dasm_put(Dst, 2688, Dt20([target]), DtE(->st), Dt11(->container_spec), Dt15(->atomic_load), Dt20([result]));
2679
0
#line 1851 "src/jit/emit_x64.dasc"
2680
0
        break;
2681
1.03k
    }
2682
0
    case MVM_OP_sp_atomicstore_o: {
2683
0
        MVMint16 target = ins->operands[0].reg.orig;
2684
0
        MVMint16 value = ins->operands[1].reg.orig;
2685
0
        //| mov ARG1, TC;
2686
0
        //| mov ARG2, aword WORK[target];
2687
0
        //| mov ARG3, aword WORK[value];
2688
0
        //| mov FUNCTION, OBJECT:ARG2->st;
2689
0
        //| mov FUNCTION, STABLE:FUNCTION->container_spec;
2690
0
        //| mov FUNCTION, CONTAINERSPEC:FUNCTION->atomic_store;
2691
0
        //| call FUNCTION;
2692
0
        dasm_put(Dst, 2717, Dt20([target]), Dt20([value]), DtE(->st), Dt11(->container_spec), Dt15(->atomic_store));
2693
0
#line 1863 "src/jit/emit_x64.dasc"
2694
0
        break;
2695
1.03k
    }
2696
0
    default:
2697
0
        MVM_panic(1, "Can't JIT opcode <%s>", ins->info->name);
2698
413k
    }
2699
413k
}
2700
2701
2702
2703
/* Call argument decoder */
2704
static void load_call_arg(MVMThreadContext *tc, MVMJitGraph *jg,
2705
645k
                          MVMJitCallArg arg, dasm_State **Dst) {
2706
645k
    switch(arg.type) {
2707
202k
    case MVM_JIT_INTERP_VAR:
2708
202k
        switch (arg.v.ivar) {
2709
168k
        case MVM_JIT_INTERP_TC:
2710
168k
            //| mov TMP6, TC;
2711
168k
            dasm_put(Dst, 2746);
2712
168k
#line 1880 "src/jit/emit_x64.dasc"
2713
168k
            break;
2714
32.3k
        case MVM_JIT_INTERP_CU:
2715
32.3k
            //| mov TMP6, CU;
2716
32.3k
            dasm_put(Dst, 2751);
2717
32.3k
#line 1883 "src/jit/emit_x64.dasc"
2718
32.3k
            break;
2719
0
        case MVM_JIT_INTERP_FRAME:
2720
0
            //| mov TMP6, TC->cur_frame;
2721
0
            dasm_put(Dst, 165, Dt1F(->cur_frame));
2722
0
#line 1886 "src/jit/emit_x64.dasc"
2723
0
            break;
2724
561
        case MVM_JIT_INTERP_PARAMS:
2725
561
            //| mov TMP6, TC->cur_frame;
2726
561
            //| lea TMP6, FRAME:TMP6->params;
2727
561
            dasm_put(Dst, 2756, Dt1F(->cur_frame), Dt2(->params));
2728
561
#line 1890 "src/jit/emit_x64.dasc"
2729
561
            break;
2730
808
        case MVM_JIT_INTERP_CALLER:
2731
808
            //| mov TMP6, TC->cur_frame;
2732
808
            //| mov TMP6, aword FRAME:TMP6->caller;
2733
808
            dasm_put(Dst, 2765, Dt1F(->cur_frame), Dt2(->caller));
2734
808
#line 1894 "src/jit/emit_x64.dasc"
2735
808
            break;
2736
202k
        }
2737
202k
        break;
2738
206k
    case MVM_JIT_REG_VAL:
2739
206k
        //| mov TMP6, qword WORK[arg.v.reg];
2740
206k
        dasm_put(Dst, 2774, Dt20([arg.v.reg]));
2741
206k
#line 1899 "src/jit/emit_x64.dasc"
2742
206k
        break;
2743
277
    case MVM_JIT_REG_VAL_F:
2744
277
        //| mov TMP6, qword WORK[arg.v.reg];
2745
277
        dasm_put(Dst, 2774, Dt20([arg.v.reg]));
2746
277
#line 1902 "src/jit/emit_x64.dasc"
2747
277
        break;
2748
35.7k
    case MVM_JIT_REG_ADDR:
2749
35.7k
        //| lea TMP6, WORK[arg.v.reg];
2750
35.7k
        dasm_put(Dst, 2779, Dt20([arg.v.reg]));
2751
35.7k
#line 1905 "src/jit/emit_x64.dasc"
2752
35.7k
        break;
2753
6.64k
    case MVM_JIT_STR_IDX:
2754
6.64k
        //| get_string TMP6, arg.v.lit_i64;
2755
6.64k
         MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, arg.v.lit_i64);
2756
6.64k
        dasm_put(Dst, 2784, Dt21(->body.strings), Dt13([arg.v.lit_i64]));
2757
6.64k
#line 1908 "src/jit/emit_x64.dasc"
2758
6.64k
        break;
2759
126k
    case MVM_JIT_LITERAL:
2760
126k
        //| mov TMP6, arg.v.lit_i64;
2761
126k
        dasm_put(Dst, 2793, arg.v.lit_i64);
2762
126k
#line 1911 "src/jit/emit_x64.dasc"
2763
126k
        break;
2764
12
    case MVM_JIT_LITERAL_64:
2765
12
    case MVM_JIT_LITERAL_PTR:
2766
12
    case MVM_JIT_LITERAL_F:
2767
12
        //| mov64 TMP6, arg.v.lit_i64;
2768
12
        dasm_put(Dst, 2798, (unsigned int)(arg.v.lit_i64), (unsigned int)((arg.v.lit_i64)>>32));
2769
12
#line 1916 "src/jit/emit_x64.dasc"
2770
12
        break;
2771
33.8k
    case MVM_JIT_REG_STABLE:
2772
33.8k
        //| mov TMP6, qword WORK[arg.v.reg];
2773
33.8k
        //| mov TMP6, OBJECT:TMP6->st;
2774
33.8k
        dasm_put(Dst, 229, Dt20([arg.v.reg]), DtE(->st));
2775
33.8k
#line 1920 "src/jit/emit_x64.dasc"
2776
33.8k
        break;
2777
33.8k
    case MVM_JIT_REG_OBJBODY:
2778
33.8k
        //| mov TMP6, qword WORK[arg.v.reg];
2779
33.8k
        //| lea TMP6, STOOGE:TMP6->data;
2780
33.8k
        dasm_put(Dst, 2803, Dt20([arg.v.reg]), DtF(->data));
2781
33.8k
#line 1924 "src/jit/emit_x64.dasc"
2782
33.8k
        break;
2783
0
    case MVM_JIT_DATA_LABEL:
2784
0
        //| lea TMP6, [=>(arg.v.lit_i64)];
2785
0
        dasm_put(Dst, 2812, (arg.v.lit_i64));
2786
0
#line 1927 "src/jit/emit_x64.dasc"
2787
0
        break;
2788
645k
    }
2789
645k
}
2790
2791
static void emit_gpr_arg(MVMThreadContext *tc, MVMJitGraph *jg,
2792
630k
                         MVMint32 i, dasm_State **Dst) {
2793
630k
    switch (i) {
2794
168k
    case 0:
2795
168k
        //| mov ARG1, TMP6;
2796
168k
        dasm_put(Dst, 2817);
2797
168k
#line 1936 "src/jit/emit_x64.dasc"
2798
168k
        break;
2799
168k
    case 1:
2800
168k
        //| mov ARG2, TMP6;
2801
168k
        dasm_put(Dst, 2821);
2802
168k
#line 1939 "src/jit/emit_x64.dasc"
2803
168k
        break;
2804
129k
    case 2:
2805
129k
        //| mov ARG3, TMP6;
2806
129k
        dasm_put(Dst, 2825);
2807
129k
#line 1942 "src/jit/emit_x64.dasc"
2808
129k
        break;
2809
90.6k
    case 3:
2810
90.6k
        //| mov ARG4, TMP6;
2811
90.6k
        dasm_put(Dst, 2829);
2812
90.6k
#line 1945 "src/jit/emit_x64.dasc"
2813
90.6k
        break;
2814
168k
//|.if POSIX
2815
39.2k
    case 4:
2816
39.2k
//|        mov ARG5, TMP6;
2817
39.2k
dasm_put(Dst, 2833);
2818
39.2k
       break;
2819
168k
#line 1950 "src/jit/emit_x64.dasc"
2820
34.1k
  case 5:
2821
34.1k
//|      mov ARG6, TMP6;
2822
34.1k
dasm_put(Dst, 2837);
2823
34.1k
     break;
2824
168k
#line 1953 "src/jit/emit_x64.dasc"
2825
168k
//|.endif
2826
0
    default:
2827
0
        MVM_oops(tc, "JIT: can't store %d arguments in GPR", i);
2828
630k
    }
2829
630k
}
2830
2831
static void emit_sse_arg(MVMThreadContext *tc, MVMJitGraph *jg,
2832
277
                         MVMint32 i, dasm_State **Dst) {
2833
277
    switch (i) {
2834
277
    case 0:
2835
277
        //| movd ARG1F, TMP6;
2836
277
        dasm_put(Dst, 2841);
2837
277
#line 1964 "src/jit/emit_x64.dasc"
2838
277
        break;
2839
0
    case 1:
2840
0
        //| movd ARG2F, TMP6;
2841
0
        dasm_put(Dst, 2847);
2842
0
#line 1967 "src/jit/emit_x64.dasc"
2843
0
        break;
2844
0
    case 2:
2845
0
        //| movd ARG3F, TMP6;
2846
0
        dasm_put(Dst, 2853);
2847
0
#line 1970 "src/jit/emit_x64.dasc"
2848
0
        break;
2849
0
    case 3:
2850
0
        //| movd ARG4F, TMP6;
2851
0
        dasm_put(Dst, 2859);
2852
0
#line 1973 "src/jit/emit_x64.dasc"
2853
0
        break;
2854
277
//|.if POSIX
2855
0
    case 4:
2856
0
//|        movd ARG5F, TMP6;
2857
0
dasm_put(Dst, 2865);
2858
0
       break;
2859
277
#line 1978 "src/jit/emit_x64.dasc"
2860
0
    case 5:
2861
0
//|         movd ARG6F, TMP6;
2862
0
dasm_put(Dst, 2871);
2863
0
        break;
2864
277
#line 1981 "src/jit/emit_x64.dasc"
2865
0
    case 6:
2866
0
//|        movd ARG7F, TMP6;
2867
0
dasm_put(Dst, 2878);
2868
0
       break;
2869
277
#line 1984 "src/jit/emit_x64.dasc"
2870
0
    case 7:
2871
0
//|        movd ARG8F, TMP6;
2872
0
dasm_put(Dst, 2885);
2873
0
       break;
2874
277
#line 1987 "src/jit/emit_x64.dasc"
2875
277
//|.endif
2876
0
    default:
2877
0
        MVM_oops(tc, "JIT: can't put  %d arguments in SSE", i);
2878
277
    }
2879
277
}
2880
2881
static void emit_stack_arg(MVMThreadContext *tc, MVMJitGraph *jg,
2882
                           MVMint32 arg_size, MVMint32 pos,
2883
14.7k
                           dasm_State **Dst) {
2884
14.7k
    /* basically, stack arguments are passed in right-to-left order
2885
14.7k
       on both POSIX and W64 backends, it seems. Thus the most logical
2886
14.7k
       thing to do is to count from the stack top upwards. */
2887
14.7k
    if (pos + arg_size > 160) {
2888
0
        MVM_oops(tc, "JIT: trying to pass arguments "
2889
0
                 " in local space (stack top offset:"
2890
0
                 " %d, size: %d)", pos, arg_size);
2891
0
    }
2892
14.7k
    switch(arg_size) {
2893
0
    case 1:
2894
0
        //| mov byte [rsp+pos], TMP6b;
2895
0
        dasm_put(Dst, 2892, pos);
2896
0
#line 2007 "src/jit/emit_x64.dasc"
2897
0
        break;
2898
0
    case 2:
2899
0
        //| mov word [rsp+pos], TMP6w;
2900
0
        dasm_put(Dst, 2899, pos);
2901
0
#line 2010 "src/jit/emit_x64.dasc"
2902
0
        break;
2903
0
    case 4:
2904
0
        //| mov dword [rsp+pos], TMP6d;
2905
0
        dasm_put(Dst, 2900, pos);
2906
0
#line 2013 "src/jit/emit_x64.dasc"
2907
0
        break;
2908
14.7k
    case 8:
2909
14.7k
        //| mov qword [rsp+pos], TMP6;
2910
14.7k
        dasm_put(Dst, 2907, pos);
2911
14.7k
#line 2016 "src/jit/emit_x64.dasc"
2912
14.7k
        break;
2913
0
    default:
2914
0
        MVM_oops(tc, "JIT: can't pass arguments size %d bytes",
2915
0
                 arg_size);
2916
14.7k
    }
2917
14.7k
}
2918
2919
static void emit_posix_callargs(MVMThreadContext *tc, MVMJitGraph *jg,
2920
                                MVMJitCallArg args[], MVMint32 num_args,
2921
168k
                                dasm_State **Dst) {
2922
168k
    MVMint32 num_gpr = 0, num_fpr = 0, num_stack = 0, i;
2923
168k
    MVMJitCallArg in_gpr[6], in_fpr[8], *on_stack = NULL;
2924
168k
    if (num_args > 6)
2925
12.4k
        on_stack = MVM_malloc(sizeof(MVMJitCallArg) * (num_args - 6));
2926
168k
    /* divide in gpr, fpr, stack values */
2927
814k
    for (i = 0; i < num_args; i++) {
2928
645k
        switch (args[i].type) {
2929
645k
        case MVM_JIT_INTERP_VAR:
2930
645k
        case MVM_JIT_REG_VAL:
2931
645k
        case MVM_JIT_REG_ADDR:
2932
645k
        case MVM_JIT_REG_OBJBODY:
2933
645k
        case MVM_JIT_REG_STABLE:
2934
645k
        case MVM_JIT_STR_IDX:
2935
645k
        case MVM_JIT_LITERAL:
2936
645k
        case MVM_JIT_LITERAL_64:
2937
645k
        case MVM_JIT_LITERAL_PTR:
2938
645k
        case MVM_JIT_DATA_LABEL:
2939
645k
            if (num_gpr < 6) {
2940
630k
                in_gpr[num_gpr++] = args[i];
2941
14.7k
            } else {
2942
14.7k
                on_stack[num_stack++] = args[i];
2943
14.7k
            }
2944
645k
            break;
2945
277
        case MVM_JIT_REG_VAL_F:
2946
277
        case MVM_JIT_LITERAL_F:
2947
277
            if (num_fpr < 8) {
2948
277
                in_fpr[num_fpr++] = args[i];
2949
0
            } else {
2950
0
                on_stack[num_stack++] = args[i];
2951
0
            }
2952
277
            break;
2953
645k
        }
2954
645k
    }
2955
799k
    for (i = 0; i < num_gpr; i++) {
2956
630k
        load_call_arg(tc, jg, in_gpr[i], Dst);
2957
630k
        emit_gpr_arg(tc, jg, i, Dst);
2958
630k
    }
2959
168k
    for (i = 0; i < num_fpr; i++) {
2960
277
        load_call_arg(tc, jg, in_fpr[i], Dst);
2961
277
        emit_sse_arg(tc, jg, i, Dst);
2962
277
    }
2963
168k
    /* push right-to-left */
2964
183k
    for (i = 0; i < num_stack; i++) {
2965
14.7k
        load_call_arg(tc, jg, on_stack[i], Dst);
2966
14.7k
        // I'm not sure this is correct, btw
2967
14.7k
        emit_stack_arg(tc, jg, 8, i*8, Dst);
2968
14.7k
    }
2969
168k
    if (on_stack)
2970
12.4k
        MVM_free(on_stack);
2971
168k
}
2972
2973
static void emit_win64_callargs(MVMThreadContext *tc, MVMJitGraph *jg,
2974
                                MVMJitCallArg args[], MVMint32 num_args,
2975
0
                                dasm_State **Dst) {
2976
0
    MVMint32 i;
2977
0
    MVMint32 num_reg_args = (num_args > 4 ? 4 : num_args);
2978
0
    for (i = 0; i < num_reg_args; i++) {
2979
0
        load_call_arg(tc, jg, args[i], Dst);
2980
0
        if (args[i].type == MVM_JIT_REG_VAL_F ||
2981
0
            args[i].type == MVM_JIT_LITERAL_F) {
2982
0
            emit_sse_arg(tc, jg, i, Dst);
2983
0
        } else {
2984
0
            emit_gpr_arg(tc, jg, i, Dst);
2985
0
        }
2986
0
    }
2987
0
    for (; i < num_args; i++) {
2988
0
        load_call_arg(tc, jg, args[i], Dst);
2989
0
        emit_stack_arg(tc, jg, 8, i * 8, Dst);
2990
0
    }
2991
0
}
2992
2993
void MVM_jit_emit_call_c(MVMThreadContext *tc, MVMJitGraph *jg,
2994
168k
                         MVMJitCallC * call_spec, dasm_State **Dst) {
2995
168k
2996
168k
    MVM_jit_log(tc, "emit c call <%d args>\n", call_spec->num_args);
2997
168k
    if (call_spec->has_vargs) {
2998
0
        MVM_oops(tc, "JIT can't handle varargs yet");
2999
0
    }
3000
168k
    //|.if WIN32;
3001
168k
#line 2106 "src/jit/emit_x64.dasc"
3002
168k
    //|.else;
3003
168k
     emit_posix_callargs(tc, jg, call_spec->args, call_spec->num_args, Dst);
3004
168k
    //|.endif
3005
168k
    /* Emit the call. I think we should be able to do something smarter than
3006
168k
     * store the constant into the bytecode, like a data segment. But I'm
3007
168k
     * not sure. */
3008
168k
    //| callp call_spec->func_ptr;
3009
168k
    dasm_put(Dst, 204);
3010
168k
    dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(call_spec->func_ptr)), (MVMuint32)((uintptr_t)(call_spec->func_ptr) >> 32));
3011
168k
    dasm_put(Dst, 212);
3012
168k
#line 2113 "src/jit/emit_x64.dasc"
3013
168k
    /* right, now determine what to do with the return value */
3014
168k
    switch(call_spec->rv_mode) {
3015
96.3k
    case MVM_JIT_RV_VOID:
3016
96.3k
        break;
3017
72.1k
    case MVM_JIT_RV_INT:
3018
72.1k
    case MVM_JIT_RV_PTR:
3019
72.1k
        //| mov WORK[call_spec->rv_idx], RV;
3020
72.1k
        dasm_put(Dst, 274, Dt20([call_spec->rv_idx]));
3021
72.1k
#line 2120 "src/jit/emit_x64.dasc"
3022
72.1k
        break;
3023
7
    case MVM_JIT_RV_NUM:
3024
7
        //| movsd qword WORK[call_spec->rv_idx], RVF;
3025
7
        dasm_put(Dst, 1232, Dt20([call_spec->rv_idx]));
3026
7
#line 2123 "src/jit/emit_x64.dasc"
3027
7
        break;
3028
0
    case MVM_JIT_RV_DEREF:
3029
0
        //| mov TMP1, [RV];
3030
0
        //| mov WORK[call_spec->rv_idx], TMP1;
3031
0
        dasm_put(Dst, 2914, Dt20([call_spec->rv_idx]));
3032
0
#line 2127 "src/jit/emit_x64.dasc"
3033
0
        break;
3034
0
    case MVM_JIT_RV_ADDR:
3035
0
        /* store local at address */
3036
0
        //| mov TMP1, WORK[call_spec->rv_idx];
3037
0
        //| mov [RV], TMP1;
3038
0
        dasm_put(Dst, 2922, Dt20([call_spec->rv_idx]));
3039
0
#line 2132 "src/jit/emit_x64.dasc"
3040
0
        break;
3041
168k
    }
3042
168k
}
3043
3044
void MVM_jit_emit_branch(MVMThreadContext *tc, MVMJitGraph *jg,
3045
103k
                         MVMJitBranch * branch, dasm_State **Dst) {
3046
103k
    MVMSpeshIns *ins = branch->ins;
3047
103k
    MVMint32 name = branch->dest;
3048
103k
    /* move gc sync point to the front so as to not have
3049
103k
     * awkward dispatching issues */
3050
103k
    //| gc_sync_point;
3051
103k
    dasm_put(Dst, 2930, Dt1F(->gc_status));
3052
103k
    dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_gc_enter_from_interrupt)), (MVMuint32)((uintptr_t)(&MVM_gc_enter_from_interrupt) >> 32));
3053
103k
    dasm_put(Dst, 1066);
3054
103k
#line 2143 "src/jit/emit_x64.dasc"
3055
103k
    if (ins == NULL || ins->info->opcode == MVM_OP_goto) {
3056
50.7k
        MVM_jit_log(tc, "emit jump to label %d\n", name);
3057
50.7k
        if (name == MVM_JIT_BRANCH_EXIT) {
3058
11.8k
            //| jmp ->exit
3059
11.8k
            dasm_put(Dst, 2945);
3060
11.8k
#line 2147 "src/jit/emit_x64.dasc"
3061
38.9k
        } else {
3062
38.9k
            //| jmp =>(name)
3063
38.9k
            dasm_put(Dst, 2950, (name));
3064
38.9k
#line 2149 "src/jit/emit_x64.dasc"
3065
38.9k
        }
3066
52.8k
    } else {
3067
52.8k
        MVMint16 val = ins->operands[0].reg.orig;
3068
52.8k
        MVM_jit_log(tc, "emit branch <%s> to label %d\n",
3069
52.8k
                    ins->info->name, name);
3070
52.8k
        switch(ins->info->opcode) {
3071
23.3k
        case MVM_OP_if_i:
3072
23.3k
            //| mov rax, WORK[val];
3073
23.3k
            //| test rax, rax;
3074
23.3k
            //| jnz =>(name); // jump to dynamic label
3075
23.3k
            dasm_put(Dst, 2954, Dt20([val]), (name));
3076
23.3k
#line 2159 "src/jit/emit_x64.dasc"
3077
23.3k
            break;
3078
20.8k
        case MVM_OP_unless_i:
3079
20.8k
            //| mov rax, WORK[val];
3080
20.8k
            //| test rax, rax;
3081
20.8k
            //| jz =>(name);
3082
20.8k
            dasm_put(Dst, 2965, Dt20([val]), (name));
3083
20.8k
#line 2164 "src/jit/emit_x64.dasc"
3084
20.8k
            break;
3085
0
        case MVM_OP_if_n:
3086
0
            //| movd xmm0, qword WORK[val];
3087
0
            //| xorpd xmm1, xmm1; // make it zero
3088
0
            //| ucomisd xmm0, xmm1;
3089
0
            //| jp =>(name);  // is NaN?
3090
0
            //| jne =>(name); // not equal to zero? we're golden
3091
0
            dasm_put(Dst, 2976, Dt20([val]), (name), (name));
3092
0
#line 2171 "src/jit/emit_x64.dasc"
3093
0
            break;
3094
31
        case MVM_OP_unless_n:
3095
31
            //| movd xmm0, qword WORK[val];
3096
31
            //| xorpd xmm1, xmm1; // make it zero
3097
31
            //| ucomisd xmm0, xmm1;
3098
31
            //| jp >1; // is NaN
3099
31
            //| jne >1; // is not zero
3100
31
            //| jmp =>(name); // it is zero yay!
3101
31
            //|1:
3102
31
            dasm_put(Dst, 2997, Dt20([val]), (name));
3103
31
#line 2180 "src/jit/emit_x64.dasc"
3104
31
            break;
3105
246
        case MVM_OP_if_s0:
3106
246
        case MVM_OP_unless_s0:
3107
246
            //| mov ARG1, TC;
3108
246
            //| mov ARG2, WORK[val];
3109
246
            //| callp &MVM_coerce_istrue_s;
3110
246
            dasm_put(Dst, 3025, Dt20([val]));
3111
246
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_coerce_istrue_s)), (MVMuint32)((uintptr_t)(&MVM_coerce_istrue_s) >> 32));
3112
246
#line 2186 "src/jit/emit_x64.dasc"
3113
246
            //| test RV, RV;
3114
246
            dasm_put(Dst, 2053);
3115
246
#line 2187 "src/jit/emit_x64.dasc"
3116
246
            if (ins->info->opcode == MVM_OP_unless_s0)
3117
246
                //| jz =>(name);
3118
246
                dasm_put(Dst, 2972, (name));
3119
246
#line 2189 "src/jit/emit_x64.dasc"
3120
246
            else
3121
246
                //| jnz =>(name);
3122
0
                dasm_put(Dst, 2961, (name));
3123
246
#line 2191 "src/jit/emit_x64.dasc"
3124
246
            break;
3125
8.15k
        case MVM_OP_ifnonnull:
3126
8.15k
            //| mov TMP1, WORK[val];
3127
8.15k
            //| test TMP1, TMP1;
3128
8.15k
            //| jz >1;
3129
8.15k
            //| get_vmnull TMP2;
3130
8.15k
            //| cmp TMP1, TMP2;
3131
8.15k
            //| je >1;
3132
8.15k
            //| jmp =>(name);
3133
8.15k
            //|1:
3134
8.15k
            dasm_put(Dst, 3035, Dt20([val]), Dt1F(->instance), DtC(->VMNull), (name));
3135
8.15k
#line 2201 "src/jit/emit_x64.dasc"
3136
8.15k
            break;
3137
306
        case MVM_OP_indexat:
3138
306
        case MVM_OP_indexnat: {
3139
306
            MVMint16 offset = ins->operands[1].reg.orig;
3140
306
            MVMuint32 str_idx = ins->operands[2].lit_str_idx;
3141
306
            //| mov ARG1, TC;
3142
306
            //| mov ARG2, WORK[val];
3143
306
            //| mov ARG3, WORK[offset];
3144
306
            //| get_string ARG4, str_idx;
3145
306
            dasm_put(Dst, 3067, Dt20([val]), Dt20([offset]));
3146
306
             MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, str_idx);
3147
306
#line 2210 "src/jit/emit_x64.dasc"
3148
306
            //| callp &MVM_string_char_at_in_string;
3149
306
            dasm_put(Dst, 3080, Dt21(->body.strings), Dt13([str_idx]));
3150
306
            dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_string_char_at_in_string)), (MVMuint32)((uintptr_t)(&MVM_string_char_at_in_string) >> 32));
3151
306
            dasm_put(Dst, 212);
3152
306
#line 2211 "src/jit/emit_x64.dasc"
3153
306
            /* This subtlety is due to the value being overloaded to
3154
306
             * -2 if it is out of bounds. Note that -1 is passed as a
3155
306
             * 32 bit integer, but this magically works in a 64 bit
3156
306
             * comparison because 32 bit values are sign-extended */
3157
306
            //| cmp RV, -1;
3158
306
            dasm_put(Dst, 3090);
3159
306
#line 2216 "src/jit/emit_x64.dasc"
3160
306
            if (ins->info->opcode == MVM_OP_indexat)
3161
306
                //| jle =>(name);
3162
298
                dasm_put(Dst, 3097, (name));
3163
306
#line 2218 "src/jit/emit_x64.dasc"
3164
8
            else {
3165
8
3166
8
                //| jne =>(name);
3167
8
                dasm_put(Dst, 2961, (name));
3168
8
#line 2221 "src/jit/emit_x64.dasc"
3169
8
            }
3170
306
            break;
3171
306
        }
3172
0
        default:
3173
0
            MVM_panic(1, "JIT: Can't handle conditional <%s>", ins->info->name);
3174
52.8k
        }
3175
52.8k
    }
3176
103k
}
3177
3178
void MVM_jit_emit_label(MVMThreadContext *tc, MVMJitGraph *jg,
3179
313k
                        MVMJitLabel *label, dasm_State **Dst) {
3180
313k
    //| =>(label->name):
3181
313k
    dasm_put(Dst, 393, (label->name));
3182
313k
#line 2233 "src/jit/emit_x64.dasc"
3183
313k
}
3184
3185
void MVM_jit_emit_guard(MVMThreadContext *tc, MVMJitGraph *jg,
3186
25.5k
                        MVMJitGuard *guard, dasm_State **Dst) {
3187
25.5k
    MVMint16 op        = guard->ins->info->opcode;
3188
25.5k
    MVMint16 obj       = guard->ins->operands[0].reg.orig;
3189
25.5k
    MVMint16 spesh_idx = guard->ins->operands[1].lit_i16;
3190
25.5k
    MVM_jit_log(tc, "emit guard <%s>\n", guard->ins->info->name);
3191
25.5k
    /* load object and spesh slot value */
3192
25.5k
    //| mov TMP1, WORK[obj];
3193
25.5k
    //| get_spesh_slot TMP2, spesh_idx;
3194
25.5k
    dasm_put(Dst, 3101, Dt20([obj]), Dt1F(->cur_frame), Dt2(->effective_spesh_slots), Dt14([spesh_idx]));
3195
25.5k
#line 2244 "src/jit/emit_x64.dasc"
3196
25.5k
    if (op == MVM_OP_sp_guard) {
3197
0
        /* object in question should just match the type, so it shouldn't
3198
0
         * be zero, and the STABLE should be equal to the value in the spesh
3199
0
         * slot */
3200
0
        /* check for null */
3201
0
        //| test TMP1, TMP1;
3202
0
        //| jz >1;
3203
0
        dasm_put(Dst, 3118);
3204
0
#line 2251 "src/jit/emit_x64.dasc"
3205
0
        /* get stable and compare */
3206
0
        //| cmp TMP2, OBJECT:TMP1->st;
3207
0
        //| jne >1;
3208
0
        dasm_put(Dst, 3126, DtE(->st));
3209
0
#line 2254 "src/jit/emit_x64.dasc"
3210
0
        /* we're good, no need to deopt */
3211
25.5k
    } else if (op == MVM_OP_sp_guardtype) {
3212
1.88k
        /* object in question should be a type object, so it shouldn't
3213
1.88k
         * be zero, should not be concrete, and the STABLE should be
3214
1.88k
         * equal to the value in the spesh slot */
3215
1.88k
        /* check for null */
3216
1.88k
        //| test TMP1, TMP1;
3217
1.88k
        //| jz >1;
3218
1.88k
        dasm_put(Dst, 3118);
3219
1.88k
#line 2262 "src/jit/emit_x64.dasc"
3220
1.88k
        /* check if type object (not concrete) */
3221
1.88k
        //| is_type_object TMP1;
3222
1.88k
        dasm_put(Dst, 3135, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3223
1.88k
#line 2264 "src/jit/emit_x64.dasc"
3224
1.88k
        /* if zero, this is a concrete object, and we should deopt */
3225
1.88k
        //| jz >1;
3226
1.88k
        dasm_put(Dst, 2589);
3227
1.88k
#line 2266 "src/jit/emit_x64.dasc"
3228
1.88k
        /* get stable and compare */
3229
1.88k
        //| cmp TMP2, OBJECT:TMP1->st;
3230
1.88k
        //| jne >1;
3231
1.88k
        dasm_put(Dst, 3126, DtE(->st));
3232
1.88k
#line 2269 "src/jit/emit_x64.dasc"
3233
1.88k
        /* we're good, no need to deopt */
3234
23.6k
    } else if (op == MVM_OP_sp_guardconc) {
3235
18.6k
        /* object should be a non-null concrete (non-type) object */
3236
18.6k
        //| test TMP1, TMP1;
3237
18.6k
        //| jz >1;
3238
18.6k
        dasm_put(Dst, 3118);
3239
18.6k
#line 2274 "src/jit/emit_x64.dasc"
3240
18.6k
        /* shouldn't be type object */
3241
18.6k
        //| is_type_object TMP1;
3242
18.6k
        //| jnz >1;
3243
18.6k
        dasm_put(Dst, 3142, DtE(->header.flags), MVM_CF_TYPE_OBJECT);
3244
18.6k
#line 2277 "src/jit/emit_x64.dasc"
3245
18.6k
        /* should have our stable */
3246
18.6k
        //| cmp TMP2, OBJECT:TMP1->st;
3247
18.6k
        //| jne >1;
3248
18.6k
        dasm_put(Dst, 3126, DtE(->st));
3249
18.6k
#line 2280 "src/jit/emit_x64.dasc"
3250
5.03k
    } else if (op == MVM_OP_sp_guardsf) {
3251
5.03k
        /* Should be an MVMCode */
3252
5.03k
        MVMint32 reprid = MVM_REPR_ID_MVMCode;
3253
5.03k
        //| mov TMP3, OBJECT:TMP1->st;
3254
5.03k
        //| mov TMP3, STABLE:TMP3->REPR;
3255
5.03k
        //| cmp qword REPR:TMP3->ID, reprid;
3256
5.03k
        //| jne >1;
3257
5.03k
        //| cmp TMP2, CODE:TMP1->body.sf;
3258
5.03k
        //| jne >1;
3259
5.03k
        dasm_put(Dst, 3153, DtE(->st), Dt11(->REPR), Dt12(->ID), reprid, Dt1A(->body.sf));
3260
5.03k
#line 2289 "src/jit/emit_x64.dasc"
3261
5.03k
    }
3262
25.5k
    /* if we're here, we didn't jump to deopt, so skip it */
3263
25.5k
    //| jmp >2;
3264
25.5k
    //|1:
3265
25.5k
    dasm_put(Dst, 1909);
3266
25.5k
#line 2293 "src/jit/emit_x64.dasc"
3267
25.5k
    /* emit deopt */
3268
25.5k
    //| mov ARG1, TC;
3269
25.5k
    //| mov ARG2, guard->deopt_offset;
3270
25.5k
    //| mov ARG3, guard->deopt_target;
3271
25.5k
    //| callp &MVM_spesh_deopt_one_direct;
3272
25.5k
    dasm_put(Dst, 3179, guard->deopt_offset, guard->deopt_target);
3273
25.5k
    dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_spesh_deopt_one_direct)), (MVMuint32)((uintptr_t)(&MVM_spesh_deopt_one_direct) >> 32));
3274
25.5k
    dasm_put(Dst, 212);
3275
25.5k
#line 2298 "src/jit/emit_x64.dasc"
3276
25.5k
    /* tell jit driver we're deopting */
3277
25.5k
    //| mov RV, MVM_JIT_CTRL_DEOPT
3278
25.5k
    //| jmp ->out;
3279
25.5k
    //|2:
3280
25.5k
    dasm_put(Dst, 3193, MVM_JIT_CTRL_DEOPT);
3281
25.5k
#line 2302 "src/jit/emit_x64.dasc"
3282
25.5k
}
3283
3284
void MVM_jit_emit_invoke(MVMThreadContext *tc, MVMJitGraph *jg, MVMJitInvoke *invoke,
3285
16.7k
                         dasm_State **Dst) {
3286
16.7k
    MVMint16 i;
3287
16.7k
    MVMuint16 callsite_idx = invoke->callsite_idx;
3288
16.7k
    MVM_jit_log(tc, "Emit invoke (%d args)\n", invoke->arg_count);
3289
16.7k
    /* Store callsite in tmp6, which we use at the end of invoke */
3290
16.7k
    //| mov TMP6, CU->body.callsites;
3291
16.7k
    //| mov TMP6, CALLSITEPTR:TMP6[callsite_idx];
3292
16.7k
    dasm_put(Dst, 2784, Dt21(->body.callsites), Dt4([callsite_idx]));
3293
16.7k
#line 2312 "src/jit/emit_x64.dasc"
3294
16.7k
3295
16.7k
    /* Store callsite in the frame. I use TMP5 as it never conflicts
3296
16.7k
     * with argument passing (like TMP6, but unlike other TMP regs) */
3297
16.7k
    //| mov TMP5, TC->cur_frame;
3298
16.7k
    //| mov FRAME:TMP5->cur_args_callsite, TMP6;
3299
16.7k
    dasm_put(Dst, 3204, Dt1F(->cur_frame), Dt2(->cur_args_callsite));
3300
16.7k
#line 2317 "src/jit/emit_x64.dasc"
3301
16.7k
3302
16.7k
    /* Setup the frame for returning to our current position */
3303
16.7k
    if (sizeof(MVMReturnType) == 1) {
3304
16.7k
        //| mov byte FRAME:TMP5->return_type, invoke->return_type;
3305
16.7k
        dasm_put(Dst, 3213, Dt2(->return_type), invoke->return_type);
3306
16.7k
#line 2321 "src/jit/emit_x64.dasc"
3307
0
    } else {
3308
0
        MVM_panic(1, "JIT: MVMReturnType has unexpected size");
3309
0
    }
3310
16.7k
    /* The register for our return value */
3311
16.7k
    if (invoke->return_type == MVM_RETURN_VOID) {
3312
418
        //| mov aword FRAME:TMP5->return_value, NULL;
3313
418
        dasm_put(Dst, 3219, Dt2(->return_value), NULL);
3314
418
#line 2327 "src/jit/emit_x64.dasc"
3315
16.3k
    } else {
3316
16.3k
        //| lea TMP2, WORK[invoke->return_register];
3317
16.3k
        //| mov aword FRAME:TMP5->return_value, TMP2;
3318
16.3k
        dasm_put(Dst, 3225, Dt20([invoke->return_register]), Dt2(->return_value));
3319
16.3k
#line 2330 "src/jit/emit_x64.dasc"
3320
16.3k
    }
3321
16.7k
    /* The return address for the interpreter */
3322
16.7k
    //| get_cur_op TMP2;
3323
16.7k
    //| mov aword FRAME:TMP5->return_address, TMP2;
3324
16.7k
    dasm_put(Dst, 3234, Dt1F(->interp_cur_op), Dt2(->return_address));
3325
16.7k
#line 2334 "src/jit/emit_x64.dasc"
3326
16.7k
3327
16.7k
    /* The re-entry label for the JIT, so that we continue in the next BB */
3328
16.7k
    //| lea TMP2, [=>(invoke->reentry_label)];
3329
16.7k
    //| mov aword FRAME:TMP5->jit_entry_label, TMP2;
3330
16.7k
    dasm_put(Dst, 3246, (invoke->reentry_label), Dt2(->jit_entry_label));
3331
16.7k
#line 2338 "src/jit/emit_x64.dasc"
3332
16.7k
3333
16.7k
    /* Install invoke args */
3334
16.7k
    //| mov TMP5, FRAME:TMP5->args;
3335
16.7k
    dasm_put(Dst, 180, Dt2(->args));
3336
16.7k
#line 2341 "src/jit/emit_x64.dasc"
3337
53.8k
    for (i = 0;  i < invoke->arg_count; i++) {
3338
37.0k
        MVMSpeshIns *ins = invoke->arg_ins[i];
3339
37.0k
        switch (ins->info->opcode) {
3340
34.9k
        case MVM_OP_arg_i:
3341
34.9k
        case MVM_OP_arg_s:
3342
34.9k
        case MVM_OP_arg_n:
3343
34.9k
        case MVM_OP_arg_o: {
3344
34.9k
            MVMint16 dst = ins->operands[0].lit_i16;
3345
34.9k
            MVMint16 src = ins->operands[1].reg.orig;
3346
34.9k
            //| mov TMP4, WORK[src];
3347
34.9k
            //| mov REGISTER:TMP5[dst], TMP4;
3348
34.9k
            dasm_put(Dst, 3255, Dt20([src]), Dt1([dst]));
3349
34.9k
#line 2352 "src/jit/emit_x64.dasc"
3350
34.9k
            break;
3351
34.9k
        }
3352
0
        case MVM_OP_argconst_n:
3353
0
        case MVM_OP_argconst_i: {
3354
0
            MVMint16 dst = ins->operands[0].lit_i16;
3355
0
            MVMint64 val = ins->operands[1].lit_i64;
3356
0
            //| mov64 TMP4, val;
3357
0
            //| mov REGISTER:TMP5[dst], TMP4;
3358
0
            dasm_put(Dst, 3264, (unsigned int)(val), (unsigned int)((val)>>32), Dt1([dst]));
3359
0
#line 2360 "src/jit/emit_x64.dasc"
3360
0
            break;
3361
0
        }
3362
2.12k
        case MVM_OP_argconst_s: {
3363
2.12k
            MVMint16 dst = ins->operands[0].lit_i16;
3364
2.12k
            MVMint32 idx = ins->operands[1].lit_str_idx;
3365
2.12k
            //| get_string TMP4, idx;
3366
2.12k
             MVM_cu_ensure_string_decoded(tc, jg->sg->sf->body.cu, idx);
3367
2.12k
#line 2366 "src/jit/emit_x64.dasc"
3368
2.12k
            //| mov REGISTER:TMP5[dst], TMP4;
3369
2.12k
            dasm_put(Dst, 3273, Dt21(->body.strings), Dt13([idx]), Dt1([dst]));
3370
2.12k
#line 2367 "src/jit/emit_x64.dasc"
3371
2.12k
            break;
3372
0
        }
3373
0
        default:
3374
0
            MVM_panic(1, "JIT invoke: Can't add arg <%s>",
3375
0
                      ins->info->name);
3376
37.0k
        }
3377
37.0k
    }
3378
16.7k
3379
16.7k
    /* if we're not fast, then we should get the code from multi resolution */
3380
16.7k
    if (!invoke->is_fast) {
3381
11.2k
        /* first, save callsite and args */
3382
11.2k
        //| mov qword [rbp-0x28], TMP5; // args
3383
11.2k
        //| mov qword [rbp-0x30], TMP6; // callsite
3384
11.2k
        dasm_put(Dst, 3286);
3385
11.2k
#line 2380 "src/jit/emit_x64.dasc"
3386
11.2k
        /* setup call MVM_frame_multi_ok(tc, code, &cur_callsite, args); */
3387
11.2k
        //| mov ARG1, TC;
3388
11.2k
        //| mov ARG2, WORK[invoke->code_register]; // code object
3389
11.2k
        //| lea ARG3, [rbp-0x30];                  // &cur_callsite
3390
11.2k
        //| mov ARG4, TMP5;                        // args
3391
11.2k
        //|.if WIN32;
3392
11.2k
        //| mov qword [rsp+0x20], 0
3393
11.2k
        //|.else;
3394
11.2k
        //| mov ARG5, 0;                           // NULL to &was_multi
3395
11.2k
        //|.endif
3396
11.2k
        //| callp &MVM_frame_find_invokee_multi_ok;
3397
11.2k
        dasm_put(Dst, 3295, Dt20([invoke->code_register]));
3398
11.2k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee_multi_ok)), (MVMuint32)((uintptr_t)(&MVM_frame_find_invokee_multi_ok) >> 32));
3399
11.2k
        dasm_put(Dst, 212);
3400
11.2k
#line 2391 "src/jit/emit_x64.dasc"
3401
11.2k
        /* restore callsite, args, RV now holds code object */
3402
11.2k
        //| mov TMP6, [rbp-0x30]; // callsite
3403
11.2k
        //| mov TMP5, [rbp-0x28]; // args
3404
11.2k
        dasm_put(Dst, 3319);
3405
11.2k
#line 2394 "src/jit/emit_x64.dasc"
3406
11.2k
        /* setup args for call to invoke(tc, code, cur_callsite, args) */
3407
11.2k
        //| mov ARG1, TC;
3408
11.2k
        //| mov ARG2, RV;   // code object
3409
11.2k
        //| mov ARG3, TMP6; // callsite
3410
11.2k
        //| mov ARG4, TMP5; // args
3411
11.2k
        dasm_put(Dst, 3328);
3412
11.2k
#line 2399 "src/jit/emit_x64.dasc"
3413
11.2k
        /* get the actual function */
3414
11.2k
        //| mov FUNCTION, OBJECT:RV->st;
3415
11.2k
        //| mov FUNCTION, STABLE:FUNCTION->invoke;
3416
11.2k
        //| call FUNCTION;
3417
11.2k
        dasm_put(Dst, 3342, DtE(->st), Dt11(->invoke));
3418
11.2k
#line 2403 "src/jit/emit_x64.dasc"
3419
5.46k
    } else {
3420
5.46k
        /* call MVM_frame_invoke_code */
3421
5.46k
        //| mov ARG1, TC;
3422
5.46k
        //| mov ARG2, WORK[invoke->code_register];
3423
5.46k
        //| mov ARG3, TMP6; // this is the callsite object
3424
5.46k
        //| mov ARG4, invoke->spesh_cand;
3425
5.46k
        //| callp &MVM_frame_invoke_code;
3426
5.46k
        dasm_put(Dst, 3355, Dt20([invoke->code_register]), invoke->spesh_cand);
3427
5.46k
        dasm_put(Dst, 206, (MVMuint32)((uintptr_t)(&MVM_frame_invoke_code)), (MVMuint32)((uintptr_t)(&MVM_frame_invoke_code) >> 32));
3428
5.46k
        dasm_put(Dst, 212);
3429
5.46k
#line 2410 "src/jit/emit_x64.dasc"
3430
5.46k
    }
3431
16.7k
    /* Almost done. jump out into the interprete */
3432
16.7k
    //| mov RV, 1;
3433
16.7k
    //| jmp ->out;
3434
16.7k
    dasm_put(Dst, 3372);
3435
16.7k
#line 2414 "src/jit/emit_x64.dasc"
3436
16.7k
}
3437
3438
void MVM_jit_emit_jumplist(MVMThreadContext *tc, MVMJitGraph *jg,
3439
524
                           MVMJitJumpList *jumplist, dasm_State **Dst) {
3440
524
    MVMint32 i;
3441
524
    MVM_jit_log(tc, "Emit jumplist (%"PRId64" labels)\n", jumplist->num_labels);
3442
524
    //| mov TMP1, WORK[jumplist->reg];
3443
524
    //| cmp TMP1, 0;
3444
524
    //| jl >2;
3445
524
    //| cmp TMP1, jumplist->num_labels;
3446
524
    //| jge >2;
3447
524
    //| imul TMP1, 0x8; // 8 bytes per goto
3448
524
    //| lea TMP2, [>1];
3449
524
    //| add TMP2, TMP1;
3450
524
    //| jmp TMP2;
3451
524
    //|.align 8;
3452
524
    //|1:
3453
524
    dasm_put(Dst, 3384, Dt20([jumplist->reg]), jumplist->num_labels);
3454
524
#line 2431 "src/jit/emit_x64.dasc"
3455
5.10k
    for (i = 0; i < jumplist->num_labels; i++) {
3456
4.58k
        //|=>(jumplist->in_labels[i]):
3457
4.58k
        //| jmp =>(jumplist->out_labels[i]);
3458
4.58k
        //|.align 8;
3459
4.58k
        dasm_put(Dst, 3426, (jumplist->in_labels[i]), (jumplist->out_labels[i]));
3460
4.58k
#line 2435 "src/jit/emit_x64.dasc"
3461
4.58k
    }
3462
524
    //|2:
3463
524
    dasm_put(Dst, 339);
3464
524
#line 2437 "src/jit/emit_x64.dasc"
3465
524
}
3466
3467
void MVM_jit_emit_control(MVMThreadContext *tc, MVMJitGraph *jg,
3468
394k
                          MVMJitControl *ctrl, dasm_State **Dst) {
3469
394k
    /* TODO - rename invokish and pre and post invokish into something that makes more sense */
3470
394k
    if (ctrl->type == MVM_JIT_CONTROL_INVOKISH) {
3471
49.5k
        MVM_jit_log(tc, "Emit invokish control guard\n");
3472
49.5k
        /* This relies on the fact that MVM_JIT_THROWISH_PRE has already
3473
49.5k
         * assigned the jit entry label */
3474
49.5k
        //| mov eax, dword TC->current_frame_nr;
3475
49.5k
        //| cmp eax, FRAME_NR;
3476
49.5k
        //| je >9;
3477
49.5k
        //| mov RV, 1;
3478
49.5k
        //| jmp ->out;
3479
49.5k
        //|9:
3480
49.5k
        dasm_put(Dst, 3433, Dt1F(->current_frame_nr));
3481
49.5k
#line 2452 "src/jit/emit_x64.dasc"
3482
49.5k
    }
3483
345k
    else if (ctrl->type == MVM_JIT_CONTROL_DYNAMIC_LABEL) {
3484
293k
        MVM_jit_log(tc, "Emit throwish control guard\n");
3485
293k
        /* This pre-loads a label for the next op, so that throwish
3486
293k
         * operators will know where we're throwing from - NB, I'm not
3487
293k
         * totally sure this is still necessary now */
3488
293k
        //| lea TMP1, [>1];
3489
293k
        //| mov TMP2, TC->cur_frame;
3490
293k
        //| mov aword FRAME:TMP2->jit_entry_label, TMP1;
3491
293k
        //|1:
3492
293k
        dasm_put(Dst, 3458, Dt1F(->cur_frame), Dt2(->jit_entry_label));
3493
293k
#line 2462 "src/jit/emit_x64.dasc"
3494
293k
    }
3495
52.2k
    else if (ctrl->type == MVM_JIT_CONTROL_THROWISH_PRE) {
3496
50.9k
        /* Store a reference to the 9 label below. I assume this label isn't
3497
50.9k
         * used in the intermediate instructions, which is basically valid
3498
50.9k
         * throughout this codebase. */
3499
50.9k
        //| lea TMP1, [>9];
3500
50.9k
        //| mov TMP2, TC->cur_frame;
3501
50.9k
        //| mov aword FRAME:TMP2->jit_entry_label, TMP1;
3502
50.9k
        dasm_put(Dst, 3474, Dt1F(->cur_frame), Dt2(->jit_entry_label));
3503
50.9k
#line 2470 "src/jit/emit_x64.dasc"
3504
50.9k
    }
3505
1.36k
    else if (ctrl->type == MVM_JIT_CONTROL_THROWISH_POST) {
3506
1.36k
        /* check if our current frame is the same as it was */
3507
1.36k
        //| mov TMP1d, dword TC->current_frame_nr;
3508
1.36k
        //| cmp TMP1d, FRAME_NR;
3509
1.36k
        //| jne >8;
3510
1.36k
        dasm_put(Dst, 3488, Dt1F(->current_frame_nr));
3511
1.36k
#line 2476 "src/jit/emit_x64.dasc"
3512
1.36k
        /* if it is, we may still be in a goto-handler, so in that
3513
1.36k
         * case the throwing machinery should have ensured that
3514
1.36k
         * jit_entry_label now points to the correct label. If not, it
3515
1.36k
         * still points to 9:. */
3516
1.36k
        //| mov TMP1, TC->cur_frame;
3517
1.36k
        //| jmp aword FRAME:TMP1->jit_entry_label;
3518
1.36k
        dasm_put(Dst, 3500, Dt1F(->cur_frame), Dt2(->jit_entry_label));
3519
1.36k
#line 2482 "src/jit/emit_x64.dasc"
3520
1.36k
        /* if not the same frame, trampoline to interpreter */
3521
1.36k
        //|8:
3522
1.36k
        //| mov RV, 1;
3523
1.36k
        //| jmp ->out;
3524
1.36k
        dasm_put(Dst, 3509);
3525
1.36k
#line 2486 "src/jit/emit_x64.dasc"
3526
1.36k
        /* I assume we *never* use a local label 9 in the code between
3527
1.36k
         * pre-and-post throwish */
3528
1.36k
        //|9:
3529
1.36k
        dasm_put(Dst, 3455);
3530
1.36k
#line 2489 "src/jit/emit_x64.dasc"
3531
0
    } else if (ctrl->type == MVM_JIT_CONTROL_BREAKPOINT) {
3532
0
        /* brrts evil testing purposes breakpoint */
3533
0
        //| int 3;
3534
0
        dasm_put(Dst, 3523);
3535
0
#line 2492 "src/jit/emit_x64.dasc"
3536
0
    } else {
3537
0
        MVM_panic(1, "Unknown conrtol code: <%s>", ctrl->ins->info->name);
3538
0
    }
3539
394k
}
3540
3541
0
void MVM_jit_emit_data(MVMThreadContext *tc, MVMJitGraph *jg, MVMJitData *data, dasm_State **Dst) {
3542
0
    MVMuint8 *bytes = data->data;
3543
0
    MVMint32 i;
3544
0
    //|.data;
3545
0
    dasm_put(Dst, 204);
3546
0
#line 2501 "src/jit/emit_x64.dasc"
3547
0
    //|=>(data->label):
3548
0
    dasm_put(Dst, 393, (data->label));
3549
0
#line 2502 "src/jit/emit_x64.dasc"
3550
0
    for (i = 0; i < data->size; i++) {
3551
0
        //|.byte bytes[i];
3552
0
        dasm_put(Dst, 2458, bytes[i]);
3553
0
#line 2504 "src/jit/emit_x64.dasc"
3554
0
    }
3555
0
    //|.code
3556
0
    dasm_put(Dst, 0);
3557
0
#line 2506 "src/jit/emit_x64.dasc"
3558
0
}