Coverage Report

Created: 2017-04-15 07:07

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