Coverage Report

Created: 2018-07-03 15:31

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