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