/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 | } |