blob: bf9a97d75cd1865fcf371d3e9b750b4a73bbeeb5 [file] [log] [blame]
Aurelien Jarno477ba622010-03-29 02:12:51 +02001/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2009-2010 Aurelien Jarno <aurelien@aurel32.net>
5 * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26/*
27 * Register definitions
28 */
29
Aurelien Jarno8d8fdba2016-04-21 10:48:50 +020030#ifdef CONFIG_DEBUG_TCG
Aurelien Jarno477ba622010-03-29 02:12:51 +020031static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
32 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
33 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
34 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
35 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
36 "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39",
37 "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47",
38 "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55",
39 "r56", "r57", "r58", "r59", "r60", "r61", "r62", "r63",
40};
41#endif
42
Laurent Vivier4cbea592015-08-24 01:42:07 +020043#ifndef CONFIG_SOFTMMU
Richard Henderson6781d082010-05-06 08:50:44 -070044#define TCG_GUEST_BASE_REG TCG_REG_R55
Richard Henderson6781d082010-05-06 08:50:44 -070045#endif
46
Aurelien Jarno477ba622010-03-29 02:12:51 +020047/* Branch registers */
48enum {
49 TCG_REG_B0 = 0,
50 TCG_REG_B1,
51 TCG_REG_B2,
52 TCG_REG_B3,
53 TCG_REG_B4,
54 TCG_REG_B5,
55 TCG_REG_B6,
56 TCG_REG_B7,
57};
58
59/* Floating point registers */
60enum {
61 TCG_REG_F0 = 0,
62 TCG_REG_F1,
63 TCG_REG_F2,
64 TCG_REG_F3,
65 TCG_REG_F4,
66 TCG_REG_F5,
67 TCG_REG_F6,
68 TCG_REG_F7,
69 TCG_REG_F8,
70 TCG_REG_F9,
71 TCG_REG_F10,
72 TCG_REG_F11,
73 TCG_REG_F12,
74 TCG_REG_F13,
75 TCG_REG_F14,
76 TCG_REG_F15,
77};
78
79/* Predicate registers */
80enum {
81 TCG_REG_P0 = 0,
82 TCG_REG_P1,
83 TCG_REG_P2,
84 TCG_REG_P3,
85 TCG_REG_P4,
86 TCG_REG_P5,
87 TCG_REG_P6,
88 TCG_REG_P7,
89 TCG_REG_P8,
90 TCG_REG_P9,
91 TCG_REG_P10,
92 TCG_REG_P11,
93 TCG_REG_P12,
94 TCG_REG_P13,
95 TCG_REG_P14,
96 TCG_REG_P15,
97};
98
99/* Application registers */
100enum {
101 TCG_REG_PFS = 64,
102};
103
104static const int tcg_target_reg_alloc_order[] = {
Aurelien Jarno477ba622010-03-29 02:12:51 +0200105 TCG_REG_R35,
106 TCG_REG_R36,
107 TCG_REG_R37,
108 TCG_REG_R38,
109 TCG_REG_R39,
110 TCG_REG_R40,
111 TCG_REG_R41,
112 TCG_REG_R42,
113 TCG_REG_R43,
114 TCG_REG_R44,
115 TCG_REG_R45,
116 TCG_REG_R46,
117 TCG_REG_R47,
118 TCG_REG_R48,
119 TCG_REG_R49,
120 TCG_REG_R50,
121 TCG_REG_R51,
122 TCG_REG_R52,
123 TCG_REG_R53,
124 TCG_REG_R54,
125 TCG_REG_R55,
126 TCG_REG_R14,
127 TCG_REG_R15,
128 TCG_REG_R16,
129 TCG_REG_R17,
130 TCG_REG_R18,
131 TCG_REG_R19,
132 TCG_REG_R20,
133 TCG_REG_R21,
134 TCG_REG_R22,
135 TCG_REG_R23,
136 TCG_REG_R24,
137 TCG_REG_R25,
138 TCG_REG_R26,
139 TCG_REG_R27,
140 TCG_REG_R28,
141 TCG_REG_R29,
142 TCG_REG_R30,
143 TCG_REG_R31,
144 TCG_REG_R56,
145 TCG_REG_R57,
146 TCG_REG_R58,
147 TCG_REG_R59,
148 TCG_REG_R60,
149 TCG_REG_R61,
150 TCG_REG_R62,
151 TCG_REG_R63,
152 TCG_REG_R8,
153 TCG_REG_R9,
154 TCG_REG_R10,
155 TCG_REG_R11
156};
157
158static const int tcg_target_call_iarg_regs[8] = {
159 TCG_REG_R56,
160 TCG_REG_R57,
161 TCG_REG_R58,
162 TCG_REG_R59,
163 TCG_REG_R60,
164 TCG_REG_R61,
165 TCG_REG_R62,
166 TCG_REG_R63,
167};
168
Stefan Weilaf15a622011-09-05 11:06:59 +0200169static const int tcg_target_call_oarg_regs[] = {
170 TCG_REG_R8
Aurelien Jarno477ba622010-03-29 02:12:51 +0200171};
172
Aurelien Jarno477ba622010-03-29 02:12:51 +0200173/*
174 * opcode formation
175 */
176
177/* bundle templates: stops (double bar in the IA64 manual) are marked with
178 an uppercase letter. */
179enum {
180 mii = 0x00,
181 miI = 0x01,
182 mIi = 0x02,
183 mII = 0x03,
184 mlx = 0x04,
185 mLX = 0x05,
186 mmi = 0x08,
187 mmI = 0x09,
188 Mmi = 0x0a,
189 MmI = 0x0b,
190 mfi = 0x0c,
191 mfI = 0x0d,
192 mmf = 0x0e,
193 mmF = 0x0f,
194 mib = 0x10,
195 miB = 0x11,
196 mbb = 0x12,
197 mbB = 0x13,
198 bbb = 0x16,
199 bbB = 0x17,
200 mmb = 0x18,
201 mmB = 0x19,
202 mfb = 0x1c,
203 mfB = 0x1d,
204};
205
206enum {
207 OPC_ADD_A1 = 0x10000000000ull,
208 OPC_AND_A1 = 0x10060000000ull,
209 OPC_AND_A3 = 0x10160000000ull,
210 OPC_ANDCM_A1 = 0x10068000000ull,
211 OPC_ANDCM_A3 = 0x10168000000ull,
212 OPC_ADDS_A4 = 0x10800000000ull,
213 OPC_ADDL_A5 = 0x12000000000ull,
214 OPC_ALLOC_M34 = 0x02c00000000ull,
215 OPC_BR_DPTK_FEW_B1 = 0x08400000000ull,
216 OPC_BR_SPTK_MANY_B1 = 0x08000001000ull,
Richard Henderson3bf16cb2013-09-06 02:06:59 -0400217 OPC_BR_CALL_SPNT_FEW_B3 = 0x0a200000000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200218 OPC_BR_SPTK_MANY_B4 = 0x00100001000ull,
219 OPC_BR_CALL_SPTK_MANY_B5 = 0x02100001000ull,
220 OPC_BR_RET_SPTK_MANY_B4 = 0x00108001100ull,
221 OPC_BRL_SPTK_MANY_X3 = 0x18000001000ull,
Richard Henderson4bdd5472013-09-06 00:38:52 -0400222 OPC_BRL_CALL_SPNT_MANY_X4 = 0x1a200001000ull,
Richard Henderson6f65c782013-09-05 12:11:27 -0400223 OPC_BRL_CALL_SPTK_MANY_X4 = 0x1a000001000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200224 OPC_CMP_LT_A6 = 0x18000000000ull,
225 OPC_CMP_LTU_A6 = 0x1a000000000ull,
226 OPC_CMP_EQ_A6 = 0x1c000000000ull,
227 OPC_CMP4_LT_A6 = 0x18400000000ull,
228 OPC_CMP4_LTU_A6 = 0x1a400000000ull,
229 OPC_CMP4_EQ_A6 = 0x1c400000000ull,
Aurelien Jarno63975ea2012-10-09 21:53:55 +0200230 OPC_DEP_I14 = 0x0ae00000000ull,
Richard Hendersonc7d44752012-10-10 16:01:35 -0700231 OPC_DEP_I15 = 0x08000000000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200232 OPC_DEP_Z_I12 = 0x0a600000000ull,
233 OPC_EXTR_I11 = 0x0a400002000ull,
234 OPC_EXTR_U_I11 = 0x0a400000000ull,
235 OPC_FCVT_FX_TRUNC_S1_F10 = 0x004d0000000ull,
236 OPC_FCVT_FXU_TRUNC_S1_F10 = 0x004d8000000ull,
237 OPC_FCVT_XF_F11 = 0x000e0000000ull,
238 OPC_FMA_S1_F1 = 0x10400000000ull,
239 OPC_FNMA_S1_F1 = 0x18400000000ull,
240 OPC_FRCPA_S1_F6 = 0x00600000000ull,
241 OPC_GETF_SIG_M19 = 0x08708000000ull,
242 OPC_LD1_M1 = 0x08000000000ull,
243 OPC_LD1_M3 = 0x0a000000000ull,
244 OPC_LD2_M1 = 0x08040000000ull,
245 OPC_LD2_M3 = 0x0a040000000ull,
246 OPC_LD4_M1 = 0x08080000000ull,
247 OPC_LD4_M3 = 0x0a080000000ull,
248 OPC_LD8_M1 = 0x080c0000000ull,
249 OPC_LD8_M3 = 0x0a0c0000000ull,
Pranith Kumar5bbadbd2016-07-14 16:20:17 -0400250 OPC_MF_M24 = 0x00110000000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200251 OPC_MUX1_I3 = 0x0eca0000000ull,
252 OPC_NOP_B9 = 0x04008000000ull,
253 OPC_NOP_F16 = 0x00008000000ull,
254 OPC_NOP_I18 = 0x00008000000ull,
255 OPC_NOP_M48 = 0x00008000000ull,
256 OPC_MOV_I21 = 0x00e00100000ull,
257 OPC_MOV_RET_I21 = 0x00e00500000ull,
258 OPC_MOV_I22 = 0x00188000000ull,
259 OPC_MOV_I_I26 = 0x00150000000ull,
260 OPC_MOVL_X2 = 0x0c000000000ull,
261 OPC_OR_A1 = 0x10070000000ull,
Richard Henderson25c9c732013-09-05 17:13:43 -0400262 OPC_OR_A3 = 0x10170000000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200263 OPC_SETF_EXP_M18 = 0x0c748000000ull,
264 OPC_SETF_SIG_M18 = 0x0c708000000ull,
265 OPC_SHL_I7 = 0x0f240000000ull,
266 OPC_SHR_I5 = 0x0f220000000ull,
267 OPC_SHR_U_I5 = 0x0f200000000ull,
268 OPC_SHRP_I10 = 0x0ac00000000ull,
269 OPC_SXT1_I29 = 0x000a0000000ull,
270 OPC_SXT2_I29 = 0x000a8000000ull,
271 OPC_SXT4_I29 = 0x000b0000000ull,
272 OPC_ST1_M4 = 0x08c00000000ull,
273 OPC_ST2_M4 = 0x08c40000000ull,
274 OPC_ST4_M4 = 0x08c80000000ull,
275 OPC_ST8_M4 = 0x08cc0000000ull,
276 OPC_SUB_A1 = 0x10028000000ull,
277 OPC_SUB_A3 = 0x10128000000ull,
278 OPC_UNPACK4_L_I2 = 0x0f860000000ull,
279 OPC_XMA_L_F2 = 0x1d000000000ull,
280 OPC_XOR_A1 = 0x10078000000ull,
Richard Henderson25c9c732013-09-05 17:13:43 -0400281 OPC_XOR_A3 = 0x10178000000ull,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200282 OPC_ZXT1_I29 = 0x00080000000ull,
283 OPC_ZXT2_I29 = 0x00088000000ull,
284 OPC_ZXT4_I29 = 0x00090000000ull,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400285
286 INSN_NOP_M = OPC_NOP_M48, /* nop.m 0 */
287 INSN_NOP_I = OPC_NOP_I18, /* nop.i 0 */
Aurelien Jarno477ba622010-03-29 02:12:51 +0200288};
289
290static inline uint64_t tcg_opc_a1(int qp, uint64_t opc, int r1,
291 int r2, int r3)
292{
293 return opc
294 | ((r3 & 0x7f) << 20)
295 | ((r2 & 0x7f) << 13)
296 | ((r1 & 0x7f) << 6)
297 | (qp & 0x3f);
298}
299
300static inline uint64_t tcg_opc_a3(int qp, uint64_t opc, int r1,
301 uint64_t imm, int r3)
302{
303 return opc
304 | ((imm & 0x80) << 29) /* s */
305 | ((imm & 0x7f) << 13) /* imm7b */
306 | ((r3 & 0x7f) << 20)
307 | ((r1 & 0x7f) << 6)
308 | (qp & 0x3f);
309}
310
311static inline uint64_t tcg_opc_a4(int qp, uint64_t opc, int r1,
312 uint64_t imm, int r3)
313{
314 return opc
315 | ((imm & 0x2000) << 23) /* s */
316 | ((imm & 0x1f80) << 20) /* imm6d */
317 | ((imm & 0x007f) << 13) /* imm7b */
318 | ((r3 & 0x7f) << 20)
319 | ((r1 & 0x7f) << 6)
320 | (qp & 0x3f);
321}
322
323static inline uint64_t tcg_opc_a5(int qp, uint64_t opc, int r1,
324 uint64_t imm, int r3)
325{
326 return opc
327 | ((imm & 0x200000) << 15) /* s */
328 | ((imm & 0x1f0000) << 6) /* imm5c */
329 | ((imm & 0x00ff80) << 20) /* imm9d */
330 | ((imm & 0x00007f) << 13) /* imm7b */
331 | ((r3 & 0x03) << 20)
332 | ((r1 & 0x7f) << 6)
333 | (qp & 0x3f);
334}
335
336static inline uint64_t tcg_opc_a6(int qp, uint64_t opc, int p1,
337 int p2, int r2, int r3)
338{
339 return opc
340 | ((p2 & 0x3f) << 27)
341 | ((r3 & 0x7f) << 20)
342 | ((r2 & 0x7f) << 13)
343 | ((p1 & 0x3f) << 6)
344 | (qp & 0x3f);
345}
346
347static inline uint64_t tcg_opc_b1(int qp, uint64_t opc, uint64_t imm)
348{
349 return opc
350 | ((imm & 0x100000) << 16) /* s */
351 | ((imm & 0x0fffff) << 13) /* imm20b */
352 | (qp & 0x3f);
353}
354
Richard Henderson3bf16cb2013-09-06 02:06:59 -0400355static inline uint64_t tcg_opc_b3(int qp, uint64_t opc, int b1, uint64_t imm)
356{
357 return opc
358 | ((imm & 0x100000) << 16) /* s */
359 | ((imm & 0x0fffff) << 13) /* imm20b */
360 | ((b1 & 0x7) << 6)
361 | (qp & 0x3f);
362}
363
Aurelien Jarno477ba622010-03-29 02:12:51 +0200364static inline uint64_t tcg_opc_b4(int qp, uint64_t opc, int b2)
365{
366 return opc
367 | ((b2 & 0x7) << 13)
368 | (qp & 0x3f);
369}
370
371static inline uint64_t tcg_opc_b5(int qp, uint64_t opc, int b1, int b2)
372{
373 return opc
374 | ((b2 & 0x7) << 13)
375 | ((b1 & 0x7) << 6)
376 | (qp & 0x3f);
377}
378
379
380static inline uint64_t tcg_opc_b9(int qp, uint64_t opc, uint64_t imm)
381{
382 return opc
383 | ((imm & 0x100000) << 16) /* i */
384 | ((imm & 0x0fffff) << 6) /* imm20a */
385 | (qp & 0x3f);
386}
387
388static inline uint64_t tcg_opc_f1(int qp, uint64_t opc, int f1,
389 int f3, int f4, int f2)
390{
391 return opc
392 | ((f4 & 0x7f) << 27)
393 | ((f3 & 0x7f) << 20)
394 | ((f2 & 0x7f) << 13)
395 | ((f1 & 0x7f) << 6)
396 | (qp & 0x3f);
397}
398
399static inline uint64_t tcg_opc_f2(int qp, uint64_t opc, int f1,
400 int f3, int f4, int f2)
401{
402 return opc
403 | ((f4 & 0x7f) << 27)
404 | ((f3 & 0x7f) << 20)
405 | ((f2 & 0x7f) << 13)
406 | ((f1 & 0x7f) << 6)
407 | (qp & 0x3f);
408}
409
410static inline uint64_t tcg_opc_f6(int qp, uint64_t opc, int f1,
411 int p2, int f2, int f3)
412{
413 return opc
414 | ((p2 & 0x3f) << 27)
415 | ((f3 & 0x7f) << 20)
416 | ((f2 & 0x7f) << 13)
417 | ((f1 & 0x7f) << 6)
418 | (qp & 0x3f);
419}
420
421static inline uint64_t tcg_opc_f10(int qp, uint64_t opc, int f1, int f2)
422{
423 return opc
424 | ((f2 & 0x7f) << 13)
425 | ((f1 & 0x7f) << 6)
426 | (qp & 0x3f);
427}
428
429static inline uint64_t tcg_opc_f11(int qp, uint64_t opc, int f1, int f2)
430{
431 return opc
432 | ((f2 & 0x7f) << 13)
433 | ((f1 & 0x7f) << 6)
434 | (qp & 0x3f);
435}
436
437static inline uint64_t tcg_opc_f16(int qp, uint64_t opc, uint64_t imm)
438{
439 return opc
440 | ((imm & 0x100000) << 16) /* i */
441 | ((imm & 0x0fffff) << 6) /* imm20a */
442 | (qp & 0x3f);
443}
444
445static inline uint64_t tcg_opc_i2(int qp, uint64_t opc, int r1,
446 int r2, int r3)
447{
448 return opc
449 | ((r3 & 0x7f) << 20)
450 | ((r2 & 0x7f) << 13)
451 | ((r1 & 0x7f) << 6)
452 | (qp & 0x3f);
453}
454
455static inline uint64_t tcg_opc_i3(int qp, uint64_t opc, int r1,
456 int r2, int mbtype)
457{
458 return opc
459 | ((mbtype & 0x0f) << 20)
460 | ((r2 & 0x7f) << 13)
461 | ((r1 & 0x7f) << 6)
462 | (qp & 0x3f);
463}
464
465static inline uint64_t tcg_opc_i5(int qp, uint64_t opc, int r1,
466 int r3, int r2)
467{
468 return opc
469 | ((r3 & 0x7f) << 20)
470 | ((r2 & 0x7f) << 13)
471 | ((r1 & 0x7f) << 6)
472 | (qp & 0x3f);
473}
474
475static inline uint64_t tcg_opc_i7(int qp, uint64_t opc, int r1,
476 int r2, int r3)
477{
478 return opc
479 | ((r3 & 0x7f) << 20)
480 | ((r2 & 0x7f) << 13)
481 | ((r1 & 0x7f) << 6)
482 | (qp & 0x3f);
483}
484
485static inline uint64_t tcg_opc_i10(int qp, uint64_t opc, int r1,
486 int r2, int r3, uint64_t count)
487{
488 return opc
489 | ((count & 0x3f) << 27)
490 | ((r3 & 0x7f) << 20)
491 | ((r2 & 0x7f) << 13)
492 | ((r1 & 0x7f) << 6)
493 | (qp & 0x3f);
494}
495
496static inline uint64_t tcg_opc_i11(int qp, uint64_t opc, int r1,
497 int r3, uint64_t pos, uint64_t len)
498{
499 return opc
500 | ((len & 0x3f) << 27)
501 | ((r3 & 0x7f) << 20)
502 | ((pos & 0x3f) << 14)
503 | ((r1 & 0x7f) << 6)
504 | (qp & 0x3f);
505}
506
507static inline uint64_t tcg_opc_i12(int qp, uint64_t opc, int r1,
508 int r2, uint64_t pos, uint64_t len)
509{
510 return opc
511 | ((len & 0x3f) << 27)
512 | ((pos & 0x3f) << 20)
513 | ((r2 & 0x7f) << 13)
514 | ((r1 & 0x7f) << 6)
515 | (qp & 0x3f);
516}
517
Aurelien Jarno63975ea2012-10-09 21:53:55 +0200518static inline uint64_t tcg_opc_i14(int qp, uint64_t opc, int r1, uint64_t imm,
519 int r3, uint64_t pos, uint64_t len)
520{
521 return opc
522 | ((imm & 0x01) << 36)
523 | ((len & 0x3f) << 27)
524 | ((r3 & 0x7f) << 20)
525 | ((pos & 0x3f) << 14)
526 | ((r1 & 0x7f) << 6)
527 | (qp & 0x3f);
528}
529
Richard Hendersonc7d44752012-10-10 16:01:35 -0700530static inline uint64_t tcg_opc_i15(int qp, uint64_t opc, int r1, int r2,
531 int r3, uint64_t pos, uint64_t len)
532{
533 return opc
534 | ((pos & 0x3f) << 31)
535 | ((len & 0x0f) << 27)
536 | ((r3 & 0x7f) << 20)
537 | ((r2 & 0x7f) << 13)
538 | ((r1 & 0x7f) << 6)
539 | (qp & 0x3f);
540}
541
Aurelien Jarno477ba622010-03-29 02:12:51 +0200542static inline uint64_t tcg_opc_i18(int qp, uint64_t opc, uint64_t imm)
543{
544 return opc
545 | ((imm & 0x100000) << 16) /* i */
546 | ((imm & 0x0fffff) << 6) /* imm20a */
547 | (qp & 0x3f);
548}
549
550static inline uint64_t tcg_opc_i21(int qp, uint64_t opc, int b1,
551 int r2, uint64_t imm)
552{
553 return opc
554 | ((imm & 0x1ff) << 24)
555 | ((r2 & 0x7f) << 13)
556 | ((b1 & 0x7) << 6)
557 | (qp & 0x3f);
558}
559
560static inline uint64_t tcg_opc_i22(int qp, uint64_t opc, int r1, int b2)
561{
562 return opc
563 | ((b2 & 0x7) << 13)
564 | ((r1 & 0x7f) << 6)
565 | (qp & 0x3f);
566}
567
568static inline uint64_t tcg_opc_i26(int qp, uint64_t opc, int ar3, int r2)
569{
570 return opc
571 | ((ar3 & 0x7f) << 20)
572 | ((r2 & 0x7f) << 13)
573 | (qp & 0x3f);
574}
575
576static inline uint64_t tcg_opc_i29(int qp, uint64_t opc, int r1, int r3)
577{
578 return opc
579 | ((r3 & 0x7f) << 20)
580 | ((r1 & 0x7f) << 6)
581 | (qp & 0x3f);
582}
583
584static inline uint64_t tcg_opc_l2(uint64_t imm)
585{
586 return (imm & 0x7fffffffffc00000ull) >> 22;
587}
588
589static inline uint64_t tcg_opc_l3(uint64_t imm)
590{
591 return (imm & 0x07fffffffff00000ull) >> 18;
592}
593
Richard Henderson6f65c782013-09-05 12:11:27 -0400594#define tcg_opc_l4 tcg_opc_l3
595
Aurelien Jarno477ba622010-03-29 02:12:51 +0200596static inline uint64_t tcg_opc_m1(int qp, uint64_t opc, int r1, int r3)
597{
598 return opc
599 | ((r3 & 0x7f) << 20)
600 | ((r1 & 0x7f) << 6)
601 | (qp & 0x3f);
602}
603
604static inline uint64_t tcg_opc_m3(int qp, uint64_t opc, int r1,
605 int r3, uint64_t imm)
606{
607 return opc
608 | ((imm & 0x100) << 28) /* s */
609 | ((imm & 0x080) << 20) /* i */
610 | ((imm & 0x07f) << 13) /* imm7b */
611 | ((r3 & 0x7f) << 20)
612 | ((r1 & 0x7f) << 6)
613 | (qp & 0x3f);
614}
615
616static inline uint64_t tcg_opc_m4(int qp, uint64_t opc, int r2, int r3)
617{
618 return opc
619 | ((r3 & 0x7f) << 20)
620 | ((r2 & 0x7f) << 13)
621 | (qp & 0x3f);
622}
623
624static inline uint64_t tcg_opc_m18(int qp, uint64_t opc, int f1, int r2)
625{
626 return opc
627 | ((r2 & 0x7f) << 13)
628 | ((f1 & 0x7f) << 6)
629 | (qp & 0x3f);
630}
631
632static inline uint64_t tcg_opc_m19(int qp, uint64_t opc, int r1, int f2)
633{
634 return opc
635 | ((f2 & 0x7f) << 13)
636 | ((r1 & 0x7f) << 6)
637 | (qp & 0x3f);
638}
639
640static inline uint64_t tcg_opc_m34(int qp, uint64_t opc, int r1,
641 int sof, int sol, int sor)
642{
643 return opc
644 | ((sor & 0x0f) << 27)
645 | ((sol & 0x7f) << 20)
646 | ((sof & 0x7f) << 13)
647 | ((r1 & 0x7f) << 6)
648 | (qp & 0x3f);
649}
650
651static inline uint64_t tcg_opc_m48(int qp, uint64_t opc, uint64_t imm)
652{
653 return opc
654 | ((imm & 0x100000) << 16) /* i */
655 | ((imm & 0x0fffff) << 6) /* imm20a */
656 | (qp & 0x3f);
657}
658
659static inline uint64_t tcg_opc_x2(int qp, uint64_t opc,
660 int r1, uint64_t imm)
661{
662 return opc
663 | ((imm & 0x8000000000000000ull) >> 27) /* i */
664 | (imm & 0x0000000000200000ull) /* ic */
665 | ((imm & 0x00000000001f0000ull) << 6) /* imm5c */
666 | ((imm & 0x000000000000ff80ull) << 20) /* imm9d */
667 | ((imm & 0x000000000000007full) << 13) /* imm7b */
668 | ((r1 & 0x7f) << 6)
669 | (qp & 0x3f);
670}
671
672static inline uint64_t tcg_opc_x3(int qp, uint64_t opc, uint64_t imm)
673{
674 return opc
675 | ((imm & 0x0800000000000000ull) >> 23) /* i */
676 | ((imm & 0x00000000000fffffull) << 13) /* imm20b */
677 | (qp & 0x3f);
678}
679
Richard Henderson6f65c782013-09-05 12:11:27 -0400680static inline uint64_t tcg_opc_x4(int qp, uint64_t opc, int b1, uint64_t imm)
681{
682 return opc
683 | ((imm & 0x0800000000000000ull) >> 23) /* i */
684 | ((imm & 0x00000000000fffffull) << 13) /* imm20b */
685 | ((b1 & 0x7) << 6)
686 | (qp & 0x3f);
687}
688
Aurelien Jarno477ba622010-03-29 02:12:51 +0200689
690/*
Richard Henderson5588ff22014-04-25 13:24:23 -0400691 * Relocations - Note that we never encode branches elsewhere than slot 2.
Aurelien Jarno477ba622010-03-29 02:12:51 +0200692 */
693
Richard Henderson5588ff22014-04-25 13:24:23 -0400694static void reloc_pcrel21b_slot2(tcg_insn_unit *pc, tcg_insn_unit *target)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200695{
Richard Henderson5588ff22014-04-25 13:24:23 -0400696 uint64_t imm = target - pc;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200697
Richard Henderson5588ff22014-04-25 13:24:23 -0400698 pc->hi = (pc->hi & 0xf700000fffffffffull)
699 | ((imm & 0x100000) << 39) /* s */
700 | ((imm & 0x0fffff) << 36); /* imm20b */
Aurelien Jarno477ba622010-03-29 02:12:51 +0200701}
702
Richard Henderson5588ff22014-04-25 13:24:23 -0400703static uint64_t get_reloc_pcrel21b_slot2(tcg_insn_unit *pc)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200704{
Richard Henderson5588ff22014-04-25 13:24:23 -0400705 int64_t high = pc->hi;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200706
Richard Henderson5588ff22014-04-25 13:24:23 -0400707 return ((high >> 39) & 0x100000) + /* s */
708 ((high >> 36) & 0x0fffff); /* imm20b */
Aurelien Jarno477ba622010-03-29 02:12:51 +0200709}
710
Richard Henderson5588ff22014-04-25 13:24:23 -0400711static void patch_reloc(tcg_insn_unit *code_ptr, int type,
Richard Henderson2ba7fae22013-08-20 15:30:10 -0700712 intptr_t value, intptr_t addend)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200713{
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +0200714 tcg_debug_assert(addend == 0);
715 tcg_debug_assert(type == R_IA64_PCREL21B);
Richard Henderson5588ff22014-04-25 13:24:23 -0400716 reloc_pcrel21b_slot2(code_ptr, (tcg_insn_unit *)value);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200717}
718
719/*
720 * Constraints
721 */
722
723/* parse target specific constraints */
Richard Henderson069ea732016-11-18 11:50:59 +0100724static const char *target_parse_constraint(TCGArgConstraint *ct,
725 const char *ct_str, TCGType type)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200726{
Richard Henderson069ea732016-11-18 11:50:59 +0100727 switch(*ct_str++) {
Aurelien Jarno477ba622010-03-29 02:12:51 +0200728 case 'r':
729 ct->ct |= TCG_CT_REG;
730 tcg_regset_set(ct->u.regs, 0xffffffffffffffffull);
731 break;
732 case 'I':
733 ct->ct |= TCG_CT_CONST_S22;
734 break;
735 case 'S':
736 ct->ct |= TCG_CT_REG;
737 tcg_regset_set(ct->u.regs, 0xffffffffffffffffull);
738#if defined(CONFIG_SOFTMMU)
739 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R56);
740 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R57);
Richard Henderson4bdd5472013-09-06 00:38:52 -0400741 tcg_regset_reset_reg(ct->u.regs, TCG_REG_R58);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200742#endif
743 break;
744 case 'Z':
745 /* We are cheating a bit here, using the fact that the register
746 r0 is also the register number 0. Hence there is no need
747 to check for const_args in each instruction. */
748 ct->ct |= TCG_CT_CONST_ZERO;
749 break;
750 default:
Richard Henderson069ea732016-11-18 11:50:59 +0100751 return NULL;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200752 }
Richard Henderson069ea732016-11-18 11:50:59 +0100753 return ct_str;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200754}
755
756/* test if a constant matches the constraint */
Richard Hendersonf6c6afc2014-03-30 21:22:11 -0700757static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200758 const TCGArgConstraint *arg_ct)
759{
760 int ct;
761 ct = arg_ct->ct;
762 if (ct & TCG_CT_CONST)
763 return 1;
764 else if ((ct & TCG_CT_CONST_ZERO) && val == 0)
765 return 1;
766 else if ((ct & TCG_CT_CONST_S22) && val == ((int32_t)val << 10) >> 10)
767 return 1;
768 else
769 return 0;
770}
771
772/*
773 * Code generation
774 */
775
Richard Henderson5588ff22014-04-25 13:24:23 -0400776static tcg_insn_unit *tb_ret_addr;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200777
778static inline void tcg_out_bundle(TCGContext *s, int template,
779 uint64_t slot0, uint64_t slot1,
780 uint64_t slot2)
781{
782 template &= 0x1f; /* 5 bits */
783 slot0 &= 0x1ffffffffffull; /* 41 bits */
784 slot1 &= 0x1ffffffffffull; /* 41 bits */
785 slot2 &= 0x1ffffffffffull; /* 41 bits */
786
Richard Henderson5588ff22014-04-25 13:24:23 -0400787 *s->code_ptr++ = (tcg_insn_unit){
788 (slot1 << 46) | (slot0 << 5) | template,
789 (slot2 << 23) | (slot1 >> 18)
790 };
Aurelien Jarno477ba622010-03-29 02:12:51 +0200791}
792
Richard Henderson3b9ccdc2013-09-05 18:48:42 -0400793static inline uint64_t tcg_opc_mov_a(int qp, TCGReg dst, TCGReg src)
794{
795 return tcg_opc_a4(qp, OPC_ADDS_A4, dst, 0, src);
796}
797
Richard Henderson3b6dac32010-06-02 17:26:55 -0700798static inline void tcg_out_mov(TCGContext *s, TCGType type,
Richard Henderson2a534af2011-11-09 08:03:34 +0000799 TCGReg ret, TCGReg arg)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200800{
801 tcg_out_bundle(s, mmI,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400802 INSN_NOP_M,
803 INSN_NOP_M,
Richard Henderson3b9ccdc2013-09-05 18:48:42 -0400804 tcg_opc_mov_a(TCG_REG_P0, ret, arg));
Aurelien Jarno477ba622010-03-29 02:12:51 +0200805}
806
Richard Hendersonfa0cdb62013-09-05 18:56:39 -0400807static inline uint64_t tcg_opc_movi_a(int qp, TCGReg dst, int64_t src)
808{
Aurelien Jarnoeabb7b92016-04-21 10:48:49 +0200809 tcg_debug_assert(src == sextract64(src, 0, 22));
Richard Hendersonfa0cdb62013-09-05 18:56:39 -0400810 return tcg_opc_a5(qp, OPC_ADDL_A5, dst, src, TCG_REG_R0);
811}
812
Aurelien Jarno477ba622010-03-29 02:12:51 +0200813static inline void tcg_out_movi(TCGContext *s, TCGType type,
Richard Henderson2a534af2011-11-09 08:03:34 +0000814 TCGReg reg, tcg_target_long arg)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200815{
816 tcg_out_bundle(s, mLX,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400817 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200818 tcg_opc_l2 (arg),
819 tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, reg, arg));
820}
821
Richard Hendersonbec16312015-02-13 13:39:54 -0800822static void tcg_out_br(TCGContext *s, TCGLabel *l)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200823{
Richard Henderson5588ff22014-04-25 13:24:23 -0400824 uint64_t imm;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200825
Aurelien Jarno56779032011-01-10 18:30:05 +0100826 /* We pay attention here to not modify the branch target by reading
827 the existing value and using it again. This ensure that caches and
828 memory are kept coherent during retranslation. */
Richard Henderson5588ff22014-04-25 13:24:23 -0400829 if (l->has_value) {
830 imm = l->u.value_ptr - s->code_ptr;
831 } else {
832 imm = get_reloc_pcrel21b_slot2(s->code_ptr);
Richard Hendersonbec16312015-02-13 13:39:54 -0800833 tcg_out_reloc(s, s->code_ptr, R_IA64_PCREL21B, l, 0);
Richard Henderson5588ff22014-04-25 13:24:23 -0400834 }
835
Aurelien Jarno477ba622010-03-29 02:12:51 +0200836 tcg_out_bundle(s, mmB,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400837 INSN_NOP_M,
838 INSN_NOP_M,
Richard Henderson5588ff22014-04-25 13:24:23 -0400839 tcg_opc_b1(TCG_REG_P0, OPC_BR_SPTK_MANY_B1, imm));
Aurelien Jarno477ba622010-03-29 02:12:51 +0200840}
841
Richard Henderson5588ff22014-04-25 13:24:23 -0400842static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *desc)
Richard Henderson6f65c782013-09-05 12:11:27 -0400843{
Richard Henderson5588ff22014-04-25 13:24:23 -0400844 uintptr_t func = desc->lo, gp = desc->hi, disp;
845
Richard Henderson6f65c782013-09-05 12:11:27 -0400846 /* Look through the function descriptor. */
Richard Henderson6f65c782013-09-05 12:11:27 -0400847 tcg_out_bundle(s, mlx,
848 INSN_NOP_M,
Richard Henderson5588ff22014-04-25 13:24:23 -0400849 tcg_opc_l2 (gp),
850 tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R1, gp));
851 disp = (tcg_insn_unit *)func - s->code_ptr;
Richard Henderson6f65c782013-09-05 12:11:27 -0400852 tcg_out_bundle(s, mLX,
853 INSN_NOP_M,
854 tcg_opc_l4 (disp),
855 tcg_opc_x4 (TCG_REG_P0, OPC_BRL_CALL_SPTK_MANY_X4,
856 TCG_REG_B0, disp));
857}
858
Aurelien Jarno477ba622010-03-29 02:12:51 +0200859static void tcg_out_exit_tb(TCGContext *s, tcg_target_long arg)
860{
Richard Hendersondcf91772013-10-31 15:19:23 -0400861 uint64_t imm, opc1;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200862
Richard Hendersondcf91772013-10-31 15:19:23 -0400863 /* At least arg == 0 is a common operation. */
864 if (arg == sextract64(arg, 0, 22)) {
865 opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R8, arg);
866 } else {
867 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R8, arg);
868 opc1 = INSN_NOP_M;
869 }
Aurelien Jarno477ba622010-03-29 02:12:51 +0200870
Richard Henderson5588ff22014-04-25 13:24:23 -0400871 imm = tb_ret_addr - s->code_ptr;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200872
873 tcg_out_bundle(s, mLX,
Richard Hendersondcf91772013-10-31 15:19:23 -0400874 opc1,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200875 tcg_opc_l3 (imm),
876 tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, imm));
877}
878
879static inline void tcg_out_goto_tb(TCGContext *s, TCGArg arg)
880{
Sergey Fedorovf3091012016-04-10 23:35:45 +0300881 if (s->tb_jmp_insn_offset) {
Aurelien Jarno477ba622010-03-29 02:12:51 +0200882 /* direct jump method */
883 tcg_abort();
884 } else {
885 /* indirect jump method */
886 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2,
Sergey Fedorovf3091012016-04-10 23:35:45 +0300887 (tcg_target_long)(s->tb_jmp_target_addr + arg));
Aurelien Jarno477ba622010-03-29 02:12:51 +0200888 tcg_out_bundle(s, MmI,
889 tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1,
890 TCG_REG_R2, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -0400891 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200892 tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6,
893 TCG_REG_R2, 0));
894 tcg_out_bundle(s, mmB,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400895 INSN_NOP_M,
896 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200897 tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4,
898 TCG_REG_B6));
899 }
Sergey Fedorovf3091012016-04-10 23:35:45 +0300900 s->tb_jmp_reset_offset[arg] = tcg_current_code_size(s);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200901}
902
903static inline void tcg_out_jmp(TCGContext *s, TCGArg addr)
904{
905 tcg_out_bundle(s, mmI,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400906 INSN_NOP_M,
907 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200908 tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21, TCG_REG_B6, addr, 0));
909 tcg_out_bundle(s, mmB,
Richard Henderson5f7b1682013-09-04 19:00:52 -0400910 INSN_NOP_M,
911 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +0200912 tcg_opc_b4(TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
913}
914
915static inline void tcg_out_ld_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg,
916 TCGArg arg1, tcg_target_long arg2)
917{
918 if (arg2 == ((int16_t)arg2 >> 2) << 2) {
919 tcg_out_bundle(s, MmI,
920 tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4,
921 TCG_REG_R2, arg2, arg1),
922 tcg_opc_m1 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -0400923 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200924 } else {
925 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg2);
926 tcg_out_bundle(s, MmI,
927 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
928 TCG_REG_R2, TCG_REG_R2, arg1),
929 tcg_opc_m1 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -0400930 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200931 }
932}
933
934static inline void tcg_out_st_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg,
935 TCGArg arg1, tcg_target_long arg2)
936{
937 if (arg2 == ((int16_t)arg2 >> 2) << 2) {
938 tcg_out_bundle(s, MmI,
939 tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4,
940 TCG_REG_R2, arg2, arg1),
941 tcg_opc_m4 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -0400942 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200943 } else {
944 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, arg2);
945 tcg_out_bundle(s, MmI,
946 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
947 TCG_REG_R2, TCG_REG_R2, arg1),
948 tcg_opc_m4 (TCG_REG_P0, opc_m4, arg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -0400949 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200950 }
951}
952
Richard Henderson2a534af2011-11-09 08:03:34 +0000953static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
Richard Hendersona05b5b92013-08-20 17:07:26 -0700954 TCGReg arg1, intptr_t arg2)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200955{
956 if (type == TCG_TYPE_I32) {
957 tcg_out_ld_rel(s, OPC_LD4_M1, arg, arg1, arg2);
958 } else {
959 tcg_out_ld_rel(s, OPC_LD8_M1, arg, arg1, arg2);
960 }
961}
962
Richard Henderson2a534af2011-11-09 08:03:34 +0000963static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
Richard Hendersona05b5b92013-08-20 17:07:26 -0700964 TCGReg arg1, intptr_t arg2)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200965{
966 if (type == TCG_TYPE_I32) {
967 tcg_out_st_rel(s, OPC_ST4_M4, arg, arg1, arg2);
968 } else {
969 tcg_out_st_rel(s, OPC_ST8_M4, arg, arg1, arg2);
970 }
971}
972
Richard Henderson59d7c142016-06-19 22:59:13 -0700973static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
974 TCGReg base, intptr_t ofs)
975{
976 if (val == 0) {
977 tcg_out_st(s, type, TCG_REG_R0, base, ofs);
978 return true;
979 }
980 return false;
981}
982
Richard Henderson25c9c732013-09-05 17:13:43 -0400983static inline void tcg_out_alu(TCGContext *s, uint64_t opc_a1, uint64_t opc_a3,
984 TCGReg ret, TCGArg arg1, int const_arg1,
985 TCGArg arg2, int const_arg2)
Aurelien Jarno477ba622010-03-29 02:12:51 +0200986{
Richard Henderson25c9c732013-09-05 17:13:43 -0400987 uint64_t opc1 = 0, opc2 = 0, opc3 = 0;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200988
989 if (const_arg2 && arg2 != 0) {
Richard Hendersonfa0cdb62013-09-05 18:56:39 -0400990 opc2 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R3, arg2);
Aurelien Jarno477ba622010-03-29 02:12:51 +0200991 arg2 = TCG_REG_R3;
Aurelien Jarno477ba622010-03-29 02:12:51 +0200992 }
Richard Henderson25c9c732013-09-05 17:13:43 -0400993 if (const_arg1 && arg1 != 0) {
994 if (opc_a3 && arg1 == (int8_t)arg1) {
995 opc3 = tcg_opc_a3(TCG_REG_P0, opc_a3, ret, arg1, arg2);
996 } else {
Richard Hendersonfa0cdb62013-09-05 18:56:39 -0400997 opc1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, arg1);
Richard Henderson25c9c732013-09-05 17:13:43 -0400998 arg1 = TCG_REG_R2;
999 }
1000 }
1001 if (opc3 == 0) {
1002 opc3 = tcg_opc_a1(TCG_REG_P0, opc_a1, ret, arg1, arg2);
1003 }
Aurelien Jarno477ba622010-03-29 02:12:51 +02001004
Richard Henderson3c289cb2013-09-05 15:56:44 -04001005 tcg_out_bundle(s, (opc1 || opc2 ? mII : miI),
1006 opc1 ? opc1 : INSN_NOP_M,
1007 opc2 ? opc2 : INSN_NOP_I,
Richard Henderson25c9c732013-09-05 17:13:43 -04001008 opc3);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001009}
1010
Richard Henderson86420882013-09-05 16:15:13 -04001011static inline void tcg_out_add(TCGContext *s, TCGReg ret, TCGReg arg1,
1012 TCGArg arg2, int const_arg2)
1013{
1014 if (const_arg2 && arg2 == sextract64(arg2, 0, 14)) {
1015 tcg_out_bundle(s, mmI,
1016 INSN_NOP_M,
1017 INSN_NOP_M,
1018 tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, arg2, arg1));
1019 } else {
Richard Henderson25c9c732013-09-05 17:13:43 -04001020 tcg_out_alu(s, OPC_ADD_A1, 0, ret, arg1, 0, arg2, const_arg2);
Richard Henderson86420882013-09-05 16:15:13 -04001021 }
1022}
1023
Richard Hendersonf940fb02013-09-05 16:44:18 -04001024static inline void tcg_out_sub(TCGContext *s, TCGReg ret, TCGArg arg1,
1025 int const_arg1, TCGArg arg2, int const_arg2)
1026{
Richard Henderson25c9c732013-09-05 17:13:43 -04001027 if (!const_arg1 && const_arg2 && -arg2 == sextract64(-arg2, 0, 14)) {
Richard Hendersonf940fb02013-09-05 16:44:18 -04001028 tcg_out_bundle(s, mmI,
1029 INSN_NOP_M,
1030 INSN_NOP_M,
1031 tcg_opc_a4(TCG_REG_P0, OPC_ADDS_A4, ret, -arg2, arg1));
1032 } else {
Richard Henderson25c9c732013-09-05 17:13:43 -04001033 tcg_out_alu(s, OPC_SUB_A1, OPC_SUB_A3, ret,
1034 arg1, const_arg1, arg2, const_arg2);
Richard Hendersonf940fb02013-09-05 16:44:18 -04001035 }
1036}
1037
Aurelien Jarno477ba622010-03-29 02:12:51 +02001038static inline void tcg_out_eqv(TCGContext *s, TCGArg ret,
1039 TCGArg arg1, int const_arg1,
1040 TCGArg arg2, int const_arg2)
1041{
1042 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001043 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001044 tcg_opc_a1 (TCG_REG_P0, OPC_XOR_A1, ret, arg1, arg2),
1045 tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
1046}
1047
1048static inline void tcg_out_nand(TCGContext *s, TCGArg ret,
1049 TCGArg arg1, int const_arg1,
1050 TCGArg arg2, int const_arg2)
1051{
1052 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001053 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001054 tcg_opc_a1 (TCG_REG_P0, OPC_AND_A1, ret, arg1, arg2),
1055 tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
1056}
1057
1058static inline void tcg_out_nor(TCGContext *s, TCGArg ret,
1059 TCGArg arg1, int const_arg1,
1060 TCGArg arg2, int const_arg2)
1061{
1062 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001063 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001064 tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret, arg1, arg2),
1065 tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, ret, -1, ret));
1066}
1067
1068static inline void tcg_out_orc(TCGContext *s, TCGArg ret,
1069 TCGArg arg1, int const_arg1,
1070 TCGArg arg2, int const_arg2)
1071{
1072 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001073 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001074 tcg_opc_a3 (TCG_REG_P0, OPC_ANDCM_A3, TCG_REG_R2, -1, arg2),
1075 tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret, arg1, TCG_REG_R2));
1076}
1077
1078static inline void tcg_out_mul(TCGContext *s, TCGArg ret,
1079 TCGArg arg1, TCGArg arg2)
1080{
1081 tcg_out_bundle(s, mmI,
1082 tcg_opc_m18(TCG_REG_P0, OPC_SETF_SIG_M18, TCG_REG_F6, arg1),
1083 tcg_opc_m18(TCG_REG_P0, OPC_SETF_SIG_M18, TCG_REG_F7, arg2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001084 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001085 tcg_out_bundle(s, mmF,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001086 INSN_NOP_M,
1087 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001088 tcg_opc_f2 (TCG_REG_P0, OPC_XMA_L_F2, TCG_REG_F6, TCG_REG_F6,
1089 TCG_REG_F7, TCG_REG_F0));
1090 tcg_out_bundle(s, miI,
1091 tcg_opc_m19(TCG_REG_P0, OPC_GETF_SIG_M19, ret, TCG_REG_F6),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001092 INSN_NOP_I,
1093 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001094}
1095
1096static inline void tcg_out_sar_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
1097 TCGArg arg2, int const_arg2)
1098{
1099 if (const_arg2) {
1100 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001101 INSN_NOP_M,
1102 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001103 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_I11,
1104 ret, arg1, arg2, 31 - arg2));
1105 } else {
1106 tcg_out_bundle(s, mII,
1107 tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3,
1108 TCG_REG_R3, 0x1f, arg2),
1109 tcg_opc_i29(TCG_REG_P0, OPC_SXT4_I29, TCG_REG_R2, arg1),
1110 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_I5, ret,
1111 TCG_REG_R2, TCG_REG_R3));
1112 }
1113}
1114
1115static inline void tcg_out_sar_i64(TCGContext *s, TCGArg ret, TCGArg arg1,
1116 TCGArg arg2, int const_arg2)
1117{
1118 if (const_arg2) {
1119 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001120 INSN_NOP_M,
1121 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001122 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_I11,
1123 ret, arg1, arg2, 63 - arg2));
1124 } else {
1125 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001126 INSN_NOP_M,
1127 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001128 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_I5, ret, arg1, arg2));
1129 }
1130}
1131
1132static inline void tcg_out_shl_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
1133 TCGArg arg2, int const_arg2)
1134{
1135 if (const_arg2) {
1136 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001137 INSN_NOP_M,
1138 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001139 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret,
1140 arg1, 63 - arg2, 31 - arg2));
1141 } else {
1142 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001143 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001144 tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R2,
1145 0x1f, arg2),
1146 tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, ret,
1147 arg1, TCG_REG_R2));
1148 }
1149}
1150
1151static inline void tcg_out_shl_i64(TCGContext *s, TCGArg ret, TCGArg arg1,
1152 TCGArg arg2, int const_arg2)
1153{
1154 if (const_arg2) {
1155 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001156 INSN_NOP_M,
1157 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001158 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret,
1159 arg1, 63 - arg2, 63 - arg2));
1160 } else {
1161 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001162 INSN_NOP_M,
1163 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001164 tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, ret,
1165 arg1, arg2));
1166 }
1167}
1168
1169static inline void tcg_out_shr_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
1170 TCGArg arg2, int const_arg2)
1171{
1172 if (const_arg2) {
1173 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001174 INSN_NOP_M,
1175 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001176 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
1177 arg1, arg2, 31 - arg2));
1178 } else {
1179 tcg_out_bundle(s, mII,
1180 tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R3,
1181 0x1f, arg2),
1182 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29, TCG_REG_R2, arg1),
1183 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
1184 TCG_REG_R2, TCG_REG_R3));
1185 }
1186}
1187
1188static inline void tcg_out_shr_i64(TCGContext *s, TCGArg ret, TCGArg arg1,
1189 TCGArg arg2, int const_arg2)
1190{
1191 if (const_arg2) {
1192 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001193 INSN_NOP_M,
1194 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001195 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
1196 arg1, arg2, 63 - arg2));
1197 } else {
1198 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001199 INSN_NOP_M,
1200 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001201 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
1202 arg1, arg2));
1203 }
1204}
1205
1206static inline void tcg_out_rotl_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
1207 TCGArg arg2, int const_arg2)
1208{
1209 if (const_arg2) {
1210 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001211 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001212 tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
1213 TCG_REG_R2, arg1, arg1),
1214 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
1215 TCG_REG_R2, 32 - arg2, 31));
1216 } else {
1217 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001218 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001219 tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
1220 TCG_REG_R2, arg1, arg1),
1221 tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R3,
1222 0x1f, arg2));
1223 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001224 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001225 tcg_opc_a3 (TCG_REG_P0, OPC_SUB_A3, TCG_REG_R3,
1226 0x20, TCG_REG_R3),
1227 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
1228 TCG_REG_R2, TCG_REG_R3));
1229 }
1230}
1231
1232static inline void tcg_out_rotl_i64(TCGContext *s, TCGArg ret, TCGArg arg1,
1233 TCGArg arg2, int const_arg2)
1234{
1235 if (const_arg2) {
1236 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001237 INSN_NOP_M,
1238 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001239 tcg_opc_i10(TCG_REG_P0, OPC_SHRP_I10, ret, arg1,
1240 arg1, 0x40 - arg2));
1241 } else {
1242 tcg_out_bundle(s, mII,
1243 tcg_opc_a3 (TCG_REG_P0, OPC_SUB_A3, TCG_REG_R2,
1244 0x40, arg2),
1245 tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, TCG_REG_R3,
1246 arg1, arg2),
1247 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, TCG_REG_R2,
1248 arg1, TCG_REG_R2));
1249 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001250 INSN_NOP_M,
1251 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001252 tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret,
1253 TCG_REG_R2, TCG_REG_R3));
1254 }
1255}
1256
1257static inline void tcg_out_rotr_i32(TCGContext *s, TCGArg ret, TCGArg arg1,
1258 TCGArg arg2, int const_arg2)
1259{
1260 if (const_arg2) {
1261 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001262 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001263 tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
1264 TCG_REG_R2, arg1, arg1),
1265 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, ret,
1266 TCG_REG_R2, arg2, 31));
1267 } else {
1268 tcg_out_bundle(s, mII,
1269 tcg_opc_a3 (TCG_REG_P0, OPC_AND_A3, TCG_REG_R3,
1270 0x1f, arg2),
1271 tcg_opc_i2 (TCG_REG_P0, OPC_UNPACK4_L_I2,
1272 TCG_REG_R2, arg1, arg1),
1273 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, ret,
1274 TCG_REG_R2, TCG_REG_R3));
1275 }
1276}
1277
1278static inline void tcg_out_rotr_i64(TCGContext *s, TCGArg ret, TCGArg arg1,
1279 TCGArg arg2, int const_arg2)
1280{
1281 if (const_arg2) {
1282 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001283 INSN_NOP_M,
1284 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001285 tcg_opc_i10(TCG_REG_P0, OPC_SHRP_I10, ret, arg1,
1286 arg1, arg2));
1287 } else {
1288 tcg_out_bundle(s, mII,
1289 tcg_opc_a3 (TCG_REG_P0, OPC_SUB_A3, TCG_REG_R2,
1290 0x40, arg2),
1291 tcg_opc_i5 (TCG_REG_P0, OPC_SHR_U_I5, TCG_REG_R3,
1292 arg1, arg2),
1293 tcg_opc_i7 (TCG_REG_P0, OPC_SHL_I7, TCG_REG_R2,
1294 arg1, TCG_REG_R2));
1295 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001296 INSN_NOP_M,
1297 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001298 tcg_opc_a1 (TCG_REG_P0, OPC_OR_A1, ret,
1299 TCG_REG_R2, TCG_REG_R3));
1300 }
1301}
1302
Richard Hendersondb008a82013-09-05 19:13:41 -04001303static const uint64_t opc_ext_i29[8] = {
1304 OPC_ZXT1_I29, OPC_ZXT2_I29, OPC_ZXT4_I29, 0,
1305 OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0
1306};
1307
1308static inline uint64_t tcg_opc_ext_i(int qp, TCGMemOp opc, TCGReg d, TCGReg s)
1309{
1310 if ((opc & MO_SIZE) == MO_64) {
1311 return tcg_opc_mov_a(qp, d, s);
1312 } else {
1313 return tcg_opc_i29(qp, opc_ext_i29[opc & MO_SSIZE], d, s);
1314 }
1315}
1316
Aurelien Jarno477ba622010-03-29 02:12:51 +02001317static inline void tcg_out_ext(TCGContext *s, uint64_t opc_i29,
1318 TCGArg ret, TCGArg arg)
1319{
1320 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001321 INSN_NOP_M,
1322 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001323 tcg_opc_i29(TCG_REG_P0, opc_i29, ret, arg));
1324}
1325
Richard Henderson463230d2013-09-05 19:20:40 -04001326static inline uint64_t tcg_opc_bswap64_i(int qp, TCGReg d, TCGReg s)
1327{
1328 return tcg_opc_i3(qp, OPC_MUX1_I3, d, s, 0xb);
1329}
1330
Aurelien Jarno477ba622010-03-29 02:12:51 +02001331static inline void tcg_out_bswap16(TCGContext *s, TCGArg ret, TCGArg arg)
1332{
1333 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001334 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001335 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 15, 15),
Richard Henderson463230d2013-09-05 19:20:40 -04001336 tcg_opc_bswap64_i(TCG_REG_P0, ret, ret));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001337}
1338
1339static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg)
1340{
1341 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001342 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001343 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, ret, arg, 31, 31),
Richard Henderson463230d2013-09-05 19:20:40 -04001344 tcg_opc_bswap64_i(TCG_REG_P0, ret, ret));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001345}
1346
1347static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
1348{
Aurelien Jarnoa3e28aa2011-01-10 01:39:49 +01001349 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001350 INSN_NOP_M,
1351 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001352 tcg_opc_bswap64_i(TCG_REG_P0, ret, arg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001353}
1354
Richard Hendersonc7d44752012-10-10 16:01:35 -07001355static inline void tcg_out_deposit(TCGContext *s, TCGArg ret, TCGArg a1,
1356 TCGArg a2, int const_a2, int pos, int len)
1357{
1358 uint64_t i1 = 0, i2 = 0;
1359 int cpos = 63 - pos, lm1 = len - 1;
1360
1361 if (const_a2) {
1362 /* Truncate the value of a constant a2 to the width of the field. */
1363 int mask = (1u << len) - 1;
1364 a2 &= mask;
1365
1366 if (a2 == 0 || a2 == mask) {
1367 /* 1-bit signed constant inserted into register. */
1368 i2 = tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, ret, a2, a1, cpos, lm1);
1369 } else {
1370 /* Otherwise, load any constant into a temporary. Do this into
1371 the first I slot to help out with cross-unit delays. */
Richard Hendersonfa0cdb62013-09-05 18:56:39 -04001372 i1 = tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, a2);
Richard Hendersonc7d44752012-10-10 16:01:35 -07001373 a2 = TCG_REG_R2;
1374 }
1375 }
1376 if (i2 == 0) {
1377 i2 = tcg_opc_i15(TCG_REG_P0, OPC_DEP_I15, ret, a2, a1, cpos, lm1);
1378 }
1379 tcg_out_bundle(s, (i1 ? mII : miI),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001380 INSN_NOP_M,
1381 i1 ? i1 : INSN_NOP_I,
Richard Hendersonc7d44752012-10-10 16:01:35 -07001382 i2);
1383}
1384
Aurelien Jarno477ba622010-03-29 02:12:51 +02001385static inline uint64_t tcg_opc_cmp_a(int qp, TCGCond cond, TCGArg arg1,
1386 TCGArg arg2, int cmp4)
1387{
1388 uint64_t opc_eq_a6, opc_lt_a6, opc_ltu_a6;
1389
1390 if (cmp4) {
1391 opc_eq_a6 = OPC_CMP4_EQ_A6;
1392 opc_lt_a6 = OPC_CMP4_LT_A6;
1393 opc_ltu_a6 = OPC_CMP4_LTU_A6;
1394 } else {
1395 opc_eq_a6 = OPC_CMP_EQ_A6;
1396 opc_lt_a6 = OPC_CMP_LT_A6;
1397 opc_ltu_a6 = OPC_CMP_LTU_A6;
1398 }
1399
1400 switch (cond) {
1401 case TCG_COND_EQ:
1402 return tcg_opc_a6 (qp, opc_eq_a6, TCG_REG_P6, TCG_REG_P7, arg1, arg2);
1403 case TCG_COND_NE:
1404 return tcg_opc_a6 (qp, opc_eq_a6, TCG_REG_P7, TCG_REG_P6, arg1, arg2);
1405 case TCG_COND_LT:
1406 return tcg_opc_a6 (qp, opc_lt_a6, TCG_REG_P6, TCG_REG_P7, arg1, arg2);
1407 case TCG_COND_LTU:
1408 return tcg_opc_a6 (qp, opc_ltu_a6, TCG_REG_P6, TCG_REG_P7, arg1, arg2);
1409 case TCG_COND_GE:
1410 return tcg_opc_a6 (qp, opc_lt_a6, TCG_REG_P7, TCG_REG_P6, arg1, arg2);
1411 case TCG_COND_GEU:
1412 return tcg_opc_a6 (qp, opc_ltu_a6, TCG_REG_P7, TCG_REG_P6, arg1, arg2);
1413 case TCG_COND_LE:
1414 return tcg_opc_a6 (qp, opc_lt_a6, TCG_REG_P7, TCG_REG_P6, arg2, arg1);
1415 case TCG_COND_LEU:
1416 return tcg_opc_a6 (qp, opc_ltu_a6, TCG_REG_P7, TCG_REG_P6, arg2, arg1);
1417 case TCG_COND_GT:
1418 return tcg_opc_a6 (qp, opc_lt_a6, TCG_REG_P6, TCG_REG_P7, arg2, arg1);
1419 case TCG_COND_GTU:
1420 return tcg_opc_a6 (qp, opc_ltu_a6, TCG_REG_P6, TCG_REG_P7, arg2, arg1);
1421 default:
1422 tcg_abort();
1423 break;
1424 }
1425}
1426
Richard Henderson6d264b32013-09-05 12:47:41 -04001427static inline void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
Richard Hendersonbec16312015-02-13 13:39:54 -08001428 TCGReg arg2, TCGLabel *l, int cmp4)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001429{
Richard Henderson5588ff22014-04-25 13:24:23 -04001430 uint64_t imm;
1431
1432 /* We pay attention here to not modify the branch target by reading
1433 the existing value and using it again. This ensure that caches and
1434 memory are kept coherent during retranslation. */
1435 if (l->has_value) {
1436 imm = l->u.value_ptr - s->code_ptr;
1437 } else {
1438 imm = get_reloc_pcrel21b_slot2(s->code_ptr);
Richard Hendersonbec16312015-02-13 13:39:54 -08001439 tcg_out_reloc(s, s->code_ptr, R_IA64_PCREL21B, l, 0);
Richard Henderson5588ff22014-04-25 13:24:23 -04001440 }
Aurelien Jarno477ba622010-03-29 02:12:51 +02001441
Richard Henderson6d264b32013-09-05 12:47:41 -04001442 tcg_out_bundle(s, miB,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001443 INSN_NOP_M,
Richard Henderson6d264b32013-09-05 12:47:41 -04001444 tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
Richard Henderson5588ff22014-04-25 13:24:23 -04001445 tcg_opc_b1(TCG_REG_P6, OPC_BR_DPTK_FEW_B1, imm));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001446}
1447
1448static inline void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg ret,
1449 TCGArg arg1, TCGArg arg2, int cmp4)
1450{
1451 tcg_out_bundle(s, MmI,
1452 tcg_opc_cmp_a(TCG_REG_P0, cond, arg1, arg2, cmp4),
Richard Hendersonfa0cdb62013-09-05 18:56:39 -04001453 tcg_opc_movi_a(TCG_REG_P6, ret, 1),
1454 tcg_opc_movi_a(TCG_REG_P7, ret, 0));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001455}
1456
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001457static inline void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGArg ret,
1458 TCGArg c1, TCGArg c2,
1459 TCGArg v1, int const_v1,
1460 TCGArg v2, int const_v2, int cmp4)
1461{
1462 uint64_t opc1, opc2;
1463
1464 if (const_v1) {
Richard Hendersonfa0cdb62013-09-05 18:56:39 -04001465 opc1 = tcg_opc_movi_a(TCG_REG_P6, ret, v1);
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001466 } else if (ret == v1) {
Richard Henderson5f7b1682013-09-04 19:00:52 -04001467 opc1 = INSN_NOP_M;
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001468 } else {
Richard Henderson3b9ccdc2013-09-05 18:48:42 -04001469 opc1 = tcg_opc_mov_a(TCG_REG_P6, ret, v1);
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001470 }
1471 if (const_v2) {
Richard Hendersonfa0cdb62013-09-05 18:56:39 -04001472 opc2 = tcg_opc_movi_a(TCG_REG_P7, ret, v2);
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001473 } else if (ret == v2) {
Richard Henderson5f7b1682013-09-04 19:00:52 -04001474 opc2 = INSN_NOP_I;
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001475 } else {
Richard Henderson3b9ccdc2013-09-05 18:48:42 -04001476 opc2 = tcg_opc_mov_a(TCG_REG_P7, ret, v2);
Aurelien Jarnob90cf712012-10-09 21:53:55 +02001477 }
1478
1479 tcg_out_bundle(s, MmI,
1480 tcg_opc_cmp_a(TCG_REG_P0, cond, c1, c2, cmp4),
1481 opc1,
1482 opc2);
1483}
1484
Aurelien Jarno477ba622010-03-29 02:12:51 +02001485#if defined(CONFIG_SOFTMMU)
Richard Henderson4c186ee2013-09-05 19:46:56 -04001486/* We're expecting to use an signed 22-bit immediate add. */
1487QEMU_BUILD_BUG_ON(offsetof(CPUArchState, tlb_table[NB_MMU_MODES - 1][1])
1488 > 0x1fffff)
1489
Aurelien Jarno477ba622010-03-29 02:12:51 +02001490/* Load and compare a TLB entry, and return the result in (p6, p7).
Richard Henderson1f91f392013-09-05 20:32:49 -04001491 R2 is loaded with the addend TLB entry.
Richard Henderson4c186ee2013-09-05 19:46:56 -04001492 R57 is loaded with the address, zero extented on 32-bit targets.
Richard Hendersonb672cf62013-09-05 20:02:51 -04001493 R1, R3 are clobbered, leaving R56 free for...
1494 BSWAP_1, BSWAP_2 and I-slot insns for swapping data for store. */
Richard Henderson4c186ee2013-09-05 19:46:56 -04001495static inline void tcg_out_qemu_tlb(TCGContext *s, TCGReg addr_reg,
Richard Henderson85aa8082016-07-14 12:43:06 -07001496 TCGMemOp opc, int off_rw, int off_add,
Richard Hendersonb672cf62013-09-05 20:02:51 -04001497 uint64_t bswap1, uint64_t bswap2)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001498{
Richard Henderson85aa8082016-07-14 12:43:06 -07001499 unsigned s_bits = opc & MO_SIZE;
1500 unsigned a_bits = get_alignment_bits(opc);
1501
1502 /* We don't support unaligned accesses, but overalignment is easy. */
1503 if (a_bits < s_bits) {
1504 a_bits = s_bits;
1505 }
1506
1507 /*
Richard Henderson4c186ee2013-09-05 19:46:56 -04001508 .mii
1509 mov r2 = off_rw
1510 extr.u r3 = addr_reg, ... # extract tlb page
1511 zxt4 r57 = addr_reg # or mov for 64-bit guest
1512 ;;
1513 .mii
1514 addl r2 = r2, areg0
1515 shl r3 = r3, cteb # via dep.z
1516 dep r1 = 0, r57, ... # zero page ofs, keep align
1517 ;;
1518 .mmi
1519 add r2 = r2, r3
1520 ;;
1521 ld4 r3 = [r2], off_add-off_rw # or ld8 for 64-bit guest
1522 nop
1523 ;;
1524 .mmi
1525 nop
1526 cmp.eq p6, p7 = r3, r58
1527 nop
1528 ;;
Richard Henderson85aa8082016-07-14 12:43:06 -07001529 */
Richard Henderson4c186ee2013-09-05 19:46:56 -04001530 tcg_out_bundle(s, miI,
1531 tcg_opc_movi_a(TCG_REG_P0, TCG_REG_R2, off_rw),
1532 tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11, TCG_REG_R3,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001533 addr_reg, TARGET_PAGE_BITS, CPU_TLB_BITS - 1),
Richard Hendersondb008a82013-09-05 19:13:41 -04001534 tcg_opc_ext_i(TCG_REG_P0,
1535 TARGET_LONG_BITS == 32 ? MO_UL : MO_Q,
Richard Henderson4c186ee2013-09-05 19:46:56 -04001536 TCG_REG_R57, addr_reg));
1537 tcg_out_bundle(s, miI,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001538 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
Richard Henderson4c186ee2013-09-05 19:46:56 -04001539 TCG_REG_R2, TCG_AREG0),
1540 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12, TCG_REG_R3,
1541 TCG_REG_R3, 63 - CPU_TLB_ENTRY_BITS,
1542 63 - CPU_TLB_ENTRY_BITS),
1543 tcg_opc_i14(TCG_REG_P0, OPC_DEP_I14, TCG_REG_R1, 0,
Richard Henderson85aa8082016-07-14 12:43:06 -07001544 TCG_REG_R57, 63 - a_bits,
1545 TARGET_PAGE_BITS - a_bits - 1));
Richard Henderson4c186ee2013-09-05 19:46:56 -04001546 tcg_out_bundle(s, MmI,
1547 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1,
1548 TCG_REG_R2, TCG_REG_R2, TCG_REG_R3),
Richard Henderson650a2172010-11-22 14:57:56 -08001549 tcg_opc_m3 (TCG_REG_P0,
1550 (TARGET_LONG_BITS == 32
Richard Henderson4c186ee2013-09-05 19:46:56 -04001551 ? OPC_LD4_M3 : OPC_LD8_M3), TCG_REG_R3,
1552 TCG_REG_R2, off_add - off_rw),
Richard Hendersonb672cf62013-09-05 20:02:51 -04001553 bswap1);
Richard Henderson4c186ee2013-09-05 19:46:56 -04001554 tcg_out_bundle(s, mmI,
Richard Henderson1f91f392013-09-05 20:32:49 -04001555 tcg_opc_m1 (TCG_REG_P0, OPC_LD8_M1, TCG_REG_R2, TCG_REG_R2),
Aurelien Jarno477ba622010-03-29 02:12:51 +02001556 tcg_opc_a6 (TCG_REG_P0, OPC_CMP_EQ_A6, TCG_REG_P6,
Richard Henderson4c186ee2013-09-05 19:46:56 -04001557 TCG_REG_P7, TCG_REG_R1, TCG_REG_R3),
Richard Hendersonb672cf62013-09-05 20:02:51 -04001558 bswap2);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001559}
1560
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001561typedef struct TCGLabelQemuLdst {
1562 bool is_ld;
1563 TCGMemOp size;
Richard Henderson5588ff22014-04-25 13:24:23 -04001564 tcg_insn_unit *label_ptr; /* label pointers to be updated */
Richard Henderson3f626792014-09-30 07:25:30 -07001565 struct TCGLabelQemuLdst *next;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001566} TCGLabelQemuLdst;
1567
1568typedef struct TCGBackendData {
Richard Henderson3f626792014-09-30 07:25:30 -07001569 TCGLabelQemuLdst *labels;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001570} TCGBackendData;
1571
1572static inline void tcg_out_tb_init(TCGContext *s)
1573{
Richard Henderson3f626792014-09-30 07:25:30 -07001574 s->be->labels = NULL;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001575}
1576
1577static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOp opc,
Richard Henderson5588ff22014-04-25 13:24:23 -04001578 tcg_insn_unit *label_ptr)
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001579{
1580 TCGBackendData *be = s->be;
Richard Henderson3f626792014-09-30 07:25:30 -07001581 TCGLabelQemuLdst *l = tcg_malloc(sizeof(*l));
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001582
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001583 l->is_ld = is_ld;
1584 l->size = opc & MO_SIZE;
1585 l->label_ptr = label_ptr;
Richard Henderson3f626792014-09-30 07:25:30 -07001586 l->next = be->labels;
1587 be->labels = l;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001588}
1589
Richard Henderson23dceda2015-12-02 13:59:59 -08001590static bool tcg_out_tb_finalize(TCGContext *s)
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001591{
1592 static const void * const helpers[8] = {
1593 helper_ret_stb_mmu,
1594 helper_le_stw_mmu,
1595 helper_le_stl_mmu,
1596 helper_le_stq_mmu,
1597 helper_ret_ldub_mmu,
1598 helper_le_lduw_mmu,
1599 helper_le_ldul_mmu,
1600 helper_le_ldq_mmu,
1601 };
Richard Henderson5588ff22014-04-25 13:24:23 -04001602 tcg_insn_unit *thunks[8] = { };
Richard Henderson3f626792014-09-30 07:25:30 -07001603 TCGLabelQemuLdst *l;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001604
Richard Henderson3f626792014-09-30 07:25:30 -07001605 for (l = s->be->labels; l != NULL; l = l->next) {
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001606 long x = l->is_ld * 4 + l->size;
Richard Henderson5588ff22014-04-25 13:24:23 -04001607 tcg_insn_unit *dest = thunks[x];
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001608
1609 /* The out-of-line thunks are all the same; load the return address
1610 from B0, load the GP, and branch to the code. Note that we are
1611 always post-call, so the register window has rolled, so we're
Veres Lajos67cc32e2015-09-08 22:45:14 +01001612 using incoming parameter register numbers, not outgoing. */
Richard Henderson5588ff22014-04-25 13:24:23 -04001613 if (dest == NULL) {
1614 uintptr_t *desc = (uintptr_t *)helpers[x];
1615 uintptr_t func = desc[0], gp = desc[1], disp;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001616
Richard Henderson5588ff22014-04-25 13:24:23 -04001617 thunks[x] = dest = s->code_ptr;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001618
1619 tcg_out_bundle(s, mlx,
1620 INSN_NOP_M,
Richard Henderson5588ff22014-04-25 13:24:23 -04001621 tcg_opc_l2 (gp),
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001622 tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
Richard Henderson5588ff22014-04-25 13:24:23 -04001623 TCG_REG_R1, gp));
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001624 tcg_out_bundle(s, mii,
1625 INSN_NOP_M,
1626 INSN_NOP_I,
1627 tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
1628 l->is_ld ? TCG_REG_R35 : TCG_REG_R36,
1629 TCG_REG_B0));
Richard Henderson5588ff22014-04-25 13:24:23 -04001630 disp = (tcg_insn_unit *)func - s->code_ptr;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001631 tcg_out_bundle(s, mLX,
1632 INSN_NOP_M,
1633 tcg_opc_l3 (disp),
1634 tcg_opc_x3 (TCG_REG_P0, OPC_BRL_SPTK_MANY_X3, disp));
1635 }
1636
Richard Henderson5588ff22014-04-25 13:24:23 -04001637 reloc_pcrel21b_slot2(l->label_ptr, dest);
Richard Henderson23dceda2015-12-02 13:59:59 -08001638
1639 /* Test for (pending) buffer overflow. The assumption is that any
1640 one operation beginning below the high water mark cannot overrun
1641 the buffer completely. Thus we can test for overflow after
1642 generating code without having to check during generation. */
1643 if (unlikely((void *)s->code_ptr > s->code_gen_highwater)) {
1644 return false;
1645 }
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001646 }
Richard Henderson23dceda2015-12-02 13:59:59 -08001647 return true;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001648}
Aurelien Jarno477ba622010-03-29 02:12:51 +02001649
Richard Henderson0374f502014-03-04 09:35:30 -08001650static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001651{
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001652 static const uint64_t opc_ld_m1[4] = {
1653 OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
1654 };
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001655 int addr_reg, data_reg, mem_index;
Richard Henderson59227d52015-05-12 11:51:44 -07001656 TCGMemOpIdx oi;
Richard Henderson0374f502014-03-04 09:35:30 -08001657 TCGMemOp opc, s_bits;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001658 uint64_t fin1, fin2;
Richard Henderson5588ff22014-04-25 13:24:23 -04001659 tcg_insn_unit *label_ptr;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001660
Richard Henderson0374f502014-03-04 09:35:30 -08001661 data_reg = args[0];
1662 addr_reg = args[1];
Richard Henderson59227d52015-05-12 11:51:44 -07001663 oi = args[2];
1664 opc = get_memop(oi);
1665 mem_index = get_mmuidx(oi);
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001666 s_bits = opc & MO_SIZE;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001667
1668 /* Read the TLB entry */
Richard Henderson85aa8082016-07-14 12:43:06 -07001669 tcg_out_qemu_tlb(s, addr_reg, opc,
Andreas Färber9349b4f2012-03-14 01:38:32 +01001670 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read),
Richard Hendersonb672cf62013-09-05 20:02:51 -04001671 offsetof(CPUArchState, tlb_table[mem_index][0].addend),
1672 INSN_NOP_I, INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001673
1674 /* P6 is the fast path, and P7 the slow path */
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001675
Richard Henderson4bdd5472013-09-06 00:38:52 -04001676 fin2 = 0;
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001677 if (opc & MO_BSWAP) {
Richard Henderson4bdd5472013-09-06 00:38:52 -04001678 fin1 = tcg_opc_bswap64_i(TCG_REG_P0, data_reg, TCG_REG_R8);
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001679 if (s_bits < MO_64) {
1680 int shift = 64 - (8 << s_bits);
Richard Henderson4bdd5472013-09-06 00:38:52 -04001681 fin2 = (opc & MO_SIGN ? OPC_EXTR_I11 : OPC_EXTR_U_I11);
1682 fin2 = tcg_opc_i11(TCG_REG_P0, fin2,
1683 data_reg, data_reg, shift, 63 - shift);
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001684 }
Richard Henderson4bdd5472013-09-06 00:38:52 -04001685 } else {
1686 fin1 = tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, TCG_REG_R8);
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001687 }
1688
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001689 tcg_out_bundle(s, mmI,
Richard Henderson3b9ccdc2013-09-05 18:48:42 -04001690 tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
Richard Henderson1f91f392013-09-05 20:32:49 -04001691 tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
1692 TCG_REG_R2, TCG_REG_R57),
Richard Henderson3972ef62015-05-13 09:10:33 -07001693 tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R58, oi));
Richard Henderson5588ff22014-04-25 13:24:23 -04001694 label_ptr = s->code_ptr;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001695 tcg_out_bundle(s, miB,
Richard Hendersonaf9fe312013-09-05 20:50:54 -04001696 tcg_opc_m1 (TCG_REG_P6, opc_ld_m1[s_bits],
1697 TCG_REG_R8, TCG_REG_R2),
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001698 INSN_NOP_I,
1699 tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
Richard Henderson5588ff22014-04-25 13:24:23 -04001700 get_reloc_pcrel21b_slot2(label_ptr)));
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001701
1702 add_qemu_ldst_label(s, 1, opc, label_ptr);
Richard Henderson4bdd5472013-09-06 00:38:52 -04001703
1704 /* Note that we always use LE helper functions, so the bswap insns
1705 here for the fast path also apply to the slow path. */
1706 tcg_out_bundle(s, (fin2 ? mII : miI),
1707 INSN_NOP_M,
1708 fin1,
1709 fin2 ? fin2 : INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001710}
1711
Richard Henderson0374f502014-03-04 09:35:30 -08001712static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001713{
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001714 static const uint64_t opc_st_m4[4] = {
1715 OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
1716 };
Richard Henderson4bdd5472013-09-06 00:38:52 -04001717 TCGReg addr_reg, data_reg;
Richard Hendersonb672cf62013-09-05 20:02:51 -04001718 int mem_index;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001719 uint64_t pre1, pre2;
Richard Henderson59227d52015-05-12 11:51:44 -07001720 TCGMemOpIdx oi;
Richard Henderson0374f502014-03-04 09:35:30 -08001721 TCGMemOp opc, s_bits;
Richard Henderson5588ff22014-04-25 13:24:23 -04001722 tcg_insn_unit *label_ptr;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001723
Richard Henderson0374f502014-03-04 09:35:30 -08001724 data_reg = args[0];
1725 addr_reg = args[1];
Richard Henderson59227d52015-05-12 11:51:44 -07001726 oi = args[2];
1727 opc = get_memop(oi);
1728 mem_index = get_mmuidx(oi);
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001729 s_bits = opc & MO_SIZE;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001730
Richard Henderson4bdd5472013-09-06 00:38:52 -04001731 /* Note that we always use LE helper functions, so the bswap insns
1732 that are here for the fast path also apply to the slow path,
1733 and move the data into the argument register. */
1734 pre2 = INSN_NOP_I;
Richard Hendersonb672cf62013-09-05 20:02:51 -04001735 if (opc & MO_BSWAP) {
Richard Henderson4bdd5472013-09-06 00:38:52 -04001736 pre1 = tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R58, data_reg);
Richard Hendersonb672cf62013-09-05 20:02:51 -04001737 if (s_bits < MO_64) {
1738 int shift = 64 - (8 << s_bits);
Richard Henderson4bdd5472013-09-06 00:38:52 -04001739 pre2 = tcg_opc_i11(TCG_REG_P0, OPC_EXTR_U_I11,
1740 TCG_REG_R58, TCG_REG_R58, shift, 63 - shift);
Richard Hendersonb672cf62013-09-05 20:02:51 -04001741 }
Richard Henderson4bdd5472013-09-06 00:38:52 -04001742 } else {
1743 /* Just move the data into place for the slow path. */
1744 pre1 = tcg_opc_ext_i(TCG_REG_P0, opc, TCG_REG_R58, data_reg);
Richard Hendersonb672cf62013-09-05 20:02:51 -04001745 }
1746
Richard Henderson85aa8082016-07-14 12:43:06 -07001747 tcg_out_qemu_tlb(s, addr_reg, opc,
Andreas Färber9349b4f2012-03-14 01:38:32 +01001748 offsetof(CPUArchState, tlb_table[mem_index][0].addr_write),
Richard Hendersonb672cf62013-09-05 20:02:51 -04001749 offsetof(CPUArchState, tlb_table[mem_index][0].addend),
Richard Henderson4bdd5472013-09-06 00:38:52 -04001750 pre1, pre2);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001751
1752 /* P6 is the fast path, and P7 the slow path */
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001753 tcg_out_bundle(s, mmI,
Richard Henderson3b9ccdc2013-09-05 18:48:42 -04001754 tcg_opc_mov_a(TCG_REG_P7, TCG_REG_R56, TCG_AREG0),
Richard Henderson1f91f392013-09-05 20:32:49 -04001755 tcg_opc_a1 (TCG_REG_P6, OPC_ADD_A1, TCG_REG_R2,
1756 TCG_REG_R2, TCG_REG_R57),
Richard Henderson3972ef62015-05-13 09:10:33 -07001757 tcg_opc_movi_a(TCG_REG_P7, TCG_REG_R59, oi));
Richard Henderson5588ff22014-04-25 13:24:23 -04001758 label_ptr = s->code_ptr;
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001759 tcg_out_bundle(s, miB,
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001760 tcg_opc_m4 (TCG_REG_P6, opc_st_m4[s_bits],
Richard Henderson4bdd5472013-09-06 00:38:52 -04001761 TCG_REG_R58, TCG_REG_R2),
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001762 INSN_NOP_I,
1763 tcg_opc_b3 (TCG_REG_P7, OPC_BR_CALL_SPNT_FEW_B3, TCG_REG_B0,
Richard Henderson5588ff22014-04-25 13:24:23 -04001764 get_reloc_pcrel21b_slot2(label_ptr)));
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001765
1766 add_qemu_ldst_label(s, 0, opc, label_ptr);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001767}
1768
1769#else /* !CONFIG_SOFTMMU */
Richard Henderson3bf16cb2013-09-06 02:06:59 -04001770# include "tcg-be-null.h"
Aurelien Jarno477ba622010-03-29 02:12:51 +02001771
Richard Henderson0374f502014-03-04 09:35:30 -08001772static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001773{
Richard Henderson6781d082010-05-06 08:50:44 -07001774 static uint64_t const opc_ld_m1[4] = {
1775 OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
1776 };
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001777 int addr_reg, data_reg;
Richard Henderson0374f502014-03-04 09:35:30 -08001778 TCGMemOp opc, s_bits, bswap;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001779
Richard Henderson0374f502014-03-04 09:35:30 -08001780 data_reg = args[0];
1781 addr_reg = args[1];
1782 opc = args[2];
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001783 s_bits = opc & MO_SIZE;
1784 bswap = opc & MO_BSWAP;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001785
Aurelien Jarno477ba622010-03-29 02:12:51 +02001786#if TARGET_LONG_BITS == 32
Laurent Vivierb76f21a2015-08-24 14:53:54 +02001787 if (guest_base != 0) {
Richard Henderson6781d082010-05-06 08:50:44 -07001788 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001789 INSN_NOP_M,
Richard Henderson6781d082010-05-06 08:50:44 -07001790 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
1791 TCG_REG_R3, addr_reg),
1792 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
1793 TCG_GUEST_BASE_REG, TCG_REG_R3));
1794 } else {
1795 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001796 INSN_NOP_M,
Richard Henderson6781d082010-05-06 08:50:44 -07001797 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
1798 TCG_REG_R2, addr_reg),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001799 INSN_NOP_I);
Richard Henderson6781d082010-05-06 08:50:44 -07001800 }
Aurelien Jarno477ba622010-03-29 02:12:51 +02001801
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001802 if (!bswap) {
1803 if (!(opc & MO_SIGN)) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001804 tcg_out_bundle(s, miI,
1805 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1806 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001807 INSN_NOP_I,
1808 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001809 } else {
1810 tcg_out_bundle(s, mII,
1811 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1812 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001813 INSN_NOP_I,
Richard Hendersondb008a82013-09-05 19:13:41 -04001814 tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001815 }
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001816 } else if (s_bits == MO_64) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001817 tcg_out_bundle(s, mII,
1818 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1819 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001820 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001821 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001822 } else {
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001823 if (s_bits == MO_16) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001824 tcg_out_bundle(s, mII,
1825 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1826 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001827 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001828 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1829 data_reg, data_reg, 15, 15));
1830 } else {
1831 tcg_out_bundle(s, mII,
1832 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1833 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001834 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001835 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1836 data_reg, data_reg, 31, 31));
1837 }
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001838 if (!(opc & MO_SIGN)) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001839 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001840 INSN_NOP_M,
1841 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001842 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001843 } else {
1844 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001845 INSN_NOP_M,
Richard Henderson463230d2013-09-05 19:20:40 -04001846 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg),
Richard Hendersondb008a82013-09-05 19:13:41 -04001847 tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001848 }
1849 }
1850#else
Laurent Vivierb76f21a2015-08-24 14:53:54 +02001851 if (guest_base != 0) {
Richard Henderson6781d082010-05-06 08:50:44 -07001852 tcg_out_bundle(s, MmI,
1853 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
1854 TCG_GUEST_BASE_REG, addr_reg),
1855 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1856 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001857 INSN_NOP_I);
Richard Henderson6781d082010-05-06 08:50:44 -07001858 } else {
1859 tcg_out_bundle(s, mmI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001860 INSN_NOP_M,
Richard Henderson6781d082010-05-06 08:50:44 -07001861 tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
1862 data_reg, addr_reg),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001863 INSN_NOP_I);
Richard Henderson6781d082010-05-06 08:50:44 -07001864 }
Aurelien Jarno477ba622010-03-29 02:12:51 +02001865
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001866 if (bswap && s_bits == MO_16) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001867 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001868 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001869 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1870 data_reg, data_reg, 15, 15),
Richard Henderson463230d2013-09-05 19:20:40 -04001871 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001872 } else if (bswap && s_bits == MO_32) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001873 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001874 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001875 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1876 data_reg, data_reg, 31, 31),
Richard Henderson463230d2013-09-05 19:20:40 -04001877 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001878 } else if (bswap && s_bits == MO_64) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001879 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001880 INSN_NOP_M,
1881 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001882 tcg_opc_bswap64_i(TCG_REG_P0, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001883 }
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001884 if (opc & MO_SIGN) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001885 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001886 INSN_NOP_M,
1887 INSN_NOP_I,
Richard Hendersondb008a82013-09-05 19:13:41 -04001888 tcg_opc_ext_i(TCG_REG_P0, opc, data_reg, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001889 }
1890#endif
1891}
1892
Richard Henderson0374f502014-03-04 09:35:30 -08001893static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
Aurelien Jarno477ba622010-03-29 02:12:51 +02001894{
Richard Henderson6781d082010-05-06 08:50:44 -07001895 static uint64_t const opc_st_m4[4] = {
1896 OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
1897 };
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001898 int addr_reg, data_reg;
Richard Henderson6781d082010-05-06 08:50:44 -07001899#if TARGET_LONG_BITS == 64
1900 uint64_t add_guest_base;
1901#endif
Richard Henderson0374f502014-03-04 09:35:30 -08001902 TCGMemOp opc, s_bits, bswap;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001903
Richard Henderson0374f502014-03-04 09:35:30 -08001904 data_reg = args[0];
1905 addr_reg = args[1];
1906 opc = args[2];
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001907 s_bits = opc & MO_SIZE;
1908 bswap = opc & MO_BSWAP;
Aurelien Jarno477ba622010-03-29 02:12:51 +02001909
Aurelien Jarno477ba622010-03-29 02:12:51 +02001910#if TARGET_LONG_BITS == 32
Laurent Vivierb76f21a2015-08-24 14:53:54 +02001911 if (guest_base != 0) {
Richard Henderson6781d082010-05-06 08:50:44 -07001912 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001913 INSN_NOP_M,
Richard Henderson6781d082010-05-06 08:50:44 -07001914 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
1915 TCG_REG_R3, addr_reg),
1916 tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
1917 TCG_GUEST_BASE_REG, TCG_REG_R3));
1918 } else {
1919 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001920 INSN_NOP_M,
Richard Henderson6781d082010-05-06 08:50:44 -07001921 tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
Richard Henderson07f59732010-11-22 14:57:57 -08001922 TCG_REG_R2, addr_reg),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001923 INSN_NOP_I);
Richard Henderson6781d082010-05-06 08:50:44 -07001924 }
1925
Aurelien Jarno477ba622010-03-29 02:12:51 +02001926 if (bswap) {
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001927 if (s_bits == MO_16) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001928 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001929 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001930 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1931 TCG_REG_R3, data_reg, 15, 15),
Richard Henderson463230d2013-09-05 19:20:40 -04001932 tcg_opc_bswap64_i(TCG_REG_P0,
1933 TCG_REG_R3, TCG_REG_R3));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001934 data_reg = TCG_REG_R3;
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001935 } else if (s_bits == MO_32) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001936 tcg_out_bundle(s, mII,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001937 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001938 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1939 TCG_REG_R3, data_reg, 31, 31),
Richard Henderson463230d2013-09-05 19:20:40 -04001940 tcg_opc_bswap64_i(TCG_REG_P0,
1941 TCG_REG_R3, TCG_REG_R3));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001942 data_reg = TCG_REG_R3;
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001943 } else if (s_bits == MO_64) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001944 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001945 INSN_NOP_M,
1946 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001947 tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R3, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001948 data_reg = TCG_REG_R3;
1949 }
1950 }
1951 tcg_out_bundle(s, mmI,
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001952 tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
Aurelien Jarno477ba622010-03-29 02:12:51 +02001953 data_reg, TCG_REG_R2),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001954 INSN_NOP_M,
1955 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001956#else
Laurent Vivierb76f21a2015-08-24 14:53:54 +02001957 if (guest_base != 0) {
Richard Henderson6781d082010-05-06 08:50:44 -07001958 add_guest_base = tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
1959 TCG_GUEST_BASE_REG, addr_reg);
1960 addr_reg = TCG_REG_R2;
1961 } else {
Richard Henderson5f7b1682013-09-04 19:00:52 -04001962 add_guest_base = INSN_NOP_M;
Richard Henderson6781d082010-05-06 08:50:44 -07001963 }
1964
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001965 if (!bswap) {
Laurent Vivierb76f21a2015-08-24 14:53:54 +02001966 tcg_out_bundle(s, (guest_base ? MmI : mmI),
Richard Henderson6781d082010-05-06 08:50:44 -07001967 add_guest_base,
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001968 tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
Richard Henderson6781d082010-05-06 08:50:44 -07001969 data_reg, addr_reg),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001970 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02001971 } else {
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001972 if (s_bits == MO_16) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001973 tcg_out_bundle(s, mII,
Richard Henderson6781d082010-05-06 08:50:44 -07001974 add_guest_base,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001975 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1976 TCG_REG_R3, data_reg, 15, 15),
Richard Henderson463230d2013-09-05 19:20:40 -04001977 tcg_opc_bswap64_i(TCG_REG_P0,
1978 TCG_REG_R3, TCG_REG_R3));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001979 data_reg = TCG_REG_R3;
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001980 } else if (s_bits == MO_32) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001981 tcg_out_bundle(s, mII,
Richard Henderson6781d082010-05-06 08:50:44 -07001982 add_guest_base,
Aurelien Jarno477ba622010-03-29 02:12:51 +02001983 tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
1984 TCG_REG_R3, data_reg, 31, 31),
Richard Henderson463230d2013-09-05 19:20:40 -04001985 tcg_opc_bswap64_i(TCG_REG_P0,
1986 TCG_REG_R3, TCG_REG_R3));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001987 data_reg = TCG_REG_R3;
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001988 } else if (s_bits == MO_64) {
Aurelien Jarno477ba622010-03-29 02:12:51 +02001989 tcg_out_bundle(s, miI,
Richard Henderson6781d082010-05-06 08:50:44 -07001990 add_guest_base,
Richard Henderson5f7b1682013-09-04 19:00:52 -04001991 INSN_NOP_I,
Richard Henderson463230d2013-09-05 19:20:40 -04001992 tcg_opc_bswap64_i(TCG_REG_P0, TCG_REG_R3, data_reg));
Aurelien Jarno477ba622010-03-29 02:12:51 +02001993 data_reg = TCG_REG_R3;
1994 }
1995 tcg_out_bundle(s, miI,
Richard Hendersone3afa1c2013-09-04 17:24:38 -04001996 tcg_opc_m4 (TCG_REG_P0, opc_st_m4[s_bits],
Richard Henderson6781d082010-05-06 08:50:44 -07001997 data_reg, addr_reg),
Richard Henderson5f7b1682013-09-04 19:00:52 -04001998 INSN_NOP_I,
1999 INSN_NOP_I);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002000 }
2001#endif
2002}
2003
2004#endif
2005
2006static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
2007 const TCGArg *args, const int *const_args)
2008{
2009 switch(opc) {
2010 case INDEX_op_exit_tb:
2011 tcg_out_exit_tb(s, args[0]);
2012 break;
2013 case INDEX_op_br:
Richard Hendersonbec16312015-02-13 13:39:54 -08002014 tcg_out_br(s, arg_label(args[0]));
Aurelien Jarno477ba622010-03-29 02:12:51 +02002015 break;
Aurelien Jarno477ba622010-03-29 02:12:51 +02002016 case INDEX_op_goto_tb:
2017 tcg_out_goto_tb(s, args[0]);
2018 break;
Aurelien Jarno477ba622010-03-29 02:12:51 +02002019
Aurelien Jarno477ba622010-03-29 02:12:51 +02002020 case INDEX_op_ld8u_i32:
2021 case INDEX_op_ld8u_i64:
2022 tcg_out_ld_rel(s, OPC_LD1_M1, args[0], args[1], args[2]);
2023 break;
2024 case INDEX_op_ld8s_i32:
2025 case INDEX_op_ld8s_i64:
2026 tcg_out_ld_rel(s, OPC_LD1_M1, args[0], args[1], args[2]);
2027 tcg_out_ext(s, OPC_SXT1_I29, args[0], args[0]);
2028 break;
2029 case INDEX_op_ld16u_i32:
2030 case INDEX_op_ld16u_i64:
2031 tcg_out_ld_rel(s, OPC_LD2_M1, args[0], args[1], args[2]);
2032 break;
2033 case INDEX_op_ld16s_i32:
2034 case INDEX_op_ld16s_i64:
2035 tcg_out_ld_rel(s, OPC_LD2_M1, args[0], args[1], args[2]);
2036 tcg_out_ext(s, OPC_SXT2_I29, args[0], args[0]);
2037 break;
2038 case INDEX_op_ld_i32:
2039 case INDEX_op_ld32u_i64:
2040 tcg_out_ld_rel(s, OPC_LD4_M1, args[0], args[1], args[2]);
2041 break;
2042 case INDEX_op_ld32s_i64:
2043 tcg_out_ld_rel(s, OPC_LD4_M1, args[0], args[1], args[2]);
2044 tcg_out_ext(s, OPC_SXT4_I29, args[0], args[0]);
2045 break;
2046 case INDEX_op_ld_i64:
2047 tcg_out_ld_rel(s, OPC_LD8_M1, args[0], args[1], args[2]);
2048 break;
2049 case INDEX_op_st8_i32:
2050 case INDEX_op_st8_i64:
2051 tcg_out_st_rel(s, OPC_ST1_M4, args[0], args[1], args[2]);
2052 break;
2053 case INDEX_op_st16_i32:
2054 case INDEX_op_st16_i64:
2055 tcg_out_st_rel(s, OPC_ST2_M4, args[0], args[1], args[2]);
2056 break;
2057 case INDEX_op_st_i32:
2058 case INDEX_op_st32_i64:
2059 tcg_out_st_rel(s, OPC_ST4_M4, args[0], args[1], args[2]);
2060 break;
2061 case INDEX_op_st_i64:
2062 tcg_out_st_rel(s, OPC_ST8_M4, args[0], args[1], args[2]);
2063 break;
2064
2065 case INDEX_op_add_i32:
2066 case INDEX_op_add_i64:
Richard Henderson86420882013-09-05 16:15:13 -04002067 tcg_out_add(s, args[0], args[1], args[2], const_args[2]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002068 break;
2069 case INDEX_op_sub_i32:
2070 case INDEX_op_sub_i64:
Richard Hendersonf940fb02013-09-05 16:44:18 -04002071 tcg_out_sub(s, args[0], args[1], const_args[1], args[2], const_args[2]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002072 break;
2073
2074 case INDEX_op_and_i32:
2075 case INDEX_op_and_i64:
Richard Henderson25c9c732013-09-05 17:13:43 -04002076 /* TCG expects arg2 constant; A3 expects arg1 constant. Swap. */
2077 tcg_out_alu(s, OPC_AND_A1, OPC_AND_A3, args[0],
2078 args[2], const_args[2], args[1], const_args[1]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002079 break;
2080 case INDEX_op_andc_i32:
2081 case INDEX_op_andc_i64:
Richard Henderson25c9c732013-09-05 17:13:43 -04002082 tcg_out_alu(s, OPC_ANDCM_A1, OPC_ANDCM_A3, args[0],
2083 args[1], const_args[1], args[2], const_args[2]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002084 break;
2085 case INDEX_op_eqv_i32:
2086 case INDEX_op_eqv_i64:
2087 tcg_out_eqv(s, args[0], args[1], const_args[1],
2088 args[2], const_args[2]);
2089 break;
2090 case INDEX_op_nand_i32:
2091 case INDEX_op_nand_i64:
2092 tcg_out_nand(s, args[0], args[1], const_args[1],
2093 args[2], const_args[2]);
2094 break;
2095 case INDEX_op_nor_i32:
2096 case INDEX_op_nor_i64:
2097 tcg_out_nor(s, args[0], args[1], const_args[1],
2098 args[2], const_args[2]);
2099 break;
2100 case INDEX_op_or_i32:
2101 case INDEX_op_or_i64:
Richard Henderson25c9c732013-09-05 17:13:43 -04002102 /* TCG expects arg2 constant; A3 expects arg1 constant. Swap. */
2103 tcg_out_alu(s, OPC_OR_A1, OPC_OR_A3, args[0],
2104 args[2], const_args[2], args[1], const_args[1]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002105 break;
2106 case INDEX_op_orc_i32:
2107 case INDEX_op_orc_i64:
2108 tcg_out_orc(s, args[0], args[1], const_args[1],
2109 args[2], const_args[2]);
2110 break;
2111 case INDEX_op_xor_i32:
2112 case INDEX_op_xor_i64:
Richard Henderson25c9c732013-09-05 17:13:43 -04002113 /* TCG expects arg2 constant; A3 expects arg1 constant. Swap. */
2114 tcg_out_alu(s, OPC_XOR_A1, OPC_XOR_A3, args[0],
2115 args[2], const_args[2], args[1], const_args[1]);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002116 break;
2117
2118 case INDEX_op_mul_i32:
2119 case INDEX_op_mul_i64:
2120 tcg_out_mul(s, args[0], args[1], args[2]);
2121 break;
2122
2123 case INDEX_op_sar_i32:
2124 tcg_out_sar_i32(s, args[0], args[1], args[2], const_args[2]);
2125 break;
2126 case INDEX_op_sar_i64:
2127 tcg_out_sar_i64(s, args[0], args[1], args[2], const_args[2]);
2128 break;
2129 case INDEX_op_shl_i32:
2130 tcg_out_shl_i32(s, args[0], args[1], args[2], const_args[2]);
2131 break;
2132 case INDEX_op_shl_i64:
2133 tcg_out_shl_i64(s, args[0], args[1], args[2], const_args[2]);
2134 break;
2135 case INDEX_op_shr_i32:
2136 tcg_out_shr_i32(s, args[0], args[1], args[2], const_args[2]);
2137 break;
2138 case INDEX_op_shr_i64:
2139 tcg_out_shr_i64(s, args[0], args[1], args[2], const_args[2]);
2140 break;
2141 case INDEX_op_rotl_i32:
2142 tcg_out_rotl_i32(s, args[0], args[1], args[2], const_args[2]);
2143 break;
2144 case INDEX_op_rotl_i64:
2145 tcg_out_rotl_i64(s, args[0], args[1], args[2], const_args[2]);
2146 break;
2147 case INDEX_op_rotr_i32:
2148 tcg_out_rotr_i32(s, args[0], args[1], args[2], const_args[2]);
2149 break;
2150 case INDEX_op_rotr_i64:
2151 tcg_out_rotr_i64(s, args[0], args[1], args[2], const_args[2]);
2152 break;
2153
2154 case INDEX_op_ext8s_i32:
2155 case INDEX_op_ext8s_i64:
2156 tcg_out_ext(s, OPC_SXT1_I29, args[0], args[1]);
2157 break;
2158 case INDEX_op_ext8u_i32:
2159 case INDEX_op_ext8u_i64:
2160 tcg_out_ext(s, OPC_ZXT1_I29, args[0], args[1]);
2161 break;
2162 case INDEX_op_ext16s_i32:
2163 case INDEX_op_ext16s_i64:
2164 tcg_out_ext(s, OPC_SXT2_I29, args[0], args[1]);
2165 break;
2166 case INDEX_op_ext16u_i32:
2167 case INDEX_op_ext16u_i64:
2168 tcg_out_ext(s, OPC_ZXT2_I29, args[0], args[1]);
2169 break;
Aurelien Jarno4f2331e2015-07-27 12:41:45 +02002170 case INDEX_op_ext_i32_i64:
Aurelien Jarno477ba622010-03-29 02:12:51 +02002171 case INDEX_op_ext32s_i64:
2172 tcg_out_ext(s, OPC_SXT4_I29, args[0], args[1]);
2173 break;
Aurelien Jarno4f2331e2015-07-27 12:41:45 +02002174 case INDEX_op_extu_i32_i64:
Aurelien Jarno477ba622010-03-29 02:12:51 +02002175 case INDEX_op_ext32u_i64:
2176 tcg_out_ext(s, OPC_ZXT4_I29, args[0], args[1]);
2177 break;
2178
2179 case INDEX_op_bswap16_i32:
2180 case INDEX_op_bswap16_i64:
2181 tcg_out_bswap16(s, args[0], args[1]);
2182 break;
2183 case INDEX_op_bswap32_i32:
2184 case INDEX_op_bswap32_i64:
2185 tcg_out_bswap32(s, args[0], args[1]);
2186 break;
2187 case INDEX_op_bswap64_i64:
2188 tcg_out_bswap64(s, args[0], args[1]);
2189 break;
2190
Richard Hendersonc7d44752012-10-10 16:01:35 -07002191 case INDEX_op_deposit_i32:
2192 case INDEX_op_deposit_i64:
2193 tcg_out_deposit(s, args[0], args[1], args[2], const_args[2],
2194 args[3], args[4]);
2195 break;
2196
Aurelien Jarno477ba622010-03-29 02:12:51 +02002197 case INDEX_op_brcond_i32:
Richard Hendersonbec16312015-02-13 13:39:54 -08002198 tcg_out_brcond(s, args[2], args[0], args[1], arg_label(args[3]), 1);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002199 break;
2200 case INDEX_op_brcond_i64:
Richard Hendersonbec16312015-02-13 13:39:54 -08002201 tcg_out_brcond(s, args[2], args[0], args[1], arg_label(args[3]), 0);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002202 break;
2203 case INDEX_op_setcond_i32:
2204 tcg_out_setcond(s, args[3], args[0], args[1], args[2], 1);
2205 break;
2206 case INDEX_op_setcond_i64:
2207 tcg_out_setcond(s, args[3], args[0], args[1], args[2], 0);
2208 break;
Aurelien Jarnob90cf712012-10-09 21:53:55 +02002209 case INDEX_op_movcond_i32:
2210 tcg_out_movcond(s, args[5], args[0], args[1], args[2],
2211 args[3], const_args[3], args[4], const_args[4], 1);
2212 break;
2213 case INDEX_op_movcond_i64:
2214 tcg_out_movcond(s, args[5], args[0], args[1], args[2],
2215 args[3], const_args[3], args[4], const_args[4], 0);
2216 break;
Aurelien Jarno477ba622010-03-29 02:12:51 +02002217
Richard Henderson0374f502014-03-04 09:35:30 -08002218 case INDEX_op_qemu_ld_i32:
2219 tcg_out_qemu_ld(s, args);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002220 break;
Richard Henderson0374f502014-03-04 09:35:30 -08002221 case INDEX_op_qemu_ld_i64:
2222 tcg_out_qemu_ld(s, args);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002223 break;
Richard Henderson0374f502014-03-04 09:35:30 -08002224 case INDEX_op_qemu_st_i32:
2225 tcg_out_qemu_st(s, args);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002226 break;
Richard Henderson0374f502014-03-04 09:35:30 -08002227 case INDEX_op_qemu_st_i64:
2228 tcg_out_qemu_st(s, args);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002229 break;
2230
Pranith Kumar5bbadbd2016-07-14 16:20:17 -04002231 case INDEX_op_mb:
2232 tcg_out_bundle(s, mmI, OPC_MF_M24, INSN_NOP_M, INSN_NOP_I);
2233 break;
Richard Henderson96d0ee72014-04-25 15:19:33 -04002234 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2235 case INDEX_op_mov_i64:
2236 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
2237 case INDEX_op_movi_i64:
2238 case INDEX_op_call: /* Always emitted via tcg_out_call. */
Aurelien Jarno477ba622010-03-29 02:12:51 +02002239 default:
2240 tcg_abort();
2241 }
2242}
2243
2244static const TCGTargetOpDef ia64_op_defs[] = {
2245 { INDEX_op_br, { } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002246 { INDEX_op_exit_tb, { } },
2247 { INDEX_op_goto_tb, { } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002248
Aurelien Jarno477ba622010-03-29 02:12:51 +02002249 { INDEX_op_ld8u_i32, { "r", "r" } },
2250 { INDEX_op_ld8s_i32, { "r", "r" } },
2251 { INDEX_op_ld16u_i32, { "r", "r" } },
2252 { INDEX_op_ld16s_i32, { "r", "r" } },
2253 { INDEX_op_ld_i32, { "r", "r" } },
2254 { INDEX_op_st8_i32, { "rZ", "r" } },
2255 { INDEX_op_st16_i32, { "rZ", "r" } },
2256 { INDEX_op_st_i32, { "rZ", "r" } },
2257
Richard Henderson86420882013-09-05 16:15:13 -04002258 { INDEX_op_add_i32, { "r", "rZ", "rI" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002259 { INDEX_op_sub_i32, { "r", "rI", "rI" } },
2260
2261 { INDEX_op_and_i32, { "r", "rI", "rI" } },
2262 { INDEX_op_andc_i32, { "r", "rI", "rI" } },
2263 { INDEX_op_eqv_i32, { "r", "rZ", "rZ" } },
2264 { INDEX_op_nand_i32, { "r", "rZ", "rZ" } },
2265 { INDEX_op_nor_i32, { "r", "rZ", "rZ" } },
2266 { INDEX_op_or_i32, { "r", "rI", "rI" } },
2267 { INDEX_op_orc_i32, { "r", "rZ", "rZ" } },
2268 { INDEX_op_xor_i32, { "r", "rI", "rI" } },
2269
2270 { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
2271
2272 { INDEX_op_sar_i32, { "r", "rZ", "ri" } },
2273 { INDEX_op_shl_i32, { "r", "rZ", "ri" } },
2274 { INDEX_op_shr_i32, { "r", "rZ", "ri" } },
2275 { INDEX_op_rotl_i32, { "r", "rZ", "ri" } },
2276 { INDEX_op_rotr_i32, { "r", "rZ", "ri" } },
2277
2278 { INDEX_op_ext8s_i32, { "r", "rZ"} },
2279 { INDEX_op_ext8u_i32, { "r", "rZ"} },
2280 { INDEX_op_ext16s_i32, { "r", "rZ"} },
2281 { INDEX_op_ext16u_i32, { "r", "rZ"} },
2282
2283 { INDEX_op_bswap16_i32, { "r", "rZ" } },
2284 { INDEX_op_bswap32_i32, { "r", "rZ" } },
2285
Richard Henderson6d264b32013-09-05 12:47:41 -04002286 { INDEX_op_brcond_i32, { "rZ", "rZ" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002287 { INDEX_op_setcond_i32, { "r", "rZ", "rZ" } },
Aurelien Jarnob90cf712012-10-09 21:53:55 +02002288 { INDEX_op_movcond_i32, { "r", "rZ", "rZ", "rI", "rI" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002289
Aurelien Jarno477ba622010-03-29 02:12:51 +02002290 { INDEX_op_ld8u_i64, { "r", "r" } },
2291 { INDEX_op_ld8s_i64, { "r", "r" } },
2292 { INDEX_op_ld16u_i64, { "r", "r" } },
2293 { INDEX_op_ld16s_i64, { "r", "r" } },
2294 { INDEX_op_ld32u_i64, { "r", "r" } },
2295 { INDEX_op_ld32s_i64, { "r", "r" } },
2296 { INDEX_op_ld_i64, { "r", "r" } },
2297 { INDEX_op_st8_i64, { "rZ", "r" } },
2298 { INDEX_op_st16_i64, { "rZ", "r" } },
2299 { INDEX_op_st32_i64, { "rZ", "r" } },
2300 { INDEX_op_st_i64, { "rZ", "r" } },
2301
Richard Henderson86420882013-09-05 16:15:13 -04002302 { INDEX_op_add_i64, { "r", "rZ", "rI" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002303 { INDEX_op_sub_i64, { "r", "rI", "rI" } },
2304
2305 { INDEX_op_and_i64, { "r", "rI", "rI" } },
2306 { INDEX_op_andc_i64, { "r", "rI", "rI" } },
2307 { INDEX_op_eqv_i64, { "r", "rZ", "rZ" } },
2308 { INDEX_op_nand_i64, { "r", "rZ", "rZ" } },
2309 { INDEX_op_nor_i64, { "r", "rZ", "rZ" } },
2310 { INDEX_op_or_i64, { "r", "rI", "rI" } },
2311 { INDEX_op_orc_i64, { "r", "rZ", "rZ" } },
2312 { INDEX_op_xor_i64, { "r", "rI", "rI" } },
2313
2314 { INDEX_op_mul_i64, { "r", "rZ", "rZ" } },
2315
2316 { INDEX_op_sar_i64, { "r", "rZ", "ri" } },
2317 { INDEX_op_shl_i64, { "r", "rZ", "ri" } },
2318 { INDEX_op_shr_i64, { "r", "rZ", "ri" } },
2319 { INDEX_op_rotl_i64, { "r", "rZ", "ri" } },
2320 { INDEX_op_rotr_i64, { "r", "rZ", "ri" } },
2321
2322 { INDEX_op_ext8s_i64, { "r", "rZ"} },
2323 { INDEX_op_ext8u_i64, { "r", "rZ"} },
2324 { INDEX_op_ext16s_i64, { "r", "rZ"} },
2325 { INDEX_op_ext16u_i64, { "r", "rZ"} },
2326 { INDEX_op_ext32s_i64, { "r", "rZ"} },
2327 { INDEX_op_ext32u_i64, { "r", "rZ"} },
Aurelien Jarno4f2331e2015-07-27 12:41:45 +02002328 { INDEX_op_ext_i32_i64, { "r", "rZ" } },
2329 { INDEX_op_extu_i32_i64, { "r", "rZ" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002330
2331 { INDEX_op_bswap16_i64, { "r", "rZ" } },
2332 { INDEX_op_bswap32_i64, { "r", "rZ" } },
2333 { INDEX_op_bswap64_i64, { "r", "rZ" } },
2334
Richard Henderson6d264b32013-09-05 12:47:41 -04002335 { INDEX_op_brcond_i64, { "rZ", "rZ" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002336 { INDEX_op_setcond_i64, { "r", "rZ", "rZ" } },
Aurelien Jarnob90cf712012-10-09 21:53:55 +02002337 { INDEX_op_movcond_i64, { "r", "rZ", "rZ", "rI", "rI" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002338
Richard Hendersonc7d44752012-10-10 16:01:35 -07002339 { INDEX_op_deposit_i32, { "r", "rZ", "ri" } },
2340 { INDEX_op_deposit_i64, { "r", "rZ", "ri" } },
2341
Richard Henderson0374f502014-03-04 09:35:30 -08002342 { INDEX_op_qemu_ld_i32, { "r", "r" } },
2343 { INDEX_op_qemu_ld_i64, { "r", "r" } },
2344 { INDEX_op_qemu_st_i32, { "SZ", "r" } },
2345 { INDEX_op_qemu_st_i64, { "SZ", "r" } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002346
Pranith Kumar5bbadbd2016-07-14 16:20:17 -04002347 { INDEX_op_mb, { } },
Aurelien Jarno477ba622010-03-29 02:12:51 +02002348 { -1 },
2349};
2350
Richard Hendersonf69d2772016-11-18 09:31:40 +01002351static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
2352{
2353 int i, n = ARRAY_SIZE(ia64_op_defs);
2354
2355 for (i = 0; i < n; ++i) {
2356 if (ia64_op_defs[i].op == op) {
2357 return &ia64_op_defs[i];
2358 }
2359 }
2360 return NULL;
2361}
2362
Aurelien Jarno477ba622010-03-29 02:12:51 +02002363/* Generate global QEMU prologue and epilogue code */
Richard Hendersone4d58b42010-06-02 17:26:56 -07002364static void tcg_target_qemu_prologue(TCGContext *s)
Aurelien Jarno477ba622010-03-29 02:12:51 +02002365{
2366 int frame_size;
2367
2368 /* reserve some stack space */
Blue Swirlda897bf2012-10-09 21:53:55 +02002369 frame_size = TCG_STATIC_CALL_ARGS_SIZE +
2370 CPU_TEMP_BUF_NLONGS * sizeof(long);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002371 frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
2372 ~(TCG_TARGET_STACK_ALIGN - 1);
Blue Swirlda897bf2012-10-09 21:53:55 +02002373 tcg_set_frame(s, TCG_REG_CALL_STACK, TCG_STATIC_CALL_ARGS_SIZE,
2374 CPU_TEMP_BUF_NLONGS * sizeof(long));
Aurelien Jarno477ba622010-03-29 02:12:51 +02002375
2376 /* First emit adhoc function descriptor */
Richard Henderson5588ff22014-04-25 13:24:23 -04002377 *s->code_ptr = (tcg_insn_unit){
2378 (uint64_t)(s->code_ptr + 1), /* entry point */
2379 0 /* skip gp */
2380 };
2381 s->code_ptr++;
Aurelien Jarno477ba622010-03-29 02:12:51 +02002382
2383 /* prologue */
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002384 tcg_out_bundle(s, miI,
Aurelien Jarno477ba622010-03-29 02:12:51 +02002385 tcg_opc_m34(TCG_REG_P0, OPC_ALLOC_M34,
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002386 TCG_REG_R34, 32, 24, 0),
Richard Hendersond15de152013-09-05 14:45:54 -04002387 INSN_NOP_I,
Aurelien Jarno477ba622010-03-29 02:12:51 +02002388 tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002389 TCG_REG_B6, TCG_REG_R33, 0));
Richard Henderson6781d082010-05-06 08:50:44 -07002390
Laurent Vivierb76f21a2015-08-24 14:53:54 +02002391 /* ??? If guest_base < 0x200000, we could load the register via
Richard Henderson6781d082010-05-06 08:50:44 -07002392 an ADDL in the M slot of the next bundle. */
Laurent Vivierb76f21a2015-08-24 14:53:54 +02002393 if (guest_base != 0) {
Richard Henderson6781d082010-05-06 08:50:44 -07002394 tcg_out_bundle(s, mlx,
Richard Henderson5f7b1682013-09-04 19:00:52 -04002395 INSN_NOP_M,
Laurent Vivierb76f21a2015-08-24 14:53:54 +02002396 tcg_opc_l2(guest_base),
Richard Henderson6781d082010-05-06 08:50:44 -07002397 tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
Laurent Vivierb76f21a2015-08-24 14:53:54 +02002398 TCG_GUEST_BASE_REG, guest_base));
Richard Henderson6781d082010-05-06 08:50:44 -07002399 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2400 }
2401
Aurelien Jarno477ba622010-03-29 02:12:51 +02002402 tcg_out_bundle(s, miB,
Richard Henderson64ba39a2011-08-17 14:11:49 -07002403 tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
Aurelien Jarno477ba622010-03-29 02:12:51 +02002404 TCG_REG_R12, -frame_size, TCG_REG_R12),
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002405 tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
Richard Hendersond15de152013-09-05 14:45:54 -04002406 TCG_REG_R33, TCG_REG_B0),
Aurelien Jarno477ba622010-03-29 02:12:51 +02002407 tcg_opc_b4 (TCG_REG_P0, OPC_BR_SPTK_MANY_B4, TCG_REG_B6));
2408
2409 /* epilogue */
2410 tb_ret_addr = s->code_ptr;
2411 tcg_out_bundle(s, miI,
Richard Henderson5f7b1682013-09-04 19:00:52 -04002412 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02002413 tcg_opc_i21(TCG_REG_P0, OPC_MOV_I21,
Richard Hendersond15de152013-09-05 14:45:54 -04002414 TCG_REG_B0, TCG_REG_R33, 0),
Aurelien Jarno477ba622010-03-29 02:12:51 +02002415 tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
2416 TCG_REG_R12, frame_size, TCG_REG_R12));
2417 tcg_out_bundle(s, miB,
Richard Henderson5f7b1682013-09-04 19:00:52 -04002418 INSN_NOP_M,
Aurelien Jarno477ba622010-03-29 02:12:51 +02002419 tcg_opc_i26(TCG_REG_P0, OPC_MOV_I_I26,
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002420 TCG_REG_PFS, TCG_REG_R34),
Aurelien Jarno477ba622010-03-29 02:12:51 +02002421 tcg_opc_b4 (TCG_REG_P0, OPC_BR_RET_SPTK_MANY_B4,
2422 TCG_REG_B0));
2423}
2424
Richard Hendersone4d58b42010-06-02 17:26:56 -07002425static void tcg_target_init(TCGContext *s)
Aurelien Jarno477ba622010-03-29 02:12:51 +02002426{
2427 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32],
2428 0xffffffffffffffffull);
2429 tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64],
2430 0xffffffffffffffffull);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002431
Richard Henderson7221f052010-05-06 08:50:43 -07002432 tcg_regset_clear(tcg_target_call_clobber_regs);
2433 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
2434 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
2435 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
2436 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
2437 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
2438 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R15);
2439 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R16);
2440 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R17);
2441 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R18);
2442 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R19);
2443 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R20);
2444 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R21);
2445 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R22);
2446 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R23);
2447 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R24);
2448 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R25);
2449 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R26);
2450 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R27);
2451 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R28);
2452 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R29);
2453 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R30);
2454 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R31);
2455 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R56);
2456 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R57);
2457 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R58);
2458 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R59);
2459 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R60);
2460 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R61);
2461 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R62);
2462 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R63);
2463
2464 tcg_regset_clear(s->reserved_regs);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002465 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* zero register */
2466 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* global pointer */
2467 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* internal use */
2468 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3); /* internal use */
2469 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12); /* stack pointer */
Richard Henderson7221f052010-05-06 08:50:43 -07002470 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
Richard Hendersond15de152013-09-05 14:45:54 -04002471 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R33); /* return address */
Aurelien Jarno18d445b2012-08-25 23:59:58 +02002472 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R34); /* PFS */
Aurelien Jarno477ba622010-03-29 02:12:51 +02002473
Richard Hendersond15de152013-09-05 14:45:54 -04002474 /* The following 4 are not in use, are call-saved, but *not* saved
Richard Henderson7221f052010-05-06 08:50:43 -07002475 by the prologue. Therefore we cannot use them without modifying
2476 the prologue. There doesn't seem to be any good reason to use
2477 these as opposed to the windowed registers. */
2478 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R4);
2479 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R5);
2480 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
Richard Hendersond15de152013-09-05 14:45:54 -04002481 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R7);
Aurelien Jarno477ba622010-03-29 02:12:51 +02002482}