]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/ppc/tcg-target.c.inc
tcg: Split out tcg_out_ext16s
[mirror_qemu.git] / tcg / ppc / tcg-target.c.inc
CommitLineData
810260a8 1/*
2 * Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
53c89efd 25#include "elf.h"
139c1837 26#include "../tcg-pool.c.inc"
8605cbcd 27#include "../tcg-ldst.c.inc"
53c89efd 28
d2168985
RH
29/*
30 * Standardize on the _CALL_FOO symbols used by GCC:
31 * Apple XCode does not define _CALL_DARWIN.
32 * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV (32-bit).
33 */
34#if !defined(_CALL_SYSV) && \
35 !defined(_CALL_DARWIN) && \
36 !defined(_CALL_AIX) && \
37 !defined(_CALL_ELF)
38# if defined(__APPLE__)
39# define _CALL_DARWIN
40# elif defined(__ELF__) && TCG_TARGET_REG_BITS == 32
41# define _CALL_SYSV
42# else
43# error "Unknown ABI"
44# endif
a813e36f 45#endif
d2168985 46
eb8b0224
RH
47#if TCG_TARGET_REG_BITS == 64
48# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_EXTEND
20861f34 49# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL
eb8b0224
RH
50#else
51# define TCG_TARGET_CALL_ARG_I32 TCG_CALL_ARG_NORMAL
20861f34 52# define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_BY_REF
eb8b0224 53#endif
7f25c469 54#ifdef _CALL_SYSV
c8eef960 55# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_EVEN
20861f34 56# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_BY_REF
c8eef960
RH
57#else
58# define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
20861f34 59# define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL
7f25c469 60#endif
ffcfbece 61
dfca1778
RH
62/* For some memory operations, we need a scratch that isn't R0. For the AIX
63 calling convention, we can re-use the TOC register since we'll be reloading
64 it at every call. Otherwise R12 will do nicely as neither a call-saved
65 register nor a parameter register. */
66#ifdef _CALL_AIX
67# define TCG_REG_TMP1 TCG_REG_R2
68#else
69# define TCG_REG_TMP1 TCG_REG_R12
70#endif
71
42281ec6
RH
72#define TCG_VEC_TMP1 TCG_REG_V0
73#define TCG_VEC_TMP2 TCG_REG_V1
74
5964fca8
RH
75#define TCG_REG_TB TCG_REG_R31
76#define USE_REG_TB (TCG_TARGET_REG_BITS == 64)
a84ac4cb 77
de3d636d
RH
78/* Shorthand for size of a pointer. Avoid promotion to unsigned. */
79#define SZP ((int)sizeof(void *))
80
4c3831a0
RH
81/* Shorthand for size of a register. */
82#define SZR (TCG_TARGET_REG_BITS / 8)
83
3d582c61
RH
84#define TCG_CT_CONST_S16 0x100
85#define TCG_CT_CONST_U16 0x200
86#define TCG_CT_CONST_S32 0x400
87#define TCG_CT_CONST_U32 0x800
88#define TCG_CT_CONST_ZERO 0x1000
6c858762 89#define TCG_CT_CONST_MONE 0x2000
d0b07481 90#define TCG_CT_CONST_WSZ 0x4000
fe6f943f 91
85d251d7
RH
92#define ALL_GENERAL_REGS 0xffffffffu
93#define ALL_VECTOR_REGS 0xffffffff00000000ull
94
95#ifdef CONFIG_SOFTMMU
96#define ALL_QLOAD_REGS \
97 (ALL_GENERAL_REGS & \
98 ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | (1 << TCG_REG_R5)))
99#define ALL_QSTORE_REGS \
100 (ALL_GENERAL_REGS & ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | \
101 (1 << TCG_REG_R5) | (1 << TCG_REG_R6)))
102#else
103#define ALL_QLOAD_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_R3))
104#define ALL_QSTORE_REGS ALL_QLOAD_REGS
105#endif
106
7d9dae0a 107TCGPowerISA have_isa;
63922f46 108static bool have_isel;
4b06c216 109bool have_altivec;
47c906ae 110bool have_vsx;
49d9870a 111
4cbea598 112#ifndef CONFIG_SOFTMMU
f6548c0a 113#define TCG_GUEST_BASE_REG 30
f6548c0a 114#endif
115
8d8fdbae 116#ifdef CONFIG_DEBUG_TCG
42281ec6
RH
117static const char tcg_target_reg_names[TCG_TARGET_NB_REGS][4] = {
118 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
119 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
120 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
121 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
122 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
123 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
124 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
125 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
810260a8 126};
d4a9eb1f 127#endif
810260a8 128
129static const int tcg_target_reg_alloc_order[] = {
5e1702b0 130 TCG_REG_R14, /* call saved registers */
810260a8 131 TCG_REG_R15,
132 TCG_REG_R16,
133 TCG_REG_R17,
134 TCG_REG_R18,
135 TCG_REG_R19,
136 TCG_REG_R20,
137 TCG_REG_R21,
138 TCG_REG_R22,
139 TCG_REG_R23,
5e1702b0
RH
140 TCG_REG_R24,
141 TCG_REG_R25,
142 TCG_REG_R26,
143 TCG_REG_R27,
810260a8 144 TCG_REG_R28,
145 TCG_REG_R29,
146 TCG_REG_R30,
147 TCG_REG_R31,
5e1702b0
RH
148 TCG_REG_R12, /* call clobbered, non-arguments */
149 TCG_REG_R11,
dfca1778
RH
150 TCG_REG_R2,
151 TCG_REG_R13,
5e1702b0 152 TCG_REG_R10, /* call clobbered, arguments */
810260a8 153 TCG_REG_R9,
5e1702b0
RH
154 TCG_REG_R8,
155 TCG_REG_R7,
156 TCG_REG_R6,
157 TCG_REG_R5,
158 TCG_REG_R4,
159 TCG_REG_R3,
42281ec6
RH
160
161 /* V0 and V1 reserved as temporaries; V20 - V31 are call-saved */
162 TCG_REG_V2, /* call clobbered, vectors */
163 TCG_REG_V3,
164 TCG_REG_V4,
165 TCG_REG_V5,
166 TCG_REG_V6,
167 TCG_REG_V7,
168 TCG_REG_V8,
169 TCG_REG_V9,
170 TCG_REG_V10,
171 TCG_REG_V11,
172 TCG_REG_V12,
173 TCG_REG_V13,
174 TCG_REG_V14,
175 TCG_REG_V15,
176 TCG_REG_V16,
177 TCG_REG_V17,
178 TCG_REG_V18,
179 TCG_REG_V19,
810260a8 180};
181
182static const int tcg_target_call_iarg_regs[] = {
183 TCG_REG_R3,
184 TCG_REG_R4,
185 TCG_REG_R5,
186 TCG_REG_R6,
187 TCG_REG_R7,
188 TCG_REG_R8,
189 TCG_REG_R9,
190 TCG_REG_R10
191};
192
5e3d0c19
RH
193static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
194{
195 tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
196 tcg_debug_assert(slot >= 0 && slot <= 1);
197 return TCG_REG_R3 + slot;
198}
810260a8 199
200static const int tcg_target_callee_save_regs[] = {
2fa169ba 201#ifdef _CALL_DARWIN
5d7ff5bb
AF
202 TCG_REG_R11,
203#endif
810260a8 204 TCG_REG_R14,
205 TCG_REG_R15,
206 TCG_REG_R16,
207 TCG_REG_R17,
208 TCG_REG_R18,
209 TCG_REG_R19,
210 TCG_REG_R20,
211 TCG_REG_R21,
212 TCG_REG_R22,
213 TCG_REG_R23,
095271d4 214 TCG_REG_R24,
215 TCG_REG_R25,
216 TCG_REG_R26,
cea5f9a2 217 TCG_REG_R27, /* currently used for the global env */
810260a8 218 TCG_REG_R28,
219 TCG_REG_R29,
220 TCG_REG_R30,
221 TCG_REG_R31
222};
223
b0940da0
RH
224static inline bool in_range_b(tcg_target_long target)
225{
226 return target == sextract64(target, 0, 26);
227}
228
d54401df
RH
229static uint32_t reloc_pc24_val(const tcg_insn_unit *pc,
230 const tcg_insn_unit *target)
810260a8 231{
e083c4a2 232 ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
eabb7b91 233 tcg_debug_assert(in_range_b(disp));
810260a8 234 return disp & 0x3fffffc;
235}
236
d54401df 237static bool reloc_pc24(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
810260a8 238{
d54401df
RH
239 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
240 ptrdiff_t disp = tcg_ptr_byte_diff(target, src_rx);
241
d5132903 242 if (in_range_b(disp)) {
d54401df 243 *src_rw = (*src_rw & ~0x3fffffc) | (disp & 0x3fffffc);
d5132903
RH
244 return true;
245 }
246 return false;
810260a8 247}
248
d54401df
RH
249static uint16_t reloc_pc14_val(const tcg_insn_unit *pc,
250 const tcg_insn_unit *target)
810260a8 251{
e083c4a2 252 ptrdiff_t disp = tcg_ptr_byte_diff(target, pc);
eabb7b91 253 tcg_debug_assert(disp == (int16_t) disp);
810260a8 254 return disp & 0xfffc;
255}
256
d54401df 257static bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
810260a8 258{
d54401df
RH
259 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
260 ptrdiff_t disp = tcg_ptr_byte_diff(target, src_rx);
261
d5132903 262 if (disp == (int16_t) disp) {
d54401df 263 *src_rw = (*src_rw & ~0xfffc) | (disp & 0xfffc);
d5132903
RH
264 return true;
265 }
266 return false;
810260a8 267}
268
810260a8 269/* test if a constant matches the constraint */
a4fbbd77 270static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
810260a8 271{
3d582c61
RH
272 if (ct & TCG_CT_CONST) {
273 return 1;
1194dcba
RH
274 }
275
276 /* The only 32-bit constraint we use aside from
277 TCG_CT_CONST is TCG_CT_CONST_S16. */
278 if (type == TCG_TYPE_I32) {
279 val = (int32_t)val;
280 }
281
282 if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
3d582c61
RH
283 return 1;
284 } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
810260a8 285 return 1;
3d582c61 286 } else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
fe6f943f 287 return 1;
3d582c61
RH
288 } else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
289 return 1;
290 } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
291 return 1;
6c858762
RH
292 } else if ((ct & TCG_CT_CONST_MONE) && val == -1) {
293 return 1;
d0b07481
RH
294 } else if ((ct & TCG_CT_CONST_WSZ)
295 && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
296 return 1;
3d582c61 297 }
810260a8 298 return 0;
299}
300
301#define OPCD(opc) ((opc)<<26)
302#define XO19(opc) (OPCD(19)|((opc)<<1))
8a94cfb0
AB
303#define MD30(opc) (OPCD(30)|((opc)<<2))
304#define MDS30(opc) (OPCD(30)|((opc)<<1))
810260a8 305#define XO31(opc) (OPCD(31)|((opc)<<1))
306#define XO58(opc) (OPCD(58)|(opc))
307#define XO62(opc) (OPCD(62)|(opc))
1838905e 308#define VX4(opc) (OPCD(4)|(opc))
810260a8 309
310#define B OPCD( 18)
311#define BC OPCD( 16)
312#define LBZ OPCD( 34)
313#define LHZ OPCD( 40)
314#define LHA OPCD( 42)
315#define LWZ OPCD( 32)
644f591a 316#define LWZUX XO31( 55)
810260a8 317#define STB OPCD( 38)
318#define STH OPCD( 44)
319#define STW OPCD( 36)
320
321#define STD XO62( 0)
322#define STDU XO62( 1)
323#define STDX XO31(149)
324
325#define LD XO58( 0)
326#define LDX XO31( 21)
327#define LDU XO58( 1)
644f591a 328#define LDUX XO31( 53)
301f6d90 329#define LWA XO58( 2)
810260a8 330#define LWAX XO31(341)
331
1cd62ae9 332#define ADDIC OPCD( 12)
810260a8 333#define ADDI OPCD( 14)
334#define ADDIS OPCD( 15)
335#define ORI OPCD( 24)
336#define ORIS OPCD( 25)
337#define XORI OPCD( 26)
338#define XORIS OPCD( 27)
339#define ANDI OPCD( 28)
340#define ANDIS OPCD( 29)
341#define MULLI OPCD( 7)
342#define CMPLI OPCD( 10)
343#define CMPI OPCD( 11)
148bdd23 344#define SUBFIC OPCD( 8)
810260a8 345
346#define LWZU OPCD( 33)
347#define STWU OPCD( 37)
348
313d91c7 349#define RLWIMI OPCD( 20)
810260a8 350#define RLWINM OPCD( 21)
313d91c7 351#define RLWNM OPCD( 23)
810260a8 352
8a94cfb0
AB
353#define RLDICL MD30( 0)
354#define RLDICR MD30( 1)
355#define RLDIMI MD30( 3)
356#define RLDCL MDS30( 8)
810260a8 357
358#define BCLR XO19( 16)
359#define BCCTR XO19(528)
360#define CRAND XO19(257)
361#define CRANDC XO19(129)
362#define CRNAND XO19(225)
363#define CROR XO19(449)
1cd62ae9 364#define CRNOR XO19( 33)
810260a8 365
366#define EXTSB XO31(954)
367#define EXTSH XO31(922)
368#define EXTSW XO31(986)
369#define ADD XO31(266)
370#define ADDE XO31(138)
6c858762
RH
371#define ADDME XO31(234)
372#define ADDZE XO31(202)
810260a8 373#define ADDC XO31( 10)
374#define AND XO31( 28)
375#define SUBF XO31( 40)
376#define SUBFC XO31( 8)
377#define SUBFE XO31(136)
6c858762
RH
378#define SUBFME XO31(232)
379#define SUBFZE XO31(200)
810260a8 380#define OR XO31(444)
381#define XOR XO31(316)
382#define MULLW XO31(235)
8fa391a0 383#define MULHW XO31( 75)
810260a8 384#define MULHWU XO31( 11)
385#define DIVW XO31(491)
386#define DIVWU XO31(459)
4d573822
MKF
387#define MODSW XO31(779)
388#define MODUW XO31(267)
810260a8 389#define CMP XO31( 0)
390#define CMPL XO31( 32)
391#define LHBRX XO31(790)
392#define LWBRX XO31(534)
49d9870a 393#define LDBRX XO31(532)
810260a8 394#define STHBRX XO31(918)
395#define STWBRX XO31(662)
49d9870a 396#define STDBRX XO31(660)
810260a8 397#define MFSPR XO31(339)
398#define MTSPR XO31(467)
399#define SRAWI XO31(824)
400#define NEG XO31(104)
1cd62ae9 401#define MFCR XO31( 19)
6995a4a0 402#define MFOCRF (MFCR | (1u << 20))
157f2662 403#define NOR XO31(124)
1cd62ae9 404#define CNTLZW XO31( 26)
405#define CNTLZD XO31( 58)
d0b07481
RH
406#define CNTTZW XO31(538)
407#define CNTTZD XO31(570)
33e75fb9
RH
408#define CNTPOPW XO31(378)
409#define CNTPOPD XO31(506)
ce1010d6
RH
410#define ANDC XO31( 60)
411#define ORC XO31(412)
412#define EQV XO31(284)
413#define NAND XO31(476)
70fac59a 414#define ISEL XO31( 15)
810260a8 415
416#define MULLD XO31(233)
417#define MULHD XO31( 73)
418#define MULHDU XO31( 9)
419#define DIVD XO31(489)
420#define DIVDU XO31(457)
4d573822
MKF
421#define MODSD XO31(777)
422#define MODUD XO31(265)
810260a8 423
424#define LBZX XO31( 87)
4f4a67ae 425#define LHZX XO31(279)
810260a8 426#define LHAX XO31(343)
427#define LWZX XO31( 23)
428#define STBX XO31(215)
429#define STHX XO31(407)
430#define STWX XO31(151)
431
7b4af5ee
PK
432#define EIEIO XO31(854)
433#define HWSYNC XO31(598)
434#define LWSYNC (HWSYNC | (1u << 21))
435
541dd4ce 436#define SPR(a, b) ((((a)<<5)|(b))<<11)
810260a8 437#define LR SPR(8, 0)
438#define CTR SPR(9, 0)
439
440#define SLW XO31( 24)
441#define SRW XO31(536)
442#define SRAW XO31(792)
443
444#define SLD XO31( 27)
445#define SRD XO31(539)
446#define SRAD XO31(794)
fe6f943f 447#define SRADI XO31(413<<1)
810260a8 448
780b573f
RH
449#define BRH XO31(219)
450#define BRW XO31(155)
451#define BRD XO31(187)
452
810260a8 453#define TW XO31( 4)
541dd4ce 454#define TRAP (TW | TO(31))
810260a8 455
a84ac4cb
RH
456#define NOP ORI /* ori 0,0,0 */
457
6ef14d7e
RH
458#define LVX XO31(103)
459#define LVEBX XO31(7)
460#define LVEHX XO31(39)
461#define LVEWX XO31(71)
47c906ae
RH
462#define LXSDX (XO31(588) | 1) /* v2.06, force tx=1 */
463#define LXVDSX (XO31(332) | 1) /* v2.06, force tx=1 */
b2dda640 464#define LXSIWZX (XO31(12) | 1) /* v2.07, force tx=1 */
6e11cde1
RH
465#define LXV (OPCD(61) | 8 | 1) /* v3.00, force tx=1 */
466#define LXSD (OPCD(57) | 2) /* v3.00 */
467#define LXVWSX (XO31(364) | 1) /* v3.00, force tx=1 */
6ef14d7e
RH
468
469#define STVX XO31(231)
470#define STVEWX XO31(199)
47c906ae 471#define STXSDX (XO31(716) | 1) /* v2.06, force sx=1 */
b2dda640 472#define STXSIWX (XO31(140) | 1) /* v2.07, force sx=1 */
6e11cde1
RH
473#define STXV (OPCD(61) | 8 | 5) /* v3.00, force sx=1 */
474#define STXSD (OPCD(61) | 2) /* v3.00 */
6ef14d7e 475
e9d1a53a
RH
476#define VADDSBS VX4(768)
477#define VADDUBS VX4(512)
d6750811 478#define VADDUBM VX4(0)
e9d1a53a
RH
479#define VADDSHS VX4(832)
480#define VADDUHS VX4(576)
d6750811 481#define VADDUHM VX4(64)
e9d1a53a
RH
482#define VADDSWS VX4(896)
483#define VADDUWS VX4(640)
d6750811 484#define VADDUWM VX4(128)
64ff1c6d 485#define VADDUDM VX4(192) /* v2.07 */
d6750811 486
e9d1a53a
RH
487#define VSUBSBS VX4(1792)
488#define VSUBUBS VX4(1536)
d6750811 489#define VSUBUBM VX4(1024)
e9d1a53a
RH
490#define VSUBSHS VX4(1856)
491#define VSUBUHS VX4(1600)
d6750811 492#define VSUBUHM VX4(1088)
e9d1a53a
RH
493#define VSUBSWS VX4(1920)
494#define VSUBUWS VX4(1664)
d6750811 495#define VSUBUWM VX4(1152)
64ff1c6d 496#define VSUBUDM VX4(1216) /* v2.07 */
d6750811 497
d7cd6a2f
RH
498#define VNEGW (VX4(1538) | (6 << 16)) /* v3.00 */
499#define VNEGD (VX4(1538) | (7 << 16)) /* v3.00 */
500
e2382972
RH
501#define VMAXSB VX4(258)
502#define VMAXSH VX4(322)
503#define VMAXSW VX4(386)
64ff1c6d 504#define VMAXSD VX4(450) /* v2.07 */
e2382972
RH
505#define VMAXUB VX4(2)
506#define VMAXUH VX4(66)
507#define VMAXUW VX4(130)
64ff1c6d 508#define VMAXUD VX4(194) /* v2.07 */
e2382972
RH
509#define VMINSB VX4(770)
510#define VMINSH VX4(834)
511#define VMINSW VX4(898)
64ff1c6d 512#define VMINSD VX4(962) /* v2.07 */
e2382972
RH
513#define VMINUB VX4(514)
514#define VMINUH VX4(578)
515#define VMINUW VX4(642)
64ff1c6d 516#define VMINUD VX4(706) /* v2.07 */
e2382972 517
6ef14d7e
RH
518#define VCMPEQUB VX4(6)
519#define VCMPEQUH VX4(70)
520#define VCMPEQUW VX4(134)
64ff1c6d 521#define VCMPEQUD VX4(199) /* v2.07 */
6ef14d7e
RH
522#define VCMPGTSB VX4(774)
523#define VCMPGTSH VX4(838)
524#define VCMPGTSW VX4(902)
64ff1c6d 525#define VCMPGTSD VX4(967) /* v2.07 */
6ef14d7e
RH
526#define VCMPGTUB VX4(518)
527#define VCMPGTUH VX4(582)
528#define VCMPGTUW VX4(646)
64ff1c6d 529#define VCMPGTUD VX4(711) /* v2.07 */
d7cd6a2f
RH
530#define VCMPNEB VX4(7) /* v3.00 */
531#define VCMPNEH VX4(71) /* v3.00 */
532#define VCMPNEW VX4(135) /* v3.00 */
6ef14d7e 533
dabae097
RH
534#define VSLB VX4(260)
535#define VSLH VX4(324)
536#define VSLW VX4(388)
64ff1c6d 537#define VSLD VX4(1476) /* v2.07 */
dabae097
RH
538#define VSRB VX4(516)
539#define VSRH VX4(580)
540#define VSRW VX4(644)
64ff1c6d 541#define VSRD VX4(1732) /* v2.07 */
dabae097
RH
542#define VSRAB VX4(772)
543#define VSRAH VX4(836)
544#define VSRAW VX4(900)
64ff1c6d 545#define VSRAD VX4(964) /* v2.07 */
d9897efa
RH
546#define VRLB VX4(4)
547#define VRLH VX4(68)
548#define VRLW VX4(132)
64ff1c6d 549#define VRLD VX4(196) /* v2.07 */
d9897efa
RH
550
551#define VMULEUB VX4(520)
552#define VMULEUH VX4(584)
64ff1c6d 553#define VMULEUW VX4(648) /* v2.07 */
d9897efa
RH
554#define VMULOUB VX4(8)
555#define VMULOUH VX4(72)
64ff1c6d
RH
556#define VMULOUW VX4(136) /* v2.07 */
557#define VMULUWM VX4(137) /* v2.07 */
73ebe95e 558#define VMULLD VX4(457) /* v3.10 */
d9897efa
RH
559#define VMSUMUHM VX4(38)
560
561#define VMRGHB VX4(12)
562#define VMRGHH VX4(76)
563#define VMRGHW VX4(140)
564#define VMRGLB VX4(268)
565#define VMRGLH VX4(332)
566#define VMRGLW VX4(396)
567
568#define VPKUHUM VX4(14)
569#define VPKUWUM VX4(78)
dabae097 570
6ef14d7e
RH
571#define VAND VX4(1028)
572#define VANDC VX4(1092)
573#define VNOR VX4(1284)
574#define VOR VX4(1156)
575#define VXOR VX4(1220)
64ff1c6d
RH
576#define VEQV VX4(1668) /* v2.07 */
577#define VNAND VX4(1412) /* v2.07 */
578#define VORC VX4(1348) /* v2.07 */
6ef14d7e
RH
579
580#define VSPLTB VX4(524)
581#define VSPLTH VX4(588)
582#define VSPLTW VX4(652)
583#define VSPLTISB VX4(780)
584#define VSPLTISH VX4(844)
585#define VSPLTISW VX4(908)
586
587#define VSLDOI VX4(44)
588
47c906ae
RH
589#define XXPERMDI (OPCD(60) | (10 << 3) | 7) /* v2.06, force ax=bx=tx=1 */
590#define XXSEL (OPCD(60) | (3 << 4) | 0xf) /* v2.06, force ax=bx=cx=tx=1 */
b7ce3cff 591#define XXSPLTIB (OPCD(60) | (360 << 1) | 1) /* v3.00, force tx=1 */
47c906ae 592
7097312d
RH
593#define MFVSRD (XO31(51) | 1) /* v2.07, force sx=1 */
594#define MFVSRWZ (XO31(115) | 1) /* v2.07, force sx=1 */
595#define MTVSRD (XO31(179) | 1) /* v2.07, force tx=1 */
596#define MTVSRWZ (XO31(243) | 1) /* v2.07, force tx=1 */
b7ce3cff
RH
597#define MTVSRDD (XO31(435) | 1) /* v3.00, force tx=1 */
598#define MTVSRWS (XO31(403) | 1) /* v3.00, force tx=1 */
7097312d 599
810260a8 600#define RT(r) ((r)<<21)
601#define RS(r) ((r)<<21)
602#define RA(r) ((r)<<16)
603#define RB(r) ((r)<<11)
604#define TO(t) ((t)<<21)
605#define SH(s) ((s)<<11)
606#define MB(b) ((b)<<6)
607#define ME(e) ((e)<<1)
608#define BO(o) ((o)<<21)
609#define MB64(b) ((b)<<5)
6995a4a0 610#define FXM(b) (1 << (19 - (b)))
810260a8 611
b82f769c
RH
612#define VRT(r) (((r) & 31) << 21)
613#define VRA(r) (((r) & 31) << 16)
614#define VRB(r) (((r) & 31) << 11)
615#define VRC(r) (((r) & 31) << 6)
616
810260a8 617#define LK 1
618
2fd8eddc
RH
619#define TAB(t, a, b) (RT(t) | RA(a) | RB(b))
620#define SAB(s, a, b) (RS(s) | RA(a) | RB(b))
621#define TAI(s, a, i) (RT(s) | RA(a) | ((i) & 0xffff))
622#define SAI(s, a, i) (RS(s) | RA(a) | ((i) & 0xffff))
810260a8 623
624#define BF(n) ((n)<<23)
625#define BI(n, c) (((c)+((n)*4))<<16)
626#define BT(n, c) (((c)+((n)*4))<<21)
627#define BA(n, c) (((c)+((n)*4))<<16)
628#define BB(n, c) (((c)+((n)*4))<<11)
70fac59a 629#define BC_(n, c) (((c)+((n)*4))<<6)
810260a8 630
541dd4ce
RH
631#define BO_COND_TRUE BO(12)
632#define BO_COND_FALSE BO( 4)
633#define BO_ALWAYS BO(20)
810260a8 634
635enum {
636 CR_LT,
637 CR_GT,
638 CR_EQ,
639 CR_SO
640};
641
0aed257f 642static const uint32_t tcg_to_bc[] = {
541dd4ce
RH
643 [TCG_COND_EQ] = BC | BI(7, CR_EQ) | BO_COND_TRUE,
644 [TCG_COND_NE] = BC | BI(7, CR_EQ) | BO_COND_FALSE,
645 [TCG_COND_LT] = BC | BI(7, CR_LT) | BO_COND_TRUE,
646 [TCG_COND_GE] = BC | BI(7, CR_LT) | BO_COND_FALSE,
647 [TCG_COND_LE] = BC | BI(7, CR_GT) | BO_COND_FALSE,
648 [TCG_COND_GT] = BC | BI(7, CR_GT) | BO_COND_TRUE,
649 [TCG_COND_LTU] = BC | BI(7, CR_LT) | BO_COND_TRUE,
650 [TCG_COND_GEU] = BC | BI(7, CR_LT) | BO_COND_FALSE,
651 [TCG_COND_LEU] = BC | BI(7, CR_GT) | BO_COND_FALSE,
652 [TCG_COND_GTU] = BC | BI(7, CR_GT) | BO_COND_TRUE,
810260a8 653};
654
70fac59a
RH
655/* The low bit here is set if the RA and RB fields must be inverted. */
656static const uint32_t tcg_to_isel[] = {
657 [TCG_COND_EQ] = ISEL | BC_(7, CR_EQ),
658 [TCG_COND_NE] = ISEL | BC_(7, CR_EQ) | 1,
659 [TCG_COND_LT] = ISEL | BC_(7, CR_LT),
660 [TCG_COND_GE] = ISEL | BC_(7, CR_LT) | 1,
661 [TCG_COND_LE] = ISEL | BC_(7, CR_GT) | 1,
662 [TCG_COND_GT] = ISEL | BC_(7, CR_GT),
663 [TCG_COND_LTU] = ISEL | BC_(7, CR_LT),
664 [TCG_COND_GEU] = ISEL | BC_(7, CR_LT) | 1,
665 [TCG_COND_LEU] = ISEL | BC_(7, CR_GT) | 1,
666 [TCG_COND_GTU] = ISEL | BC_(7, CR_GT),
667};
668
6ac17786 669static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
030ffe39
RH
670 intptr_t value, intptr_t addend)
671{
d54401df 672 const tcg_insn_unit *target;
6ef14d7e
RH
673 int16_t lo;
674 int32_t hi;
030ffe39
RH
675
676 value += addend;
d54401df 677 target = (const tcg_insn_unit *)value;
030ffe39
RH
678
679 switch (type) {
680 case R_PPC_REL14:
d5132903 681 return reloc_pc14(code_ptr, target);
030ffe39 682 case R_PPC_REL24:
d5132903 683 return reloc_pc24(code_ptr, target);
030ffe39 684 case R_PPC_ADDR16:
a7cdaf71
RH
685 /*
686 * We are (slightly) abusing this relocation type. In particular,
687 * assert that the low 2 bits are zero, and do not modify them.
688 * That way we can use this with LD et al that have opcode bits
689 * in the low 2 bits of the insn.
690 */
691 if ((value & 3) || value != (int16_t)value) {
692 return false;
030ffe39 693 }
a7cdaf71 694 *code_ptr = (*code_ptr & ~0xfffc) | (value & 0xfffc);
030ffe39 695 break;
6ef14d7e
RH
696 case R_PPC_ADDR32:
697 /*
698 * We are abusing this relocation type. Again, this points to
699 * a pair of insns, lis + load. This is an absolute address
700 * relocation for PPC32 so the lis cannot be removed.
701 */
702 lo = value;
703 hi = value - lo;
704 if (hi + lo != value) {
705 return false;
706 }
707 code_ptr[0] = deposit32(code_ptr[0], 0, 16, hi >> 16);
708 code_ptr[1] = deposit32(code_ptr[1], 0, 16, lo);
709 break;
030ffe39
RH
710 default:
711 g_assert_not_reached();
712 }
6ac17786 713 return true;
030ffe39
RH
714}
715
a84ac4cb
RH
716static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
717 TCGReg base, tcg_target_long offset);
718
78113e83 719static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
810260a8 720{
6ef14d7e
RH
721 if (ret == arg) {
722 return true;
723 }
724 switch (type) {
725 case TCG_TYPE_I64:
726 tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
727 /* fallthru */
728 case TCG_TYPE_I32:
7097312d
RH
729 if (ret < TCG_REG_V0) {
730 if (arg < TCG_REG_V0) {
731 tcg_out32(s, OR | SAB(arg, ret, arg));
732 break;
733 } else if (have_isa_2_07) {
734 tcg_out32(s, (type == TCG_TYPE_I32 ? MFVSRWZ : MFVSRD)
735 | VRT(arg) | RA(ret));
736 break;
737 } else {
738 /* Altivec does not support vector->integer moves. */
739 return false;
740 }
741 } else if (arg < TCG_REG_V0) {
742 if (have_isa_2_07) {
743 tcg_out32(s, (type == TCG_TYPE_I32 ? MTVSRWZ : MTVSRD)
744 | VRT(ret) | RA(arg));
745 break;
746 } else {
747 /* Altivec does not support integer->vector moves. */
748 return false;
749 }
6ef14d7e
RH
750 }
751 /* fallthru */
752 case TCG_TYPE_V64:
753 case TCG_TYPE_V128:
754 tcg_debug_assert(ret >= TCG_REG_V0 && arg >= TCG_REG_V0);
755 tcg_out32(s, VOR | VRT(ret) | VRA(arg) | VRB(arg));
756 break;
757 default:
758 g_assert_not_reached();
f8b84129 759 }
78113e83 760 return true;
810260a8 761}
762
aceac8d6
RH
763static inline void tcg_out_rld(TCGContext *s, int op, TCGReg ra, TCGReg rs,
764 int sh, int mb)
810260a8 765{
eabb7b91 766 tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
541dd4ce
RH
767 sh = SH(sh & 0x1f) | (((sh >> 5) & 1) << 1);
768 mb = MB64((mb >> 5) | ((mb << 1) & 0x3f));
769 tcg_out32(s, op | RA(ra) | RS(rs) | sh | mb);
810260a8 770}
771
9e555b73
RH
772static inline void tcg_out_rlw(TCGContext *s, int op, TCGReg ra, TCGReg rs,
773 int sh, int mb, int me)
774{
775 tcg_out32(s, op | RA(ra) | RS(rs) | SH(sh) | MB(mb) | ME(me));
776}
777
678155b2 778static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
f4bf14f4
RH
779{
780 tcg_out32(s, EXTSB | RA(dst) | RS(src));
781}
782
d0e66c89
RH
783static void tcg_out_ext8u(TCGContext *s, TCGReg dst, TCGReg src)
784{
785 tcg_out32(s, ANDI | SAI(src, dst, 0xff));
786}
787
753e42ea 788static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg dst, TCGReg src)
f4bf14f4
RH
789{
790 tcg_out32(s, EXTSH | RA(dst) | RS(src));
791}
792
780b573f
RH
793static inline void tcg_out_ext16u(TCGContext *s, TCGReg dst, TCGReg src)
794{
795 tcg_out32(s, ANDI | SAI(src, dst, 0xffff));
796}
797
f4bf14f4
RH
798static inline void tcg_out_ext32s(TCGContext *s, TCGReg dst, TCGReg src)
799{
800 tcg_out32(s, EXTSW | RA(dst) | RS(src));
801}
802
6e5e0602
RH
803static inline void tcg_out_ext32u(TCGContext *s, TCGReg dst, TCGReg src)
804{
805 tcg_out_rld(s, RLDICL, dst, src, 0, 32);
806}
807
a757e1ee
RH
808static inline void tcg_out_shli32(TCGContext *s, TCGReg dst, TCGReg src, int c)
809{
810 tcg_out_rlw(s, RLWINM, dst, src, c, 0, 31 - c);
811}
812
0a9564b9
RH
813static inline void tcg_out_shli64(TCGContext *s, TCGReg dst, TCGReg src, int c)
814{
815 tcg_out_rld(s, RLDICR, dst, src, c, 63 - c);
816}
817
05dd01fa
RH
818static inline void tcg_out_sari32(TCGContext *s, TCGReg dst, TCGReg src, int c)
819{
820 /* Limit immediate shift count lest we create an illegal insn. */
821 tcg_out32(s, SRAWI | RA(dst) | RS(src) | SH(c & 31));
822}
823
a757e1ee
RH
824static inline void tcg_out_shri32(TCGContext *s, TCGReg dst, TCGReg src, int c)
825{
826 tcg_out_rlw(s, RLWINM, dst, src, 32 - c, c, 31);
827}
828
5e916c28
RH
829static inline void tcg_out_shri64(TCGContext *s, TCGReg dst, TCGReg src, int c)
830{
831 tcg_out_rld(s, RLDICL, dst, src, 64 - c, c);
832}
833
05dd01fa
RH
834static inline void tcg_out_sari64(TCGContext *s, TCGReg dst, TCGReg src, int c)
835{
836 tcg_out32(s, SRADI | RA(dst) | RS(src) | SH(c & 0x1f) | ((c >> 4) & 2));
837}
838
26ce7005 839static void tcg_out_bswap16(TCGContext *s, TCGReg dst, TCGReg src, int flags)
783d3ecd
RH
840{
841 TCGReg tmp = dst == src ? TCG_REG_R0 : dst;
842
780b573f
RH
843 if (have_isa_3_10) {
844 tcg_out32(s, BRH | RA(dst) | RS(src));
845 if (flags & TCG_BSWAP_OS) {
753e42ea 846 tcg_out_ext16s(s, TCG_TYPE_REG, dst, dst);
780b573f
RH
847 } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
848 tcg_out_ext16u(s, dst, dst);
849 }
850 return;
851 }
852
783d3ecd
RH
853 /*
854 * In the following,
855 * dep(a, b, m) -> (a & ~m) | (b & m)
856 *
857 * Begin with: src = xxxxabcd
858 */
859 /* tmp = rol32(src, 24) & 0x000000ff = 0000000c */
860 tcg_out_rlw(s, RLWINM, tmp, src, 24, 24, 31);
861 /* tmp = dep(tmp, rol32(src, 8), 0x0000ff00) = 000000dc */
862 tcg_out_rlw(s, RLWIMI, tmp, src, 8, 16, 23);
863
26ce7005 864 if (flags & TCG_BSWAP_OS) {
753e42ea 865 tcg_out_ext16s(s, TCG_TYPE_REG, dst, tmp);
26ce7005
RH
866 } else {
867 tcg_out_mov(s, TCG_TYPE_REG, dst, tmp);
868 }
783d3ecd
RH
869}
870
26ce7005 871static void tcg_out_bswap32(TCGContext *s, TCGReg dst, TCGReg src, int flags)
8a611d86
RH
872{
873 TCGReg tmp = dst == src ? TCG_REG_R0 : dst;
874
780b573f
RH
875 if (have_isa_3_10) {
876 tcg_out32(s, BRW | RA(dst) | RS(src));
877 if (flags & TCG_BSWAP_OS) {
878 tcg_out_ext32s(s, dst, dst);
879 } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
880 tcg_out_ext32u(s, dst, dst);
881 }
882 return;
883 }
884
8a611d86
RH
885 /*
886 * Stolen from gcc's builtin_bswap32.
887 * In the following,
888 * dep(a, b, m) -> (a & ~m) | (b & m)
889 *
890 * Begin with: src = xxxxabcd
891 */
892 /* tmp = rol32(src, 8) & 0xffffffff = 0000bcda */
893 tcg_out_rlw(s, RLWINM, tmp, src, 8, 0, 31);
894 /* tmp = dep(tmp, rol32(src, 24), 0xff000000) = 0000dcda */
895 tcg_out_rlw(s, RLWIMI, tmp, src, 24, 0, 7);
896 /* tmp = dep(tmp, rol32(src, 24), 0x0000ff00) = 0000dcba */
897 tcg_out_rlw(s, RLWIMI, tmp, src, 24, 16, 23);
898
26ce7005
RH
899 if (flags & TCG_BSWAP_OS) {
900 tcg_out_ext32s(s, dst, tmp);
901 } else {
902 tcg_out_mov(s, TCG_TYPE_REG, dst, tmp);
903 }
8a611d86
RH
904}
905
674ba588
RH
906static void tcg_out_bswap64(TCGContext *s, TCGReg dst, TCGReg src)
907{
908 TCGReg t0 = dst == src ? TCG_REG_R0 : dst;
909 TCGReg t1 = dst == src ? dst : TCG_REG_R0;
910
780b573f
RH
911 if (have_isa_3_10) {
912 tcg_out32(s, BRD | RA(dst) | RS(src));
913 return;
914 }
915
674ba588
RH
916 /*
917 * In the following,
918 * dep(a, b, m) -> (a & ~m) | (b & m)
919 *
920 * Begin with: src = abcdefgh
921 */
922 /* t0 = rol32(src, 8) & 0xffffffff = 0000fghe */
923 tcg_out_rlw(s, RLWINM, t0, src, 8, 0, 31);
924 /* t0 = dep(t0, rol32(src, 24), 0xff000000) = 0000hghe */
925 tcg_out_rlw(s, RLWIMI, t0, src, 24, 0, 7);
926 /* t0 = dep(t0, rol32(src, 24), 0x0000ff00) = 0000hgfe */
927 tcg_out_rlw(s, RLWIMI, t0, src, 24, 16, 23);
928
929 /* t0 = rol64(t0, 32) = hgfe0000 */
930 tcg_out_rld(s, RLDICL, t0, t0, 32, 0);
931 /* t1 = rol64(src, 32) = efghabcd */
932 tcg_out_rld(s, RLDICL, t1, src, 32, 0);
933
934 /* t0 = dep(t0, rol32(t1, 24), 0xffffffff) = hgfebcda */
935 tcg_out_rlw(s, RLWIMI, t0, t1, 8, 0, 31);
936 /* t0 = dep(t0, rol32(t1, 24), 0xff000000) = hgfedcda */
937 tcg_out_rlw(s, RLWIMI, t0, t1, 24, 0, 7);
938 /* t0 = dep(t0, rol32(t1, 24), 0x0000ff00) = hgfedcba */
939 tcg_out_rlw(s, RLWIMI, t0, t1, 24, 16, 23);
940
941 tcg_out_mov(s, TCG_TYPE_REG, dst, t0);
942}
943
77bfc7c0
RH
944/* Emit a move into ret of arg, if it can be done in one insn. */
945static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg)
946{
947 if (arg == (int16_t)arg) {
948 tcg_out32(s, ADDI | TAI(ret, 0, arg));
949 return true;
950 }
951 if (arg == (int32_t)arg && (arg & 0xffff) == 0) {
952 tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
953 return true;
954 }
955 return false;
956}
957
5964fca8
RH
958static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
959 tcg_target_long arg, bool in_prologue)
810260a8 960{
5964fca8 961 intptr_t tb_diff;
77bfc7c0
RH
962 tcg_target_long tmp;
963 int shift;
5964fca8
RH
964
965 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
966
967 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
968 arg = (int32_t)arg;
969 }
970
971 /* Load 16-bit immediates with one insn. */
77bfc7c0 972 if (tcg_out_movi_one(s, ret, arg)) {
5964fca8
RH
973 return;
974 }
975
976 /* Load addresses within the TB with one insn. */
e6dc7f81 977 tb_diff = tcg_tbrel_diff(s, (void *)arg);
5964fca8
RH
978 if (!in_prologue && USE_REG_TB && tb_diff == (int16_t)tb_diff) {
979 tcg_out32(s, ADDI | TAI(ret, TCG_REG_TB, tb_diff));
980 return;
981 }
982
77bfc7c0
RH
983 /* Load 32-bit immediates with two insns. Note that we've already
984 eliminated bare ADDIS, so we know both insns are required. */
5964fca8 985 if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) {
2fd8eddc 986 tcg_out32(s, ADDIS | TAI(ret, 0, arg >> 16));
77bfc7c0 987 tcg_out32(s, ORI | SAI(ret, ret, arg));
5964fca8 988 return;
810260a8 989 }
5964fca8 990 if (arg == (uint32_t)arg && !(arg & 0x8000)) {
421233a1
RH
991 tcg_out32(s, ADDI | TAI(ret, 0, arg));
992 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
5964fca8
RH
993 return;
994 }
a84ac4cb 995
77bfc7c0
RH
996 /* Load masked 16-bit value. */
997 if (arg > 0 && (arg & 0x8000)) {
998 tmp = arg | 0x7fff;
999 if ((tmp & (tmp + 1)) == 0) {
1000 int mb = clz64(tmp + 1) + 1;
1001 tcg_out32(s, ADDI | TAI(ret, 0, arg));
1002 tcg_out_rld(s, RLDICL, ret, ret, 0, mb);
1003 return;
1004 }
1005 }
1006
1007 /* Load common masks with 2 insns. */
1008 shift = ctz64(arg);
1009 tmp = arg >> shift;
1010 if (tmp == (int16_t)tmp) {
1011 tcg_out32(s, ADDI | TAI(ret, 0, tmp));
1012 tcg_out_shli64(s, ret, ret, shift);
1013 return;
1014 }
1015 shift = clz64(arg);
1016 if (tcg_out_movi_one(s, ret, arg << shift)) {
1017 tcg_out_shri64(s, ret, ret, shift);
1018 return;
1019 }
1020
5964fca8
RH
1021 /* Load addresses within 2GB of TB with 2 (or rarely 3) insns. */
1022 if (!in_prologue && USE_REG_TB && tb_diff == (int32_t)tb_diff) {
1023 tcg_out_mem_long(s, ADDI, ADD, ret, TCG_REG_TB, tb_diff);
1024 return;
1025 }
a84ac4cb 1026
53c89efd
RH
1027 /* Use the constant pool, if possible. */
1028 if (!in_prologue && USE_REG_TB) {
1029 new_pool_label(s, arg, R_PPC_ADDR16, s->code_ptr,
e6dc7f81 1030 tcg_tbrel_diff(s, NULL));
a7cdaf71 1031 tcg_out32(s, LD | TAI(ret, TCG_REG_TB, 0));
53c89efd
RH
1032 return;
1033 }
1034
77bfc7c0
RH
1035 tmp = arg >> 31 >> 1;
1036 tcg_out_movi(s, TCG_TYPE_I32, ret, tmp);
1037 if (tmp) {
5964fca8 1038 tcg_out_shli64(s, ret, ret, 32);
810260a8 1039 }
5964fca8
RH
1040 if (arg & 0xffff0000) {
1041 tcg_out32(s, ORIS | SAI(ret, ret, arg >> 16));
1042 }
1043 if (arg & 0xffff) {
1044 tcg_out32(s, ORI | SAI(ret, ret, arg));
1045 }
1046}
1047
4e186175
RH
1048static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
1049 TCGReg ret, int64_t val)
5964fca8 1050{
6ef14d7e
RH
1051 uint32_t load_insn;
1052 int rel, low;
1053 intptr_t add;
1054
4e186175
RH
1055 switch (vece) {
1056 case MO_8:
1057 low = (int8_t)val;
1058 if (low >= -16 && low < 16) {
6ef14d7e
RH
1059 tcg_out32(s, VSPLTISB | VRT(ret) | ((val & 31) << 16));
1060 return;
1061 }
4e186175
RH
1062 if (have_isa_3_00) {
1063 tcg_out32(s, XXSPLTIB | VRT(ret) | ((val & 0xff) << 11));
1064 return;
1065 }
1066 break;
1067
1068 case MO_16:
1069 low = (int16_t)val;
1070 if (low >= -16 && low < 16) {
6ef14d7e
RH
1071 tcg_out32(s, VSPLTISH | VRT(ret) | ((val & 31) << 16));
1072 return;
1073 }
4e186175
RH
1074 break;
1075
1076 case MO_32:
1077 low = (int32_t)val;
1078 if (low >= -16 && low < 16) {
6ef14d7e
RH
1079 tcg_out32(s, VSPLTISW | VRT(ret) | ((val & 31) << 16));
1080 return;
1081 }
4e186175 1082 break;
b7ce3cff 1083 }
6ef14d7e
RH
1084
1085 /*
1086 * Otherwise we must load the value from the constant pool.
1087 */
1088 if (USE_REG_TB) {
1089 rel = R_PPC_ADDR16;
e6dc7f81 1090 add = tcg_tbrel_diff(s, NULL);
6ef14d7e
RH
1091 } else {
1092 rel = R_PPC_ADDR32;
1093 add = 0;
1094 }
1095
47c906ae
RH
1096 if (have_vsx) {
1097 load_insn = type == TCG_TYPE_V64 ? LXSDX : LXVDSX;
1098 load_insn |= VRT(ret) | RB(TCG_REG_TMP1);
1099 if (TCG_TARGET_REG_BITS == 64) {
1100 new_pool_label(s, val, rel, s->code_ptr, add);
1101 } else {
4e186175 1102 new_pool_l2(s, rel, s->code_ptr, add, val >> 32, val);
47c906ae 1103 }
6ef14d7e 1104 } else {
47c906ae
RH
1105 load_insn = LVX | VRT(ret) | RB(TCG_REG_TMP1);
1106 if (TCG_TARGET_REG_BITS == 64) {
1107 new_pool_l2(s, rel, s->code_ptr, add, val, val);
1108 } else {
4e186175
RH
1109 new_pool_l4(s, rel, s->code_ptr, add,
1110 val >> 32, val, val >> 32, val);
47c906ae 1111 }
6ef14d7e
RH
1112 }
1113
1114 if (USE_REG_TB) {
1115 tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, 0, 0));
1116 load_insn |= RA(TCG_REG_TB);
1117 } else {
1118 tcg_out32(s, ADDIS | TAI(TCG_REG_TMP1, 0, 0));
1119 tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, TCG_REG_TMP1, 0));
1120 }
1121 tcg_out32(s, load_insn);
4b06c216
RH
1122}
1123
1124static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg ret,
1125 tcg_target_long arg)
1126{
1127 switch (type) {
1128 case TCG_TYPE_I32:
1129 case TCG_TYPE_I64:
1130 tcg_debug_assert(ret < TCG_REG_V0);
1131 tcg_out_movi_int(s, type, ret, arg, false);
1132 break;
1133
4b06c216
RH
1134 default:
1135 g_assert_not_reached();
1136 }
810260a8 1137}
1138
6a6d772e
RH
1139static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
1140 tcg_target_long imm)
1141{
1142 /* This function is only used for passing structs by reference. */
1143 g_assert_not_reached();
1144}
1145
637af30c 1146static bool mask_operand(uint32_t c, int *mb, int *me)
a9249dff
RH
1147{
1148 uint32_t lsb, test;
1149
1150 /* Accept a bit pattern like:
1151 0....01....1
1152 1....10....0
1153 0..01..10..0
1154 Keep track of the transitions. */
1155 if (c == 0 || c == -1) {
1156 return false;
1157 }
1158 test = c;
1159 lsb = test & -test;
1160 test += lsb;
1161 if (test & (test - 1)) {
1162 return false;
1163 }
1164
1165 *me = clz32(lsb);
1166 *mb = test ? clz32(test & -test) + 1 : 0;
1167 return true;
1168}
1169
637af30c
RH
1170static bool mask64_operand(uint64_t c, int *mb, int *me)
1171{
1172 uint64_t lsb;
1173
1174 if (c == 0) {
1175 return false;
1176 }
1177
1178 lsb = c & -c;
1179 /* Accept 1..10..0. */
1180 if (c == -lsb) {
1181 *mb = 0;
1182 *me = clz64(lsb);
1183 return true;
1184 }
1185 /* Accept 0..01..1. */
1186 if (lsb == 1 && (c & (c + 1)) == 0) {
1187 *mb = clz64(c + 1) + 1;
1188 *me = 63;
1189 return true;
1190 }
1191 return false;
1192}
1193
a9249dff
RH
1194static void tcg_out_andi32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
1195{
1196 int mb, me;
1197
1e1df962
RH
1198 if (mask_operand(c, &mb, &me)) {
1199 tcg_out_rlw(s, RLWINM, dst, src, 0, mb, me);
1200 } else if ((c & 0xffff) == c) {
a9249dff
RH
1201 tcg_out32(s, ANDI | SAI(src, dst, c));
1202 return;
1203 } else if ((c & 0xffff0000) == c) {
1204 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
1205 return;
a9249dff 1206 } else {
8327a470
RH
1207 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_R0, c);
1208 tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
a9249dff
RH
1209 }
1210}
1211
637af30c
RH
1212static void tcg_out_andi64(TCGContext *s, TCGReg dst, TCGReg src, uint64_t c)
1213{
1214 int mb, me;
1215
eabb7b91 1216 tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
1e1df962 1217 if (mask64_operand(c, &mb, &me)) {
637af30c
RH
1218 if (mb == 0) {
1219 tcg_out_rld(s, RLDICR, dst, src, 0, me);
1220 } else {
1221 tcg_out_rld(s, RLDICL, dst, src, 0, mb);
1222 }
1e1df962
RH
1223 } else if ((c & 0xffff) == c) {
1224 tcg_out32(s, ANDI | SAI(src, dst, c));
1225 return;
1226 } else if ((c & 0xffff0000) == c) {
1227 tcg_out32(s, ANDIS | SAI(src, dst, c >> 16));
1228 return;
637af30c 1229 } else {
8327a470
RH
1230 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, c);
1231 tcg_out32(s, AND | SAB(src, dst, TCG_REG_R0));
637af30c
RH
1232 }
1233}
1234
dce74c57
RH
1235static void tcg_out_zori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c,
1236 int op_lo, int op_hi)
1237{
1238 if (c >> 16) {
1239 tcg_out32(s, op_hi | SAI(src, dst, c >> 16));
1240 src = dst;
1241 }
1242 if (c & 0xffff) {
1243 tcg_out32(s, op_lo | SAI(src, dst, c));
1244 src = dst;
1245 }
1246}
1247
1248static void tcg_out_ori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
1249{
1250 tcg_out_zori32(s, dst, src, c, ORI, ORIS);
1251}
1252
1253static void tcg_out_xori32(TCGContext *s, TCGReg dst, TCGReg src, uint32_t c)
1254{
1255 tcg_out_zori32(s, dst, src, c, XORI, XORIS);
1256}
1257
2be7d76b 1258static void tcg_out_b(TCGContext *s, int mask, const tcg_insn_unit *target)
5d7ff5bb 1259{
e083c4a2 1260 ptrdiff_t disp = tcg_pcrel_diff(s, target);
b0940da0 1261 if (in_range_b(disp)) {
541dd4ce
RH
1262 tcg_out32(s, B | (disp & 0x3fffffc) | mask);
1263 } else {
de3d636d 1264 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, (uintptr_t)target);
8327a470 1265 tcg_out32(s, MTSPR | RS(TCG_REG_R0) | CTR);
541dd4ce 1266 tcg_out32(s, BCCTR | BO_ALWAYS | mask);
5d7ff5bb
AF
1267 }
1268}
1269
b18d5d2b
RH
1270static void tcg_out_mem_long(TCGContext *s, int opi, int opx, TCGReg rt,
1271 TCGReg base, tcg_target_long offset)
810260a8 1272{
b18d5d2b 1273 tcg_target_long orig = offset, l0, l1, extra = 0, align = 0;
6e11cde1 1274 bool is_int_store = false;
dfca1778 1275 TCGReg rs = TCG_REG_TMP1;
b18d5d2b 1276
b18d5d2b
RH
1277 switch (opi) {
1278 case LD: case LWA:
1279 align = 3;
1280 /* FALLTHRU */
1281 default:
6ef14d7e 1282 if (rt > TCG_REG_R0 && rt < TCG_REG_V0) {
b18d5d2b 1283 rs = rt;
de7761a3 1284 break;
b18d5d2b
RH
1285 }
1286 break;
6e11cde1
RH
1287 case LXSD:
1288 case STXSD:
1289 align = 3;
1290 break;
1291 case LXV:
1292 case STXV:
1293 align = 15;
1294 break;
b18d5d2b
RH
1295 case STD:
1296 align = 3;
de7761a3 1297 /* FALLTHRU */
b18d5d2b 1298 case STB: case STH: case STW:
6e11cde1 1299 is_int_store = true;
b18d5d2b 1300 break;
810260a8 1301 }
810260a8 1302
b18d5d2b 1303 /* For unaligned, or very large offsets, use the indexed form. */
6ef14d7e 1304 if (offset & align || offset != (int32_t)offset || opi == 0) {
d4cba13b
RH
1305 if (rs == base) {
1306 rs = TCG_REG_R0;
1307 }
6e11cde1 1308 tcg_debug_assert(!is_int_store || rs != rt);
de7761a3 1309 tcg_out_movi(s, TCG_TYPE_PTR, rs, orig);
6ef14d7e 1310 tcg_out32(s, opx | TAB(rt & 31, base, rs));
b18d5d2b
RH
1311 return;
1312 }
1313
1314 l0 = (int16_t)offset;
1315 offset = (offset - l0) >> 16;
1316 l1 = (int16_t)offset;
1317
1318 if (l1 < 0 && orig >= 0) {
1319 extra = 0x4000;
1320 l1 = (int16_t)(offset - 0x4000);
1321 }
1322 if (l1) {
1323 tcg_out32(s, ADDIS | TAI(rs, base, l1));
1324 base = rs;
1325 }
1326 if (extra) {
1327 tcg_out32(s, ADDIS | TAI(rs, base, extra));
1328 base = rs;
1329 }
1330 if (opi != ADDI || base != rt || l0 != 0) {
6ef14d7e 1331 tcg_out32(s, opi | TAI(rt & 31, base, l0));
828808f5 1332 }
1333}
1334
6ef14d7e
RH
1335static void tcg_out_vsldoi(TCGContext *s, TCGReg ret,
1336 TCGReg va, TCGReg vb, int shb)
d604f1a9 1337{
6ef14d7e
RH
1338 tcg_out32(s, VSLDOI | VRT(ret) | VRA(va) | VRB(vb) | (shb << 6));
1339}
810260a8 1340
6ef14d7e
RH
1341static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
1342 TCGReg base, intptr_t offset)
1343{
1344 int shift;
1345
1346 switch (type) {
1347 case TCG_TYPE_I32:
1348 if (ret < TCG_REG_V0) {
1349 tcg_out_mem_long(s, LWZ, LWZX, ret, base, offset);
1350 break;
1351 }
b2dda640
RH
1352 if (have_isa_2_07 && have_vsx) {
1353 tcg_out_mem_long(s, 0, LXSIWZX, ret, base, offset);
1354 break;
1355 }
6ef14d7e
RH
1356 tcg_debug_assert((offset & 3) == 0);
1357 tcg_out_mem_long(s, 0, LVEWX, ret, base, offset);
1358 shift = (offset - 4) & 0xc;
1359 if (shift) {
1360 tcg_out_vsldoi(s, ret, ret, ret, shift);
1361 }
1362 break;
1363 case TCG_TYPE_I64:
1364 if (ret < TCG_REG_V0) {
1365 tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
1366 tcg_out_mem_long(s, LD, LDX, ret, base, offset);
1367 break;
1368 }
1369 /* fallthru */
1370 case TCG_TYPE_V64:
1371 tcg_debug_assert(ret >= TCG_REG_V0);
47c906ae 1372 if (have_vsx) {
6e11cde1
RH
1373 tcg_out_mem_long(s, have_isa_3_00 ? LXSD : 0, LXSDX,
1374 ret, base, offset);
47c906ae
RH
1375 break;
1376 }
6ef14d7e
RH
1377 tcg_debug_assert((offset & 7) == 0);
1378 tcg_out_mem_long(s, 0, LVX, ret, base, offset & -16);
1379 if (offset & 8) {
1380 tcg_out_vsldoi(s, ret, ret, ret, 8);
1381 }
1382 break;
1383 case TCG_TYPE_V128:
1384 tcg_debug_assert(ret >= TCG_REG_V0);
1385 tcg_debug_assert((offset & 15) == 0);
6e11cde1
RH
1386 tcg_out_mem_long(s, have_isa_3_00 ? LXV : 0,
1387 LVX, ret, base, offset);
6ef14d7e
RH
1388 break;
1389 default:
1390 g_assert_not_reached();
d604f1a9 1391 }
d604f1a9 1392}
fedee3e7 1393
6ef14d7e
RH
1394static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1395 TCGReg base, intptr_t offset)
810260a8 1396{
6ef14d7e 1397 int shift;
fedee3e7 1398
6ef14d7e
RH
1399 switch (type) {
1400 case TCG_TYPE_I32:
1401 if (arg < TCG_REG_V0) {
1402 tcg_out_mem_long(s, STW, STWX, arg, base, offset);
1403 break;
1404 }
b2dda640
RH
1405 if (have_isa_2_07 && have_vsx) {
1406 tcg_out_mem_long(s, 0, STXSIWX, arg, base, offset);
1407 break;
1408 }
1409 assert((offset & 3) == 0);
6ef14d7e
RH
1410 tcg_debug_assert((offset & 3) == 0);
1411 shift = (offset - 4) & 0xc;
1412 if (shift) {
1413 tcg_out_vsldoi(s, TCG_VEC_TMP1, arg, arg, shift);
1414 arg = TCG_VEC_TMP1;
1415 }
1416 tcg_out_mem_long(s, 0, STVEWX, arg, base, offset);
1417 break;
1418 case TCG_TYPE_I64:
1419 if (arg < TCG_REG_V0) {
1420 tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
1421 tcg_out_mem_long(s, STD, STDX, arg, base, offset);
1422 break;
1423 }
1424 /* fallthru */
1425 case TCG_TYPE_V64:
1426 tcg_debug_assert(arg >= TCG_REG_V0);
47c906ae 1427 if (have_vsx) {
6e11cde1
RH
1428 tcg_out_mem_long(s, have_isa_3_00 ? STXSD : 0,
1429 STXSDX, arg, base, offset);
47c906ae
RH
1430 break;
1431 }
6ef14d7e
RH
1432 tcg_debug_assert((offset & 7) == 0);
1433 if (offset & 8) {
1434 tcg_out_vsldoi(s, TCG_VEC_TMP1, arg, arg, 8);
1435 arg = TCG_VEC_TMP1;
1436 }
1437 tcg_out_mem_long(s, 0, STVEWX, arg, base, offset);
1438 tcg_out_mem_long(s, 0, STVEWX, arg, base, offset + 4);
1439 break;
1440 case TCG_TYPE_V128:
1441 tcg_debug_assert(arg >= TCG_REG_V0);
6e11cde1
RH
1442 tcg_out_mem_long(s, have_isa_3_00 ? STXV : 0,
1443 STVX, arg, base, offset);
6ef14d7e
RH
1444 break;
1445 default:
1446 g_assert_not_reached();
fedee3e7 1447 }
d604f1a9 1448}
810260a8 1449
59d7c14e
RH
1450static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1451 TCGReg base, intptr_t ofs)
1452{
1453 return false;
1454}
1455
d604f1a9
RH
1456static void tcg_out_cmp(TCGContext *s, int cond, TCGArg arg1, TCGArg arg2,
1457 int const_arg2, int cr, TCGType type)
1458{
1459 int imm;
1460 uint32_t op;
810260a8 1461
abcf61c4
RH
1462 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
1463
d604f1a9
RH
1464 /* Simplify the comparisons below wrt CMPI. */
1465 if (type == TCG_TYPE_I32) {
1466 arg2 = (int32_t)arg2;
4a40e231 1467 }
fedee3e7 1468
d604f1a9
RH
1469 switch (cond) {
1470 case TCG_COND_EQ:
1471 case TCG_COND_NE:
1472 if (const_arg2) {
1473 if ((int16_t) arg2 == arg2) {
1474 op = CMPI;
1475 imm = 1;
1476 break;
1477 } else if ((uint16_t) arg2 == arg2) {
1478 op = CMPLI;
1479 imm = 1;
1480 break;
1481 }
1482 }
1483 op = CMPL;
1484 imm = 0;
1485 break;
fedee3e7 1486
d604f1a9
RH
1487 case TCG_COND_LT:
1488 case TCG_COND_GE:
1489 case TCG_COND_LE:
1490 case TCG_COND_GT:
1491 if (const_arg2) {
1492 if ((int16_t) arg2 == arg2) {
1493 op = CMPI;
1494 imm = 1;
1495 break;
1496 }
1497 }
1498 op = CMP;
1499 imm = 0;
1500 break;
fedee3e7 1501
d604f1a9
RH
1502 case TCG_COND_LTU:
1503 case TCG_COND_GEU:
1504 case TCG_COND_LEU:
1505 case TCG_COND_GTU:
1506 if (const_arg2) {
1507 if ((uint16_t) arg2 == arg2) {
1508 op = CMPLI;
1509 imm = 1;
1510 break;
1511 }
1512 }
1513 op = CMPL;
1514 imm = 0;
1515 break;
fedee3e7 1516
d604f1a9 1517 default:
732e89f4 1518 g_assert_not_reached();
fedee3e7 1519 }
d604f1a9 1520 op |= BF(cr) | ((type == TCG_TYPE_I64) << 21);
fedee3e7 1521
d604f1a9
RH
1522 if (imm) {
1523 tcg_out32(s, op | RA(arg1) | (arg2 & 0xffff));
1524 } else {
1525 if (const_arg2) {
1526 tcg_out_movi(s, type, TCG_REG_R0, arg2);
1527 arg2 = TCG_REG_R0;
1528 }
1529 tcg_out32(s, op | RA(arg1) | RB(arg2));
1530 }
810260a8 1531}
1532
d604f1a9
RH
1533static void tcg_out_setcond_eq0(TCGContext *s, TCGType type,
1534 TCGReg dst, TCGReg src)
7f12d649 1535{
a757e1ee
RH
1536 if (type == TCG_TYPE_I32) {
1537 tcg_out32(s, CNTLZW | RS(src) | RA(dst));
1538 tcg_out_shri32(s, dst, dst, 5);
1539 } else {
1540 tcg_out32(s, CNTLZD | RS(src) | RA(dst));
1541 tcg_out_shri64(s, dst, dst, 6);
1542 }
7f12d649
RH
1543}
1544
d604f1a9 1545static void tcg_out_setcond_ne0(TCGContext *s, TCGReg dst, TCGReg src)
7f12d649 1546{
d604f1a9
RH
1547 /* X != 0 implies X + -1 generates a carry. Extra addition
1548 trickery means: R = X-1 + ~X + C = X-1 + (-X+1) + C = C. */
1549 if (dst != src) {
1550 tcg_out32(s, ADDIC | TAI(dst, src, -1));
1551 tcg_out32(s, SUBFE | TAB(dst, dst, src));
7f12d649 1552 } else {
d604f1a9
RH
1553 tcg_out32(s, ADDIC | TAI(TCG_REG_R0, src, -1));
1554 tcg_out32(s, SUBFE | TAB(dst, TCG_REG_R0, src));
7f12d649 1555 }
d604f1a9 1556}
7f12d649 1557
d604f1a9
RH
1558static TCGReg tcg_gen_setcond_xor(TCGContext *s, TCGReg arg1, TCGArg arg2,
1559 bool const_arg2)
1560{
1561 if (const_arg2) {
1562 if ((uint32_t)arg2 == arg2) {
1563 tcg_out_xori32(s, TCG_REG_R0, arg1, arg2);
1564 } else {
1565 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_R0, arg2);
1566 tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, TCG_REG_R0));
1567 }
1568 } else {
1569 tcg_out32(s, XOR | SAB(arg1, TCG_REG_R0, arg2));
1570 }
1571 return TCG_REG_R0;
7f12d649
RH
1572}
1573
d604f1a9
RH
1574static void tcg_out_setcond(TCGContext *s, TCGType type, TCGCond cond,
1575 TCGArg arg0, TCGArg arg1, TCGArg arg2,
1576 int const_arg2)
7f12d649 1577{
d604f1a9 1578 int crop, sh;
7f12d649 1579
eabb7b91 1580 tcg_debug_assert(TCG_TARGET_REG_BITS == 64 || type == TCG_TYPE_I32);
a757e1ee 1581
d604f1a9
RH
1582 /* Ignore high bits of a potential constant arg2. */
1583 if (type == TCG_TYPE_I32) {
1584 arg2 = (uint32_t)arg2;
1585 }
7f12d649 1586
d604f1a9
RH
1587 /* Handle common and trivial cases before handling anything else. */
1588 if (arg2 == 0) {
1589 switch (cond) {
1590 case TCG_COND_EQ:
1591 tcg_out_setcond_eq0(s, type, arg0, arg1);
1592 return;
1593 case TCG_COND_NE:
a757e1ee 1594 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
d604f1a9
RH
1595 tcg_out_ext32u(s, TCG_REG_R0, arg1);
1596 arg1 = TCG_REG_R0;
1597 }
1598 tcg_out_setcond_ne0(s, arg0, arg1);
1599 return;
1600 case TCG_COND_GE:
1601 tcg_out32(s, NOR | SAB(arg1, arg0, arg1));
1602 arg1 = arg0;
1603 /* FALLTHRU */
1604 case TCG_COND_LT:
1605 /* Extract the sign bit. */
a757e1ee
RH
1606 if (type == TCG_TYPE_I32) {
1607 tcg_out_shri32(s, arg0, arg1, 31);
1608 } else {
1609 tcg_out_shri64(s, arg0, arg1, 63);
1610 }
d604f1a9
RH
1611 return;
1612 default:
1613 break;
1614 }
1615 }
7f12d649 1616
d604f1a9
RH
1617 /* If we have ISEL, we can implement everything with 3 or 4 insns.
1618 All other cases below are also at least 3 insns, so speed up the
1619 code generator by not considering them and always using ISEL. */
63922f46 1620 if (have_isel) {
d604f1a9 1621 int isel, tab;
7f12d649 1622
d604f1a9 1623 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
7f12d649 1624
d604f1a9 1625 isel = tcg_to_isel[cond];
7f12d649 1626
d604f1a9
RH
1627 tcg_out_movi(s, type, arg0, 1);
1628 if (isel & 1) {
1629 /* arg0 = (bc ? 0 : 1) */
1630 tab = TAB(arg0, 0, arg0);
1631 isel &= ~1;
1632 } else {
1633 /* arg0 = (bc ? 1 : 0) */
1634 tcg_out_movi(s, type, TCG_REG_R0, 0);
1635 tab = TAB(arg0, arg0, TCG_REG_R0);
1636 }
1637 tcg_out32(s, isel | tab);
1638 return;
1639 }
49d9870a 1640
d604f1a9
RH
1641 switch (cond) {
1642 case TCG_COND_EQ:
1643 arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
1644 tcg_out_setcond_eq0(s, type, arg0, arg1);
1645 return;
810260a8 1646
d604f1a9
RH
1647 case TCG_COND_NE:
1648 arg1 = tcg_gen_setcond_xor(s, arg1, arg2, const_arg2);
1649 /* Discard the high bits only once, rather than both inputs. */
a757e1ee 1650 if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
d604f1a9
RH
1651 tcg_out_ext32u(s, TCG_REG_R0, arg1);
1652 arg1 = TCG_REG_R0;
1653 }
1654 tcg_out_setcond_ne0(s, arg0, arg1);
1655 return;
810260a8 1656
d604f1a9
RH
1657 case TCG_COND_GT:
1658 case TCG_COND_GTU:
1659 sh = 30;
1660 crop = 0;
1661 goto crtest;
810260a8 1662
d604f1a9
RH
1663 case TCG_COND_LT:
1664 case TCG_COND_LTU:
1665 sh = 29;
1666 crop = 0;
1667 goto crtest;
810260a8 1668
d604f1a9
RH
1669 case TCG_COND_GE:
1670 case TCG_COND_GEU:
1671 sh = 31;
1672 crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_LT) | BB(7, CR_LT);
1673 goto crtest;
810260a8 1674
d604f1a9
RH
1675 case TCG_COND_LE:
1676 case TCG_COND_LEU:
1677 sh = 31;
1678 crop = CRNOR | BT(7, CR_EQ) | BA(7, CR_GT) | BB(7, CR_GT);
1679 crtest:
1680 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
1681 if (crop) {
1682 tcg_out32(s, crop);
1683 }
1684 tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
1685 tcg_out_rlw(s, RLWINM, arg0, TCG_REG_R0, sh, 31, 31);
1686 break;
1687
1688 default:
732e89f4 1689 g_assert_not_reached();
d604f1a9 1690 }
810260a8 1691}
1692
bec16311 1693static void tcg_out_bc(TCGContext *s, int bc, TCGLabel *l)
810260a8 1694{
d604f1a9 1695 if (l->has_value) {
d54401df 1696 bc |= reloc_pc14_val(tcg_splitwx_to_rx(s->code_ptr), l->u.value_ptr);
49d9870a 1697 } else {
bec16311 1698 tcg_out_reloc(s, s->code_ptr, R_PPC_REL14, l, 0);
810260a8 1699 }
f9c7246f 1700 tcg_out32(s, bc);
810260a8 1701}
1702
d604f1a9
RH
1703static void tcg_out_brcond(TCGContext *s, TCGCond cond,
1704 TCGArg arg1, TCGArg arg2, int const_arg2,
bec16311 1705 TCGLabel *l, TCGType type)
810260a8 1706{
d604f1a9 1707 tcg_out_cmp(s, cond, arg1, arg2, const_arg2, 7, type);
bec16311 1708 tcg_out_bc(s, tcg_to_bc[cond], l);
d604f1a9 1709}
fa94c3be 1710
d604f1a9
RH
1711static void tcg_out_movcond(TCGContext *s, TCGType type, TCGCond cond,
1712 TCGArg dest, TCGArg c1, TCGArg c2, TCGArg v1,
1713 TCGArg v2, bool const_c2)
1714{
1715 /* If for some reason both inputs are zero, don't produce bad code. */
1716 if (v1 == 0 && v2 == 0) {
1717 tcg_out_movi(s, type, dest, 0);
1718 return;
b9e946c7 1719 }
f6548c0a 1720
d604f1a9 1721 tcg_out_cmp(s, cond, c1, c2, const_c2, 7, type);
a69abbe0 1722
63922f46 1723 if (have_isel) {
d604f1a9 1724 int isel = tcg_to_isel[cond];
810260a8 1725
d604f1a9
RH
1726 /* Swap the V operands if the operation indicates inversion. */
1727 if (isel & 1) {
1728 int t = v1;
1729 v1 = v2;
1730 v2 = t;
1731 isel &= ~1;
1732 }
1733 /* V1 == 0 is handled by isel; V2 == 0 must be handled by hand. */
1734 if (v2 == 0) {
1735 tcg_out_movi(s, type, TCG_REG_R0, 0);
1736 }
1737 tcg_out32(s, isel | TAB(dest, v1, v2));
1738 } else {
1739 if (dest == v2) {
1740 cond = tcg_invert_cond(cond);
1741 v2 = v1;
1742 } else if (dest != v1) {
1743 if (v1 == 0) {
1744 tcg_out_movi(s, type, dest, 0);
1745 } else {
1746 tcg_out_mov(s, type, dest, v1);
1747 }
1748 }
1749 /* Branch forward over one insn */
1750 tcg_out32(s, tcg_to_bc[cond] | 8);
1751 if (v2 == 0) {
1752 tcg_out_movi(s, type, dest, 0);
1753 } else {
1754 tcg_out_mov(s, type, dest, v2);
1755 }
29b69198 1756 }
810260a8 1757}
1758
d0b07481
RH
1759static void tcg_out_cntxz(TCGContext *s, TCGType type, uint32_t opc,
1760 TCGArg a0, TCGArg a1, TCGArg a2, bool const_a2)
1761{
1762 if (const_a2 && a2 == (type == TCG_TYPE_I32 ? 32 : 64)) {
1763 tcg_out32(s, opc | RA(a0) | RS(a1));
1764 } else {
1765 tcg_out_cmp(s, TCG_COND_EQ, a1, 0, 1, 7, type);
1766 /* Note that the only other valid constant for a2 is 0. */
63922f46 1767 if (have_isel) {
d0b07481
RH
1768 tcg_out32(s, opc | RA(TCG_REG_R0) | RS(a1));
1769 tcg_out32(s, tcg_to_isel[TCG_COND_EQ] | TAB(a0, a2, TCG_REG_R0));
1770 } else if (!const_a2 && a0 == a2) {
1771 tcg_out32(s, tcg_to_bc[TCG_COND_EQ] | 8);
1772 tcg_out32(s, opc | RA(a0) | RS(a1));
1773 } else {
1774 tcg_out32(s, opc | RA(a0) | RS(a1));
1775 tcg_out32(s, tcg_to_bc[TCG_COND_NE] | 8);
1776 if (const_a2) {
1777 tcg_out_movi(s, type, a0, 0);
1778 } else {
1779 tcg_out_mov(s, type, a0, a2);
1780 }
1781 }
1782 }
1783}
1784
abcf61c4
RH
1785static void tcg_out_cmp2(TCGContext *s, const TCGArg *args,
1786 const int *const_args)
1787{
1788 static const struct { uint8_t bit1, bit2; } bits[] = {
1789 [TCG_COND_LT ] = { CR_LT, CR_LT },
1790 [TCG_COND_LE ] = { CR_LT, CR_GT },
1791 [TCG_COND_GT ] = { CR_GT, CR_GT },
1792 [TCG_COND_GE ] = { CR_GT, CR_LT },
1793 [TCG_COND_LTU] = { CR_LT, CR_LT },
1794 [TCG_COND_LEU] = { CR_LT, CR_GT },
1795 [TCG_COND_GTU] = { CR_GT, CR_GT },
1796 [TCG_COND_GEU] = { CR_GT, CR_LT },
1797 };
1798
1799 TCGCond cond = args[4], cond2;
1800 TCGArg al, ah, bl, bh;
1801 int blconst, bhconst;
1802 int op, bit1, bit2;
1803
1804 al = args[0];
1805 ah = args[1];
1806 bl = args[2];
1807 bh = args[3];
1808 blconst = const_args[2];
1809 bhconst = const_args[3];
1810
1811 switch (cond) {
1812 case TCG_COND_EQ:
1813 op = CRAND;
1814 goto do_equality;
1815 case TCG_COND_NE:
1816 op = CRNAND;
1817 do_equality:
1818 tcg_out_cmp(s, cond, al, bl, blconst, 6, TCG_TYPE_I32);
1819 tcg_out_cmp(s, cond, ah, bh, bhconst, 7, TCG_TYPE_I32);
1820 tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
1821 break;
1822
1823 case TCG_COND_LT:
1824 case TCG_COND_LE:
1825 case TCG_COND_GT:
1826 case TCG_COND_GE:
1827 case TCG_COND_LTU:
1828 case TCG_COND_LEU:
1829 case TCG_COND_GTU:
1830 case TCG_COND_GEU:
1831 bit1 = bits[cond].bit1;
1832 bit2 = bits[cond].bit2;
1833 op = (bit1 != bit2 ? CRANDC : CRAND);
1834 cond2 = tcg_unsigned_cond(cond);
1835
1836 tcg_out_cmp(s, cond, ah, bh, bhconst, 6, TCG_TYPE_I32);
1837 tcg_out_cmp(s, cond2, al, bl, blconst, 7, TCG_TYPE_I32);
1838 tcg_out32(s, op | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, bit2));
1839 tcg_out32(s, CROR | BT(7, CR_EQ) | BA(6, bit1) | BB(7, CR_EQ));
1840 break;
1841
1842 default:
732e89f4 1843 g_assert_not_reached();
abcf61c4
RH
1844 }
1845}
1846
1847static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
1848 const int *const_args)
1849{
1850 tcg_out_cmp2(s, args + 1, const_args + 1);
1851 tcg_out32(s, MFOCRF | RT(TCG_REG_R0) | FXM(7));
1852 tcg_out_rlw(s, RLWINM, args[0], TCG_REG_R0, 31, 31, 31);
1853}
1854
1855static void tcg_out_brcond2 (TCGContext *s, const TCGArg *args,
1856 const int *const_args)
1857{
1858 tcg_out_cmp2(s, args, const_args);
bec16311 1859 tcg_out_bc(s, BC | BI(7, CR_EQ) | BO_COND_TRUE, arg_label(args[5]));
abcf61c4
RH
1860}
1861
7b4af5ee
PK
1862static void tcg_out_mb(TCGContext *s, TCGArg a0)
1863{
fc879703
NP
1864 uint32_t insn;
1865
1866 if (a0 & TCG_MO_ST_LD) {
1867 insn = HWSYNC;
1868 } else {
7b4af5ee 1869 insn = LWSYNC;
7b4af5ee 1870 }
fc879703 1871
7b4af5ee
PK
1872 tcg_out32(s, insn);
1873}
1874
8605cbcd
RH
1875static void tcg_out_call_int(TCGContext *s, int lk,
1876 const tcg_insn_unit *target)
810260a8 1877{
eaf7d1cf 1878#ifdef _CALL_AIX
d604f1a9
RH
1879 /* Look through the descriptor. If the branch is in range, and we
1880 don't have to spend too much effort on building the toc. */
2be7d76b
RH
1881 const void *tgt = ((const void * const *)target)[0];
1882 uintptr_t toc = ((const uintptr_t *)target)[1];
d604f1a9 1883 intptr_t diff = tcg_pcrel_diff(s, tgt);
b18d5d2b 1884
d604f1a9 1885 if (in_range_b(diff) && toc == (uint32_t)toc) {
dfca1778 1886 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, toc);
8605cbcd 1887 tcg_out_b(s, lk, tgt);
541dd4ce 1888 } else {
d604f1a9
RH
1889 /* Fold the low bits of the constant into the addresses below. */
1890 intptr_t arg = (intptr_t)target;
1891 int ofs = (int16_t)arg;
1892
1893 if (ofs + 8 < 0x8000) {
1894 arg -= ofs;
1895 } else {
1896 ofs = 0;
1897 }
dfca1778
RH
1898 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, arg);
1899 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_TMP1, ofs);
d604f1a9 1900 tcg_out32(s, MTSPR | RA(TCG_REG_R0) | CTR);
dfca1778 1901 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R2, TCG_REG_TMP1, ofs + SZP);
8605cbcd 1902 tcg_out32(s, BCCTR | BO_ALWAYS | lk);
541dd4ce 1903 }
77e58d0d
UW
1904#elif defined(_CALL_ELF) && _CALL_ELF == 2
1905 intptr_t diff;
1906
1907 /* In the ELFv2 ABI, we have to set up r12 to contain the destination
1908 address, which the callee uses to compute its TOC address. */
1909 /* FIXME: when the branch is in range, we could avoid r12 load if we
1910 knew that the destination uses the same TOC, and what its local
1911 entry point offset is. */
1912 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R12, (intptr_t)target);
1913
1914 diff = tcg_pcrel_diff(s, target);
1915 if (in_range_b(diff)) {
8605cbcd 1916 tcg_out_b(s, lk, target);
77e58d0d
UW
1917 } else {
1918 tcg_out32(s, MTSPR | RS(TCG_REG_R12) | CTR);
8605cbcd 1919 tcg_out32(s, BCCTR | BO_ALWAYS | lk);
77e58d0d 1920 }
eaf7d1cf 1921#else
8605cbcd 1922 tcg_out_b(s, lk, target);
d604f1a9 1923#endif
810260a8 1924}
1925
cee44b03
RH
1926static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target,
1927 const TCGHelperInfo *info)
8605cbcd
RH
1928{
1929 tcg_out_call_int(s, LK, target);
1930}
1931
4b473e0c 1932static const uint32_t qemu_ldx_opc[(MO_SSIZE + MO_BSWAP) + 1] = {
d604f1a9
RH
1933 [MO_UB] = LBZX,
1934 [MO_UW] = LHZX,
1935 [MO_UL] = LWZX,
fc313c64 1936 [MO_UQ] = LDX,
d604f1a9
RH
1937 [MO_SW] = LHAX,
1938 [MO_SL] = LWAX,
1939 [MO_BSWAP | MO_UB] = LBZX,
1940 [MO_BSWAP | MO_UW] = LHBRX,
1941 [MO_BSWAP | MO_UL] = LWBRX,
fc313c64 1942 [MO_BSWAP | MO_UQ] = LDBRX,
d604f1a9 1943};
810260a8 1944
4b473e0c 1945static const uint32_t qemu_stx_opc[(MO_SIZE + MO_BSWAP) + 1] = {
d604f1a9
RH
1946 [MO_UB] = STBX,
1947 [MO_UW] = STHX,
1948 [MO_UL] = STWX,
fc313c64 1949 [MO_UQ] = STDX,
d604f1a9
RH
1950 [MO_BSWAP | MO_UB] = STBX,
1951 [MO_BSWAP | MO_UW] = STHBRX,
1952 [MO_BSWAP | MO_UL] = STWBRX,
fc313c64 1953 [MO_BSWAP | MO_UQ] = STDBRX,
d604f1a9 1954};
991041a4 1955
d604f1a9
RH
1956static const uint32_t qemu_exts_opc[4] = {
1957 EXTSB, EXTSH, EXTSW, 0
1958};
810260a8 1959
d604f1a9
RH
1960#if defined (CONFIG_SOFTMMU)
1961/* helper signature: helper_ld_mmu(CPUState *env, target_ulong addr,
1962 * int mmu_idx, uintptr_t ra)
1963 */
4b473e0c 1964static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
d604f1a9
RH
1965 [MO_UB] = helper_ret_ldub_mmu,
1966 [MO_LEUW] = helper_le_lduw_mmu,
1967 [MO_LEUL] = helper_le_ldul_mmu,
fc313c64 1968 [MO_LEUQ] = helper_le_ldq_mmu,
d604f1a9
RH
1969 [MO_BEUW] = helper_be_lduw_mmu,
1970 [MO_BEUL] = helper_be_ldul_mmu,
fc313c64 1971 [MO_BEUQ] = helper_be_ldq_mmu,
d604f1a9 1972};
810260a8 1973
d604f1a9
RH
1974/* helper signature: helper_st_mmu(CPUState *env, target_ulong addr,
1975 * uintxx_t val, int mmu_idx, uintptr_t ra)
1976 */
4b473e0c 1977static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
d604f1a9
RH
1978 [MO_UB] = helper_ret_stb_mmu,
1979 [MO_LEUW] = helper_le_stw_mmu,
1980 [MO_LEUL] = helper_le_stl_mmu,
fc313c64 1981 [MO_LEUQ] = helper_le_stq_mmu,
d604f1a9
RH
1982 [MO_BEUW] = helper_be_stw_mmu,
1983 [MO_BEUL] = helper_be_stl_mmu,
fc313c64 1984 [MO_BEUQ] = helper_be_stq_mmu,
d604f1a9 1985};
810260a8 1986
269bd5d8
RH
1987/* We expect to use a 16-bit negative offset from ENV. */
1988QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
1989QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -32768);
1990
d604f1a9
RH
1991/* Perform the TLB load and compare. Places the result of the comparison
1992 in CR7, loads the addend of the TLB into R3, and returns the register
1993 containing the guest address (zero-extended into R4). Clobbers R0 and R2. */
1994
14776ab5 1995static TCGReg tcg_out_tlb_read(TCGContext *s, MemOp opc,
7f25c469 1996 TCGReg addrlo, TCGReg addrhi,
d604f1a9
RH
1997 int mem_index, bool is_read)
1998{
1999 int cmp_off
2000 = (is_read
644f591a
RH
2001 ? offsetof(CPUTLBEntry, addr_read)
2002 : offsetof(CPUTLBEntry, addr_write));
269bd5d8
RH
2003 int fast_off = TLB_MASK_TABLE_OFS(mem_index);
2004 int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
2005 int table_off = fast_off + offsetof(CPUTLBDescFast, table);
85aa8081
RH
2006 unsigned s_bits = opc & MO_SIZE;
2007 unsigned a_bits = get_alignment_bits(opc);
d604f1a9 2008
644f591a 2009 /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
269bd5d8
RH
2010 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_AREG0, mask_off);
2011 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R4, TCG_AREG0, table_off);
644f591a
RH
2012
2013 /* Extract the page index, shifted into place for tlb index. */
2014 if (TCG_TARGET_REG_BITS == 32) {
2015 tcg_out_shri32(s, TCG_REG_TMP1, addrlo,
2016 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
4c314da6 2017 } else {
644f591a
RH
2018 tcg_out_shri64(s, TCG_REG_TMP1, addrlo,
2019 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
810260a8 2020 }
644f591a 2021 tcg_out32(s, AND | SAB(TCG_REG_R3, TCG_REG_R3, TCG_REG_TMP1));
810260a8 2022
644f591a
RH
2023 /* Load the TLB comparator. */
2024 if (cmp_off == 0 && TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
2025 uint32_t lxu = (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32
2026 ? LWZUX : LDUX);
2027 tcg_out32(s, lxu | TAB(TCG_REG_TMP1, TCG_REG_R3, TCG_REG_R4));
7f25c469 2028 } else {
644f591a
RH
2029 tcg_out32(s, ADD | TAB(TCG_REG_R3, TCG_REG_R3, TCG_REG_R4));
2030 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
2031 tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_TMP1, TCG_REG_R3, cmp_off + 4);
2032 tcg_out_ld(s, TCG_TYPE_I32, TCG_REG_R4, TCG_REG_R3, cmp_off);
2033 } else {
2034 tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP1, TCG_REG_R3, cmp_off);
2035 }
7f25c469 2036 }
d604f1a9
RH
2037
2038 /* Load the TLB addend for use on the fast path. Do this asap
2039 to minimize any load use delay. */
644f591a
RH
2040 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R3, TCG_REG_R3,
2041 offsetof(CPUTLBEntry, addend));
d604f1a9 2042
68d45bb6 2043 /* Clear the non-page, non-alignment bits from the address */
85aa8081
RH
2044 if (TCG_TARGET_REG_BITS == 32) {
2045 /* We don't support unaligned accesses on 32-bits.
2046 * Preserve the bottom bits and thus trigger a comparison
2047 * failure on unaligned accesses.
68d45bb6 2048 */
85aa8081 2049 if (a_bits < s_bits) {
1f00b27f
SS
2050 a_bits = s_bits;
2051 }
7f25c469 2052 tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0,
1f00b27f 2053 (32 - a_bits) & 31, 31 - TARGET_PAGE_BITS);
85aa8081
RH
2054 } else {
2055 TCGReg t = addrlo;
2056
2057 /* If the access is unaligned, we need to make sure we fail if we
2058 * cross a page boundary. The trick is to add the access size-1
2059 * to the address before masking the low bits. That will make the
2060 * address overflow to the next page if we cross a page boundary,
2061 * which will then force a mismatch of the TLB compare.
2062 */
2063 if (a_bits < s_bits) {
2064 unsigned a_mask = (1 << a_bits) - 1;
2065 unsigned s_mask = (1 << s_bits) - 1;
2066 tcg_out32(s, ADDI | TAI(TCG_REG_R0, t, s_mask - a_mask));
2067 t = TCG_REG_R0;
2068 }
2069
2070 /* Mask the address for the requested alignment. */
2071 if (TARGET_LONG_BITS == 32) {
2072 tcg_out_rlw(s, RLWINM, TCG_REG_R0, t, 0,
2073 (32 - a_bits) & 31, 31 - TARGET_PAGE_BITS);
644f591a
RH
2074 /* Zero-extend the address for use in the final address. */
2075 tcg_out_ext32u(s, TCG_REG_R4, addrlo);
2076 addrlo = TCG_REG_R4;
85aa8081
RH
2077 } else if (a_bits == 0) {
2078 tcg_out_rld(s, RLDICR, TCG_REG_R0, t, 0, 63 - TARGET_PAGE_BITS);
2079 } else {
2080 tcg_out_rld(s, RLDICL, TCG_REG_R0, t,
1f00b27f 2081 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - a_bits);
68d45bb6 2082 tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
68d45bb6 2083 }
70fac59a 2084 }
d604f1a9 2085
7f25c469 2086 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
dfca1778
RH
2087 tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
2088 0, 7, TCG_TYPE_I32);
7f25c469
RH
2089 tcg_out_cmp(s, TCG_COND_EQ, addrhi, TCG_REG_R4, 0, 6, TCG_TYPE_I32);
2090 tcg_out32(s, CRAND | BT(7, CR_EQ) | BA(6, CR_EQ) | BB(7, CR_EQ));
2091 } else {
dfca1778
RH
2092 tcg_out_cmp(s, TCG_COND_EQ, TCG_REG_R0, TCG_REG_TMP1,
2093 0, 7, TCG_TYPE_TL);
7f25c469 2094 }
d604f1a9 2095
7f25c469 2096 return addrlo;
70fac59a 2097}
1cd62ae9 2098
d604f1a9
RH
2099/* Record the context of a call to the out of line helper code for the slow
2100 path for a load or store, so that we can later generate the correct
2101 helper code. */
9002ffcb 2102static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi,
7f25c469
RH
2103 TCGReg datalo_reg, TCGReg datahi_reg,
2104 TCGReg addrlo_reg, TCGReg addrhi_reg,
3972ef6f 2105 tcg_insn_unit *raddr, tcg_insn_unit *lptr)
70fac59a 2106{
d604f1a9
RH
2107 TCGLabelQemuLdst *label = new_ldst_label(s);
2108
2109 label->is_ld = is_ld;
3972ef6f 2110 label->oi = oi;
7f25c469
RH
2111 label->datalo_reg = datalo_reg;
2112 label->datahi_reg = datahi_reg;
2113 label->addrlo_reg = addrlo_reg;
2114 label->addrhi_reg = addrhi_reg;
e5e2e4c7 2115 label->raddr = tcg_splitwx_to_rx(raddr);
7f25c469 2116 label->label_ptr[0] = lptr;
70fac59a 2117}
1cd62ae9 2118
aeee05f5 2119static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
70fac59a 2120{
9002ffcb 2121 MemOpIdx oi = lb->oi;
14776ab5 2122 MemOp opc = get_memop(oi);
7f25c469 2123 TCGReg hi, lo, arg = TCG_REG_R3;
70fac59a 2124
d54401df 2125 if (!reloc_pc14(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
aeee05f5
RH
2126 return false;
2127 }
70fac59a 2128
7f25c469 2129 tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
1cd62ae9 2130
7f25c469
RH
2131 lo = lb->addrlo_reg;
2132 hi = lb->addrhi_reg;
2133 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
c8eef960 2134 arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
7f25c469
RH
2135 tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
2136 tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
2137 } else {
2138 /* If the address needed to be zero-extended, we'll have already
2139 placed it in R4. The only remaining case is 64-bit guest. */
2140 tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
2141 }
752c1fdb 2142
3972ef6f 2143 tcg_out_movi(s, TCG_TYPE_I32, arg++, oi);
7f25c469 2144 tcg_out32(s, MFSPR | RT(arg) | LR);
70fac59a 2145
cee44b03 2146 tcg_out_call_int(s, LK, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
70fac59a 2147
7f25c469
RH
2148 lo = lb->datalo_reg;
2149 hi = lb->datahi_reg;
2150 if (TCG_TARGET_REG_BITS == 32 && (opc & MO_SIZE) == MO_64) {
2151 tcg_out_mov(s, TCG_TYPE_I32, lo, TCG_REG_R4);
2152 tcg_out_mov(s, TCG_TYPE_I32, hi, TCG_REG_R3);
2153 } else if (opc & MO_SIGN) {
d604f1a9 2154 uint32_t insn = qemu_exts_opc[opc & MO_SIZE];
7f25c469 2155 tcg_out32(s, insn | RA(lo) | RS(TCG_REG_R3));
d604f1a9 2156 } else {
7f25c469 2157 tcg_out_mov(s, TCG_TYPE_REG, lo, TCG_REG_R3);
70fac59a
RH
2158 }
2159
d604f1a9 2160 tcg_out_b(s, 0, lb->raddr);
aeee05f5 2161 return true;
d604f1a9 2162}
70fac59a 2163
aeee05f5 2164static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
d604f1a9 2165{
9002ffcb 2166 MemOpIdx oi = lb->oi;
14776ab5
TN
2167 MemOp opc = get_memop(oi);
2168 MemOp s_bits = opc & MO_SIZE;
7f25c469 2169 TCGReg hi, lo, arg = TCG_REG_R3;
1cd62ae9 2170
d54401df 2171 if (!reloc_pc14(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
aeee05f5
RH
2172 return false;
2173 }
1cd62ae9 2174
7f25c469
RH
2175 tcg_out_mov(s, TCG_TYPE_PTR, arg++, TCG_AREG0);
2176
2177 lo = lb->addrlo_reg;
2178 hi = lb->addrhi_reg;
2179 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
c8eef960 2180 arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
7f25c469
RH
2181 tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
2182 tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
2183 } else {
2184 /* If the address needed to be zero-extended, we'll have already
2185 placed it in R4. The only remaining case is 64-bit guest. */
2186 tcg_out_mov(s, TCG_TYPE_TL, arg++, lo);
2187 }
1cd62ae9 2188
7f25c469
RH
2189 lo = lb->datalo_reg;
2190 hi = lb->datahi_reg;
2191 if (TCG_TARGET_REG_BITS == 32) {
2192 switch (s_bits) {
2193 case MO_64:
c8eef960 2194 arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
7f25c469
RH
2195 tcg_out_mov(s, TCG_TYPE_I32, arg++, hi);
2196 /* FALLTHRU */
2197 case MO_32:
2198 tcg_out_mov(s, TCG_TYPE_I32, arg++, lo);
2199 break;
2200 default:
2201 tcg_out_rlw(s, RLWINM, arg++, lo, 0, 32 - (8 << s_bits), 31);
2202 break;
2203 }
2204 } else {
2205 if (s_bits == MO_64) {
2206 tcg_out_mov(s, TCG_TYPE_I64, arg++, lo);
2207 } else {
2208 tcg_out_rld(s, RLDICL, arg++, lo, 0, 64 - (8 << s_bits));
2209 }
2210 }
1cd62ae9 2211
3972ef6f 2212 tcg_out_movi(s, TCG_TYPE_I32, arg++, oi);
7f25c469 2213 tcg_out32(s, MFSPR | RT(arg) | LR);
1cd62ae9 2214
cee44b03 2215 tcg_out_call_int(s, LK, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
d604f1a9
RH
2216
2217 tcg_out_b(s, 0, lb->raddr);
aeee05f5 2218 return true;
1cd62ae9 2219}
8605cbcd
RH
2220#else
2221
2222static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addrlo,
2223 TCGReg addrhi, unsigned a_bits)
2224{
2225 unsigned a_mask = (1 << a_bits) - 1;
2226 TCGLabelQemuLdst *label = new_ldst_label(s);
2227
2228 label->is_ld = is_ld;
2229 label->addrlo_reg = addrlo;
2230 label->addrhi_reg = addrhi;
2231
2232 /* We are expecting a_bits to max out at 7, much lower than ANDI. */
2233 tcg_debug_assert(a_bits < 16);
2234 tcg_out32(s, ANDI | SAI(addrlo, TCG_REG_R0, a_mask));
2235
2236 label->label_ptr[0] = s->code_ptr;
2237 tcg_out32(s, BC | BI(0, CR_EQ) | BO_COND_FALSE | LK);
2238
2239 label->raddr = tcg_splitwx_to_rx(s->code_ptr);
2240}
2241
2242static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
2243{
2244 if (!reloc_pc14(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
2245 return false;
2246 }
2247
2248 if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
2249 TCGReg arg = TCG_REG_R4;
c8eef960
RH
2250
2251 arg |= (TCG_TARGET_CALL_ARG_I64 == TCG_CALL_ARG_EVEN);
8605cbcd
RH
2252 if (l->addrlo_reg != arg) {
2253 tcg_out_mov(s, TCG_TYPE_I32, arg, l->addrhi_reg);
2254 tcg_out_mov(s, TCG_TYPE_I32, arg + 1, l->addrlo_reg);
2255 } else if (l->addrhi_reg != arg + 1) {
2256 tcg_out_mov(s, TCG_TYPE_I32, arg + 1, l->addrlo_reg);
2257 tcg_out_mov(s, TCG_TYPE_I32, arg, l->addrhi_reg);
2258 } else {
2259 tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R0, arg);
2260 tcg_out_mov(s, TCG_TYPE_I32, arg, arg + 1);
2261 tcg_out_mov(s, TCG_TYPE_I32, arg + 1, TCG_REG_R0);
2262 }
2263 } else {
2264 tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_R4, l->addrlo_reg);
2265 }
2266 tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_R3, TCG_AREG0);
2267
2268 /* "Tail call" to the helper, with the return address back inline. */
2269 tcg_out_call_int(s, 0, (const void *)(l->is_ld ? helper_unaligned_ld
2270 : helper_unaligned_st));
2271 return true;
2272}
2273
2274static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
2275{
2276 return tcg_out_fail_alignment(s, l);
2277}
2278
2279static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
2280{
2281 return tcg_out_fail_alignment(s, l);
2282}
2283
d604f1a9 2284#endif /* SOFTMMU */
1cd62ae9 2285
7f25c469 2286static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
810260a8 2287{
7f25c469
RH
2288 TCGReg datalo, datahi, addrlo, rbase;
2289 TCGReg addrhi __attribute__((unused));
9002ffcb 2290 MemOpIdx oi;
14776ab5 2291 MemOp opc, s_bits;
d604f1a9 2292#ifdef CONFIG_SOFTMMU
7f25c469 2293 int mem_index;
d604f1a9 2294 tcg_insn_unit *label_ptr;
8605cbcd
RH
2295#else
2296 unsigned a_bits;
d604f1a9 2297#endif
810260a8 2298
7f25c469
RH
2299 datalo = *args++;
2300 datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
2301 addrlo = *args++;
2302 addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
59227d5d
RH
2303 oi = *args++;
2304 opc = get_memop(oi);
7f25c469
RH
2305 s_bits = opc & MO_SIZE;
2306
d604f1a9 2307#ifdef CONFIG_SOFTMMU
59227d5d 2308 mem_index = get_mmuidx(oi);
68d45bb6 2309 addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, true);
d604f1a9
RH
2310
2311 /* Load a pointer into the current opcode w/conditional branch-link. */
2312 label_ptr = s->code_ptr;
f9c7246f 2313 tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
d604f1a9
RH
2314
2315 rbase = TCG_REG_R3;
2316#else /* !CONFIG_SOFTMMU */
8605cbcd
RH
2317 a_bits = get_alignment_bits(opc);
2318 if (a_bits) {
2319 tcg_out_test_alignment(s, true, addrlo, addrhi, a_bits);
2320 }
b76f21a7 2321 rbase = guest_base ? TCG_GUEST_BASE_REG : 0;
7f25c469 2322 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
dfca1778
RH
2323 tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
2324 addrlo = TCG_REG_TMP1;
d604f1a9
RH
2325 }
2326#endif
2327
7f25c469
RH
2328 if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
2329 if (opc & MO_BSWAP) {
2330 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
2331 tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
2332 tcg_out32(s, LWBRX | TAB(datahi, rbase, TCG_REG_R0));
2333 } else if (rbase != 0) {
2334 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
2335 tcg_out32(s, LWZX | TAB(datahi, rbase, addrlo));
2336 tcg_out32(s, LWZX | TAB(datalo, rbase, TCG_REG_R0));
2337 } else if (addrlo == datahi) {
2338 tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
2339 tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
2340 } else {
2341 tcg_out32(s, LWZ | TAI(datahi, addrlo, 0));
2342 tcg_out32(s, LWZ | TAI(datalo, addrlo, 4));
2343 }
541dd4ce 2344 } else {
2b7ec66f 2345 uint32_t insn = qemu_ldx_opc[opc & (MO_BSWAP | MO_SSIZE)];
4e33fe01 2346 if (!have_isa_2_06 && insn == LDBRX) {
7f25c469
RH
2347 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
2348 tcg_out32(s, LWBRX | TAB(datalo, rbase, addrlo));
2349 tcg_out32(s, LWBRX | TAB(TCG_REG_R0, rbase, TCG_REG_R0));
2350 tcg_out_rld(s, RLDIMI, datalo, TCG_REG_R0, 32, 0);
2351 } else if (insn) {
2352 tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
2353 } else {
2354 insn = qemu_ldx_opc[opc & (MO_SIZE | MO_BSWAP)];
2355 tcg_out32(s, insn | TAB(datalo, rbase, addrlo));
2356 insn = qemu_exts_opc[s_bits];
2357 tcg_out32(s, insn | RA(datalo) | RS(datalo));
2358 }
810260a8 2359 }
810260a8 2360
d604f1a9 2361#ifdef CONFIG_SOFTMMU
3972ef6f
RH
2362 add_qemu_ldst_label(s, true, oi, datalo, datahi, addrlo, addrhi,
2363 s->code_ptr, label_ptr);
d604f1a9 2364#endif
810260a8 2365}
2366
7f25c469 2367static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
027ffea9 2368{
7f25c469
RH
2369 TCGReg datalo, datahi, addrlo, rbase;
2370 TCGReg addrhi __attribute__((unused));
9002ffcb 2371 MemOpIdx oi;
14776ab5 2372 MemOp opc, s_bits;
d604f1a9 2373#ifdef CONFIG_SOFTMMU
7f25c469 2374 int mem_index;
d604f1a9 2375 tcg_insn_unit *label_ptr;
8605cbcd
RH
2376#else
2377 unsigned a_bits;
d604f1a9 2378#endif
027ffea9 2379
7f25c469
RH
2380 datalo = *args++;
2381 datahi = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
2382 addrlo = *args++;
2383 addrhi = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
59227d5d
RH
2384 oi = *args++;
2385 opc = get_memop(oi);
7f25c469
RH
2386 s_bits = opc & MO_SIZE;
2387
d604f1a9 2388#ifdef CONFIG_SOFTMMU
59227d5d 2389 mem_index = get_mmuidx(oi);
68d45bb6 2390 addrlo = tcg_out_tlb_read(s, opc, addrlo, addrhi, mem_index, false);
027ffea9 2391
d604f1a9
RH
2392 /* Load a pointer into the current opcode w/conditional branch-link. */
2393 label_ptr = s->code_ptr;
f9c7246f 2394 tcg_out32(s, BC | BI(7, CR_EQ) | BO_COND_FALSE | LK);
027ffea9 2395
d604f1a9
RH
2396 rbase = TCG_REG_R3;
2397#else /* !CONFIG_SOFTMMU */
8605cbcd
RH
2398 a_bits = get_alignment_bits(opc);
2399 if (a_bits) {
2400 tcg_out_test_alignment(s, false, addrlo, addrhi, a_bits);
2401 }
b76f21a7 2402 rbase = guest_base ? TCG_GUEST_BASE_REG : 0;
7f25c469 2403 if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
dfca1778
RH
2404 tcg_out_ext32u(s, TCG_REG_TMP1, addrlo);
2405 addrlo = TCG_REG_TMP1;
d604f1a9
RH
2406 }
2407#endif
2408
7f25c469
RH
2409 if (TCG_TARGET_REG_BITS == 32 && s_bits == MO_64) {
2410 if (opc & MO_BSWAP) {
2411 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
2412 tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
2413 tcg_out32(s, STWBRX | SAB(datahi, rbase, TCG_REG_R0));
2414 } else if (rbase != 0) {
2415 tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, 4));
2416 tcg_out32(s, STWX | SAB(datahi, rbase, addrlo));
2417 tcg_out32(s, STWX | SAB(datalo, rbase, TCG_REG_R0));
2418 } else {
2419 tcg_out32(s, STW | TAI(datahi, addrlo, 0));
2420 tcg_out32(s, STW | TAI(datalo, addrlo, 4));
2421 }
027ffea9 2422 } else {
2b7ec66f 2423 uint32_t insn = qemu_stx_opc[opc & (MO_BSWAP | MO_SIZE)];
4e33fe01 2424 if (!have_isa_2_06 && insn == STDBRX) {
7f25c469 2425 tcg_out32(s, STWBRX | SAB(datalo, rbase, addrlo));
dfca1778 2426 tcg_out32(s, ADDI | TAI(TCG_REG_TMP1, addrlo, 4));
7f25c469 2427 tcg_out_shri64(s, TCG_REG_R0, datalo, 32);
dfca1778 2428 tcg_out32(s, STWBRX | SAB(TCG_REG_R0, rbase, TCG_REG_TMP1));
7f25c469
RH
2429 } else {
2430 tcg_out32(s, insn | SAB(datalo, rbase, addrlo));
2431 }
027ffea9 2432 }
d604f1a9
RH
2433
2434#ifdef CONFIG_SOFTMMU
3972ef6f
RH
2435 add_qemu_ldst_label(s, false, oi, datalo, datahi, addrlo, addrhi,
2436 s->code_ptr, label_ptr);
d604f1a9 2437#endif
027ffea9
RH
2438}
2439
53c89efd
RH
2440static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
2441{
2442 int i;
2443 for (i = 0; i < count; ++i) {
2444 p[i] = NOP;
2445 }
2446}
2447
a921fddc
RH
2448/* Parameters for function call generation, used in tcg.c. */
2449#define TCG_TARGET_STACK_ALIGN 16
a921fddc 2450
802ca56e
RH
2451#ifdef _CALL_AIX
2452# define LINK_AREA_SIZE (6 * SZR)
2453# define LR_OFFSET (1 * SZR)
2454# define TCG_TARGET_CALL_STACK_OFFSET (LINK_AREA_SIZE + 8 * SZR)
2fa169ba 2455#elif defined(_CALL_DARWIN)
1045fc04
PM
2456# define LINK_AREA_SIZE (6 * SZR)
2457# define LR_OFFSET (2 * SZR)
ffcfbece
RH
2458#elif TCG_TARGET_REG_BITS == 64
2459# if defined(_CALL_ELF) && _CALL_ELF == 2
2460# define LINK_AREA_SIZE (4 * SZR)
2461# define LR_OFFSET (1 * SZR)
2462# endif
2463#else /* TCG_TARGET_REG_BITS == 32 */
2464# if defined(_CALL_SYSV)
ffcfbece
RH
2465# define LINK_AREA_SIZE (2 * SZR)
2466# define LR_OFFSET (1 * SZR)
ffcfbece
RH
2467# endif
2468#endif
2469#ifndef LR_OFFSET
2470# error "Unhandled abi"
2471#endif
2472#ifndef TCG_TARGET_CALL_STACK_OFFSET
a2a98f80 2473# define TCG_TARGET_CALL_STACK_OFFSET LINK_AREA_SIZE
802ca56e
RH
2474#endif
2475
2476#define CPU_TEMP_BUF_SIZE (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2477#define REG_SAVE_SIZE ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * SZR)
d604f1a9 2478
802ca56e
RH
2479#define FRAME_SIZE ((TCG_TARGET_CALL_STACK_OFFSET \
2480 + TCG_STATIC_CALL_ARGS_SIZE \
2481 + CPU_TEMP_BUF_SIZE \
2482 + REG_SAVE_SIZE \
2483 + TCG_TARGET_STACK_ALIGN - 1) \
2484 & -TCG_TARGET_STACK_ALIGN)
2485
2486#define REG_SAVE_BOT (FRAME_SIZE - REG_SAVE_SIZE)
d604f1a9
RH
2487
2488static void tcg_target_qemu_prologue(TCGContext *s)
810260a8 2489{
d604f1a9 2490 int i;
810260a8 2491
802ca56e 2492#ifdef _CALL_AIX
d54401df
RH
2493 const void **desc = (const void **)s->code_ptr;
2494 desc[0] = tcg_splitwx_to_rx(desc + 2); /* entry point */
2495 desc[1] = 0; /* environment pointer */
2496 s->code_ptr = (void *)(desc + 2); /* skip over descriptor */
d604f1a9
RH
2497#endif
2498
a84ac4cb
RH
2499 tcg_set_frame(s, TCG_REG_CALL_STACK, REG_SAVE_BOT - CPU_TEMP_BUF_SIZE,
2500 CPU_TEMP_BUF_SIZE);
2501
d604f1a9
RH
2502 /* Prologue */
2503 tcg_out32(s, MFSPR | RT(TCG_REG_R0) | LR);
ffcfbece
RH
2504 tcg_out32(s, (SZR == 8 ? STDU : STWU)
2505 | SAI(TCG_REG_R1, TCG_REG_R1, -FRAME_SIZE));
802ca56e 2506
d604f1a9 2507 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
4c3831a0
RH
2508 tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2509 TCG_REG_R1, REG_SAVE_BOT + i * SZR);
d604f1a9 2510 }
802ca56e 2511 tcg_out_st(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
d604f1a9 2512
4cbea598 2513#ifndef CONFIG_SOFTMMU
b76f21a7 2514 if (guest_base) {
5964fca8 2515 tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base, true);
d604f1a9
RH
2516 tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2517 }
2518#endif
2519
2520 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2521 tcg_out32(s, MTSPR | RS(tcg_target_call_iarg_regs[1]) | CTR);
5964fca8
RH
2522 if (USE_REG_TB) {
2523 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
a84ac4cb 2524 }
5964fca8 2525 tcg_out32(s, BCCTR | BO_ALWAYS);
d604f1a9
RH
2526
2527 /* Epilogue */
c8bc1168 2528 tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
d604f1a9 2529
802ca56e 2530 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_R0, TCG_REG_R1, FRAME_SIZE+LR_OFFSET);
d604f1a9 2531 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i) {
4c3831a0
RH
2532 tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2533 TCG_REG_R1, REG_SAVE_BOT + i * SZR);
d604f1a9 2534 }
d604f1a9
RH
2535 tcg_out32(s, MTSPR | RS(TCG_REG_R0) | LR);
2536 tcg_out32(s, ADDI | TAI(TCG_REG_R1, TCG_REG_R1, FRAME_SIZE));
2537 tcg_out32(s, BCLR | BO_ALWAYS);
810260a8 2538}
2539
b55a8d9d
RH
2540static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg)
2541{
2542 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, arg);
2543 tcg_out_b(s, 0, tcg_code_gen_epilogue);
2544}
2545
cf7d6b8e 2546static void tcg_out_goto_tb(TCGContext *s, int which)
810260a8 2547{
20b66433
RH
2548 uintptr_t ptr = get_jmp_target_addr(s, which);
2549
2550 if (USE_REG_TB) {
2551 ptrdiff_t offset = tcg_tbrel_diff(s, (void *)ptr);
2552 tcg_out_mem_long(s, LD, LDX, TCG_REG_TB, TCG_REG_TB, offset);
2553
2554 /* Direct branch will be patched by tb_target_set_jmp_target. */
cf7d6b8e 2555 set_jmp_insn_offset(s, which);
5964fca8 2556 tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR);
20b66433
RH
2557
2558 /* When branch is out of range, fall through to indirect. */
5bfd75a3 2559 tcg_out32(s, BCCTR | BO_ALWAYS);
20b66433
RH
2560
2561 /* For the unlinked case, need to reset TCG_REG_TB. */
cf7d6b8e 2562 set_jmp_reset_offset(s, which);
20b66433
RH
2563 tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB,
2564 -tcg_current_code_size(s));
cf7d6b8e 2565 } else {
20b66433 2566 /* Direct branch will be patched by tb_target_set_jmp_target. */
cf7d6b8e 2567 set_jmp_insn_offset(s, which);
20b66433
RH
2568 tcg_out32(s, NOP);
2569
2570 /* When branch is out of range, fall through to indirect. */
2571 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, ptr - (int16_t)ptr);
2572 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1, (int16_t)ptr);
2573 tcg_out32(s, MTSPR | RS(TCG_REG_TMP1) | CTR);
2574 tcg_out32(s, BCCTR | BO_ALWAYS);
cf7d6b8e
RH
2575 set_jmp_reset_offset(s, which);
2576 }
2577}
2578
20b66433
RH
2579void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
2580 uintptr_t jmp_rx, uintptr_t jmp_rw)
2581{
2582 uintptr_t addr = tb->jmp_target_addr[n];
2583 intptr_t diff = addr - jmp_rx;
2584 tcg_insn_unit insn;
2585
2586 if (in_range_b(diff)) {
2587 insn = B | (diff & 0x3fffffc);
2588 } else if (USE_REG_TB) {
2589 insn = MTSPR | RS(TCG_REG_TB) | CTR;
2590 } else {
2591 insn = NOP;
2592 }
2593
2594 qatomic_set((uint32_t *)jmp_rw, insn);
2595 flush_idcache_range(jmp_rx, jmp_rw, 4);
2596}
2597
cf7d6b8e
RH
2598static void tcg_out_op(TCGContext *s, TCGOpcode opc,
2599 const TCGArg args[TCG_MAX_OP_ARGS],
2600 const int const_args[TCG_MAX_OP_ARGS])
2601{
2602 TCGArg a0, a1, a2;
2603
2604 switch (opc) {
0c240785
RH
2605 case INDEX_op_goto_ptr:
2606 tcg_out32(s, MTSPR | RS(args[0]) | CTR);
5964fca8
RH
2607 if (USE_REG_TB) {
2608 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, args[0]);
2609 }
2610 tcg_out32(s, ADDI | TAI(TCG_REG_R3, 0, 0));
0c240785
RH
2611 tcg_out32(s, BCCTR | BO_ALWAYS);
2612 break;
810260a8 2613 case INDEX_op_br:
2614 {
bec16311 2615 TCGLabel *l = arg_label(args[0]);
f9c7246f 2616 uint32_t insn = B;
810260a8 2617
2618 if (l->has_value) {
d54401df
RH
2619 insn |= reloc_pc24_val(tcg_splitwx_to_rx(s->code_ptr),
2620 l->u.value_ptr);
541dd4ce 2621 } else {
bec16311 2622 tcg_out_reloc(s, s->code_ptr, R_PPC_REL24, l, 0);
810260a8 2623 }
f9c7246f 2624 tcg_out32(s, insn);
810260a8 2625 }
2626 break;
810260a8 2627 case INDEX_op_ld8u_i32:
2628 case INDEX_op_ld8u_i64:
b18d5d2b 2629 tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
810260a8 2630 break;
2631 case INDEX_op_ld8s_i32:
2632 case INDEX_op_ld8s_i64:
b18d5d2b 2633 tcg_out_mem_long(s, LBZ, LBZX, args[0], args[1], args[2]);
678155b2 2634 tcg_out_ext8s(s, TCG_TYPE_REG, args[0], args[0]);
810260a8 2635 break;
2636 case INDEX_op_ld16u_i32:
2637 case INDEX_op_ld16u_i64:
b18d5d2b 2638 tcg_out_mem_long(s, LHZ, LHZX, args[0], args[1], args[2]);
810260a8 2639 break;
2640 case INDEX_op_ld16s_i32:
2641 case INDEX_op_ld16s_i64:
b18d5d2b 2642 tcg_out_mem_long(s, LHA, LHAX, args[0], args[1], args[2]);
810260a8 2643 break;
2644 case INDEX_op_ld_i32:
2645 case INDEX_op_ld32u_i64:
b18d5d2b 2646 tcg_out_mem_long(s, LWZ, LWZX, args[0], args[1], args[2]);
810260a8 2647 break;
2648 case INDEX_op_ld32s_i64:
b18d5d2b 2649 tcg_out_mem_long(s, LWA, LWAX, args[0], args[1], args[2]);
810260a8 2650 break;
2651 case INDEX_op_ld_i64:
b18d5d2b 2652 tcg_out_mem_long(s, LD, LDX, args[0], args[1], args[2]);
810260a8 2653 break;
2654 case INDEX_op_st8_i32:
2655 case INDEX_op_st8_i64:
b18d5d2b 2656 tcg_out_mem_long(s, STB, STBX, args[0], args[1], args[2]);
810260a8 2657 break;
2658 case INDEX_op_st16_i32:
2659 case INDEX_op_st16_i64:
b18d5d2b 2660 tcg_out_mem_long(s, STH, STHX, args[0], args[1], args[2]);
810260a8 2661 break;
2662 case INDEX_op_st_i32:
2663 case INDEX_op_st32_i64:
b18d5d2b 2664 tcg_out_mem_long(s, STW, STWX, args[0], args[1], args[2]);
810260a8 2665 break;
2666 case INDEX_op_st_i64:
b18d5d2b 2667 tcg_out_mem_long(s, STD, STDX, args[0], args[1], args[2]);
810260a8 2668 break;
2669
2670 case INDEX_op_add_i32:
ee924fa6
RH
2671 a0 = args[0], a1 = args[1], a2 = args[2];
2672 if (const_args[2]) {
ee924fa6 2673 do_addi_32:
b18d5d2b 2674 tcg_out_mem_long(s, ADDI, ADD, a0, a1, (int32_t)a2);
ee924fa6
RH
2675 } else {
2676 tcg_out32(s, ADD | TAB(a0, a1, a2));
2677 }
810260a8 2678 break;
2679 case INDEX_op_sub_i32:
ee924fa6 2680 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
2681 if (const_args[1]) {
2682 if (const_args[2]) {
2683 tcg_out_movi(s, TCG_TYPE_I32, a0, a1 - a2);
2684 } else {
2685 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
2686 }
2687 } else if (const_args[2]) {
ee924fa6
RH
2688 a2 = -a2;
2689 goto do_addi_32;
2690 } else {
2691 tcg_out32(s, SUBF | TAB(a0, a2, a1));
2692 }
810260a8 2693 break;
2694
2695 case INDEX_op_and_i32:
37251b98 2696 a0 = args[0], a1 = args[1], a2 = args[2];
a9249dff 2697 if (const_args[2]) {
37251b98 2698 tcg_out_andi32(s, a0, a1, a2);
a9249dff 2699 } else {
37251b98 2700 tcg_out32(s, AND | SAB(a1, a0, a2));
a9249dff
RH
2701 }
2702 break;
2703 case INDEX_op_and_i64:
37251b98 2704 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 2705 if (const_args[2]) {
37251b98 2706 tcg_out_andi64(s, a0, a1, a2);
637af30c 2707 } else {
37251b98 2708 tcg_out32(s, AND | SAB(a1, a0, a2));
810260a8 2709 }
810260a8 2710 break;
fe6f943f 2711 case INDEX_op_or_i64:
810260a8 2712 case INDEX_op_or_i32:
dce74c57 2713 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 2714 if (const_args[2]) {
dce74c57
RH
2715 tcg_out_ori32(s, a0, a1, a2);
2716 } else {
2717 tcg_out32(s, OR | SAB(a1, a0, a2));
810260a8 2718 }
810260a8 2719 break;
fe6f943f 2720 case INDEX_op_xor_i64:
810260a8 2721 case INDEX_op_xor_i32:
dce74c57 2722 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 2723 if (const_args[2]) {
dce74c57
RH
2724 tcg_out_xori32(s, a0, a1, a2);
2725 } else {
2726 tcg_out32(s, XOR | SAB(a1, a0, a2));
810260a8 2727 }
810260a8 2728 break;
ce1010d6 2729 case INDEX_op_andc_i32:
37251b98
RH
2730 a0 = args[0], a1 = args[1], a2 = args[2];
2731 if (const_args[2]) {
2732 tcg_out_andi32(s, a0, a1, ~a2);
2733 } else {
2734 tcg_out32(s, ANDC | SAB(a1, a0, a2));
2735 }
2736 break;
ce1010d6 2737 case INDEX_op_andc_i64:
37251b98
RH
2738 a0 = args[0], a1 = args[1], a2 = args[2];
2739 if (const_args[2]) {
2740 tcg_out_andi64(s, a0, a1, ~a2);
2741 } else {
2742 tcg_out32(s, ANDC | SAB(a1, a0, a2));
2743 }
ce1010d6
RH
2744 break;
2745 case INDEX_op_orc_i32:
37251b98
RH
2746 if (const_args[2]) {
2747 tcg_out_ori32(s, args[0], args[1], ~args[2]);
2748 break;
2749 }
2750 /* FALLTHRU */
ce1010d6
RH
2751 case INDEX_op_orc_i64:
2752 tcg_out32(s, ORC | SAB(args[1], args[0], args[2]));
2753 break;
2754 case INDEX_op_eqv_i32:
37251b98
RH
2755 if (const_args[2]) {
2756 tcg_out_xori32(s, args[0], args[1], ~args[2]);
2757 break;
2758 }
2759 /* FALLTHRU */
ce1010d6
RH
2760 case INDEX_op_eqv_i64:
2761 tcg_out32(s, EQV | SAB(args[1], args[0], args[2]));
2762 break;
2763 case INDEX_op_nand_i32:
2764 case INDEX_op_nand_i64:
2765 tcg_out32(s, NAND | SAB(args[1], args[0], args[2]));
2766 break;
2767 case INDEX_op_nor_i32:
2768 case INDEX_op_nor_i64:
2769 tcg_out32(s, NOR | SAB(args[1], args[0], args[2]));
2770 break;
810260a8 2771
d0b07481
RH
2772 case INDEX_op_clz_i32:
2773 tcg_out_cntxz(s, TCG_TYPE_I32, CNTLZW, args[0], args[1],
2774 args[2], const_args[2]);
2775 break;
2776 case INDEX_op_ctz_i32:
2777 tcg_out_cntxz(s, TCG_TYPE_I32, CNTTZW, args[0], args[1],
2778 args[2], const_args[2]);
2779 break;
33e75fb9
RH
2780 case INDEX_op_ctpop_i32:
2781 tcg_out32(s, CNTPOPW | SAB(args[1], args[0], 0));
2782 break;
d0b07481
RH
2783
2784 case INDEX_op_clz_i64:
2785 tcg_out_cntxz(s, TCG_TYPE_I64, CNTLZD, args[0], args[1],
2786 args[2], const_args[2]);
2787 break;
2788 case INDEX_op_ctz_i64:
2789 tcg_out_cntxz(s, TCG_TYPE_I64, CNTTZD, args[0], args[1],
2790 args[2], const_args[2]);
2791 break;
33e75fb9
RH
2792 case INDEX_op_ctpop_i64:
2793 tcg_out32(s, CNTPOPD | SAB(args[1], args[0], 0));
2794 break;
d0b07481 2795
810260a8 2796 case INDEX_op_mul_i32:
ef809300 2797 a0 = args[0], a1 = args[1], a2 = args[2];
810260a8 2798 if (const_args[2]) {
ef809300
RH
2799 tcg_out32(s, MULLI | TAI(a0, a1, a2));
2800 } else {
2801 tcg_out32(s, MULLW | TAB(a0, a1, a2));
810260a8 2802 }
810260a8 2803 break;
2804
2805 case INDEX_op_div_i32:
541dd4ce 2806 tcg_out32(s, DIVW | TAB(args[0], args[1], args[2]));
810260a8 2807 break;
2808
2809 case INDEX_op_divu_i32:
541dd4ce 2810 tcg_out32(s, DIVWU | TAB(args[0], args[1], args[2]));
810260a8 2811 break;
2812
4d573822
MKF
2813 case INDEX_op_rem_i32:
2814 tcg_out32(s, MODSW | TAB(args[0], args[1], args[2]));
2815 break;
2816
2817 case INDEX_op_remu_i32:
2818 tcg_out32(s, MODUW | TAB(args[0], args[1], args[2]));
2819 break;
2820
810260a8 2821 case INDEX_op_shl_i32:
2822 if (const_args[2]) {
94248cfc
CF
2823 /* Limit immediate shift count lest we create an illegal insn. */
2824 tcg_out_shli32(s, args[0], args[1], args[2] & 31);
9e555b73 2825 } else {
541dd4ce 2826 tcg_out32(s, SLW | SAB(args[1], args[0], args[2]));
9e555b73 2827 }
810260a8 2828 break;
2829 case INDEX_op_shr_i32:
2830 if (const_args[2]) {
94248cfc
CF
2831 /* Limit immediate shift count lest we create an illegal insn. */
2832 tcg_out_shri32(s, args[0], args[1], args[2] & 31);
9e555b73 2833 } else {
541dd4ce 2834 tcg_out32(s, SRW | SAB(args[1], args[0], args[2]));
9e555b73 2835 }
810260a8 2836 break;
2837 case INDEX_op_sar_i32:
541dd4ce 2838 if (const_args[2]) {
05dd01fa 2839 tcg_out_sari32(s, args[0], args[1], args[2]);
541dd4ce
RH
2840 } else {
2841 tcg_out32(s, SRAW | SAB(args[1], args[0], args[2]));
2842 }
810260a8 2843 break;
313d91c7
RH
2844 case INDEX_op_rotl_i32:
2845 if (const_args[2]) {
2846 tcg_out_rlw(s, RLWINM, args[0], args[1], args[2], 0, 31);
2847 } else {
2848 tcg_out32(s, RLWNM | SAB(args[1], args[0], args[2])
2849 | MB(0) | ME(31));
2850 }
2851 break;
2852 case INDEX_op_rotr_i32:
2853 if (const_args[2]) {
2854 tcg_out_rlw(s, RLWINM, args[0], args[1], 32 - args[2], 0, 31);
2855 } else {
8327a470
RH
2856 tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 32));
2857 tcg_out32(s, RLWNM | SAB(args[1], args[0], TCG_REG_R0)
313d91c7
RH
2858 | MB(0) | ME(31));
2859 }
2860 break;
810260a8 2861
2862 case INDEX_op_brcond_i32:
4c314da6 2863 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
bec16311 2864 arg_label(args[3]), TCG_TYPE_I32);
e924bbec 2865 break;
810260a8 2866 case INDEX_op_brcond_i64:
4c314da6 2867 tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
bec16311 2868 arg_label(args[3]), TCG_TYPE_I64);
810260a8 2869 break;
abcf61c4
RH
2870 case INDEX_op_brcond2_i32:
2871 tcg_out_brcond2(s, args, const_args);
2872 break;
810260a8 2873
2874 case INDEX_op_neg_i32:
810260a8 2875 case INDEX_op_neg_i64:
541dd4ce 2876 tcg_out32(s, NEG | RT(args[0]) | RA(args[1]));
810260a8 2877 break;
2878
157f2662 2879 case INDEX_op_not_i32:
2880 case INDEX_op_not_i64:
541dd4ce 2881 tcg_out32(s, NOR | SAB(args[1], args[0], args[1]));
157f2662 2882 break;
2883
810260a8 2884 case INDEX_op_add_i64:
ee924fa6
RH
2885 a0 = args[0], a1 = args[1], a2 = args[2];
2886 if (const_args[2]) {
ee924fa6 2887 do_addi_64:
b18d5d2b 2888 tcg_out_mem_long(s, ADDI, ADD, a0, a1, a2);
ee924fa6
RH
2889 } else {
2890 tcg_out32(s, ADD | TAB(a0, a1, a2));
2891 }
810260a8 2892 break;
2893 case INDEX_op_sub_i64:
ee924fa6 2894 a0 = args[0], a1 = args[1], a2 = args[2];
148bdd23
RH
2895 if (const_args[1]) {
2896 if (const_args[2]) {
2897 tcg_out_movi(s, TCG_TYPE_I64, a0, a1 - a2);
2898 } else {
2899 tcg_out32(s, SUBFIC | TAI(a0, a2, a1));
2900 }
2901 } else if (const_args[2]) {
ee924fa6
RH
2902 a2 = -a2;
2903 goto do_addi_64;
2904 } else {
2905 tcg_out32(s, SUBF | TAB(a0, a2, a1));
2906 }
810260a8 2907 break;
2908
2909 case INDEX_op_shl_i64:
541dd4ce 2910 if (const_args[2]) {
94248cfc
CF
2911 /* Limit immediate shift count lest we create an illegal insn. */
2912 tcg_out_shli64(s, args[0], args[1], args[2] & 63);
541dd4ce
RH
2913 } else {
2914 tcg_out32(s, SLD | SAB(args[1], args[0], args[2]));
2915 }
810260a8 2916 break;
2917 case INDEX_op_shr_i64:
541dd4ce 2918 if (const_args[2]) {
94248cfc
CF
2919 /* Limit immediate shift count lest we create an illegal insn. */
2920 tcg_out_shri64(s, args[0], args[1], args[2] & 63);
541dd4ce
RH
2921 } else {
2922 tcg_out32(s, SRD | SAB(args[1], args[0], args[2]));
2923 }
810260a8 2924 break;
2925 case INDEX_op_sar_i64:
fe6f943f 2926 if (const_args[2]) {
05dd01fa 2927 tcg_out_sari64(s, args[0], args[1], args[2]);
541dd4ce
RH
2928 } else {
2929 tcg_out32(s, SRAD | SAB(args[1], args[0], args[2]));
fe6f943f 2930 }
810260a8 2931 break;
313d91c7
RH
2932 case INDEX_op_rotl_i64:
2933 if (const_args[2]) {
2934 tcg_out_rld(s, RLDICL, args[0], args[1], args[2], 0);
2935 } else {
2936 tcg_out32(s, RLDCL | SAB(args[1], args[0], args[2]) | MB64(0));
2937 }
2938 break;
2939 case INDEX_op_rotr_i64:
2940 if (const_args[2]) {
2941 tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 0);
2942 } else {
8327a470
RH
2943 tcg_out32(s, SUBFIC | TAI(TCG_REG_R0, args[2], 64));
2944 tcg_out32(s, RLDCL | SAB(args[1], args[0], TCG_REG_R0) | MB64(0));
313d91c7
RH
2945 }
2946 break;
810260a8 2947
2948 case INDEX_op_mul_i64:
ef809300
RH
2949 a0 = args[0], a1 = args[1], a2 = args[2];
2950 if (const_args[2]) {
2951 tcg_out32(s, MULLI | TAI(a0, a1, a2));
2952 } else {
2953 tcg_out32(s, MULLD | TAB(a0, a1, a2));
2954 }
810260a8 2955 break;
2956 case INDEX_op_div_i64:
541dd4ce 2957 tcg_out32(s, DIVD | TAB(args[0], args[1], args[2]));
810260a8 2958 break;
2959 case INDEX_op_divu_i64:
541dd4ce 2960 tcg_out32(s, DIVDU | TAB(args[0], args[1], args[2]));
810260a8 2961 break;
4d573822
MKF
2962 case INDEX_op_rem_i64:
2963 tcg_out32(s, MODSD | TAB(args[0], args[1], args[2]));
2964 break;
2965 case INDEX_op_remu_i64:
2966 tcg_out32(s, MODUD | TAB(args[0], args[1], args[2]));
2967 break;
810260a8 2968
1768ec06 2969 case INDEX_op_qemu_ld_i32:
7f25c469
RH
2970 tcg_out_qemu_ld(s, args, false);
2971 break;
1768ec06 2972 case INDEX_op_qemu_ld_i64:
7f25c469 2973 tcg_out_qemu_ld(s, args, true);
810260a8 2974 break;
1768ec06 2975 case INDEX_op_qemu_st_i32:
7f25c469
RH
2976 tcg_out_qemu_st(s, args, false);
2977 break;
1768ec06 2978 case INDEX_op_qemu_st_i64:
7f25c469 2979 tcg_out_qemu_st(s, args, true);
810260a8 2980 break;
2981
4f2331e5 2982 case INDEX_op_ext_i32_i64:
e46b9681 2983 case INDEX_op_ext32s_i64:
f4bf14f4 2984 tcg_out_ext32s(s, args[0], args[1]);
e46b9681 2985 break;
4f2331e5
AJ
2986 case INDEX_op_extu_i32_i64:
2987 tcg_out_ext32u(s, args[0], args[1]);
2988 break;
e46b9681 2989
1cd62ae9 2990 case INDEX_op_setcond_i32:
541dd4ce
RH
2991 tcg_out_setcond(s, TCG_TYPE_I32, args[3], args[0], args[1], args[2],
2992 const_args[2]);
1cd62ae9 2993 break;
2994 case INDEX_op_setcond_i64:
541dd4ce
RH
2995 tcg_out_setcond(s, TCG_TYPE_I64, args[3], args[0], args[1], args[2],
2996 const_args[2]);
1cd62ae9 2997 break;
abcf61c4
RH
2998 case INDEX_op_setcond2_i32:
2999 tcg_out_setcond2(s, args, const_args);
3000 break;
1cd62ae9 3001
5d221582
RH
3002 case INDEX_op_bswap16_i32:
3003 case INDEX_op_bswap16_i64:
26ce7005 3004 tcg_out_bswap16(s, args[0], args[1], args[2]);
5d221582 3005 break;
5d221582 3006 case INDEX_op_bswap32_i32:
26ce7005
RH
3007 tcg_out_bswap32(s, args[0], args[1], 0);
3008 break;
5d221582 3009 case INDEX_op_bswap32_i64:
26ce7005 3010 tcg_out_bswap32(s, args[0], args[1], args[2]);
5d221582 3011 break;
68aebd45 3012 case INDEX_op_bswap64_i64:
674ba588 3013 tcg_out_bswap64(s, args[0], args[1]);
68aebd45
RH
3014 break;
3015
33de9ed2 3016 case INDEX_op_deposit_i32:
39dc85b9
RH
3017 if (const_args[2]) {
3018 uint32_t mask = ((2u << (args[4] - 1)) - 1) << args[3];
3019 tcg_out_andi32(s, args[0], args[0], ~mask);
3020 } else {
3021 tcg_out_rlw(s, RLWIMI, args[0], args[2], args[3],
3022 32 - args[3] - args[4], 31 - args[3]);
3023 }
33de9ed2
RH
3024 break;
3025 case INDEX_op_deposit_i64:
39dc85b9
RH
3026 if (const_args[2]) {
3027 uint64_t mask = ((2ull << (args[4] - 1)) - 1) << args[3];
3028 tcg_out_andi64(s, args[0], args[0], ~mask);
3029 } else {
3030 tcg_out_rld(s, RLDIMI, args[0], args[2], args[3],
3031 64 - args[3] - args[4]);
3032 }
33de9ed2
RH
3033 break;
3034
c05021c3
RH
3035 case INDEX_op_extract_i32:
3036 tcg_out_rlw(s, RLWINM, args[0], args[1],
3037 32 - args[2], 32 - args[3], 31);
3038 break;
3039 case INDEX_op_extract_i64:
3040 tcg_out_rld(s, RLDICL, args[0], args[1], 64 - args[2], 64 - args[3]);
3041 break;
3042
027ffea9
RH
3043 case INDEX_op_movcond_i32:
3044 tcg_out_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1], args[2],
3045 args[3], args[4], const_args[2]);
3046 break;
3047 case INDEX_op_movcond_i64:
3048 tcg_out_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1], args[2],
3049 args[3], args[4], const_args[2]);
3050 break;
3051
796f1a68 3052#if TCG_TARGET_REG_BITS == 64
6c858762 3053 case INDEX_op_add2_i64:
796f1a68
RH
3054#else
3055 case INDEX_op_add2_i32:
3056#endif
6c858762
RH
3057 /* Note that the CA bit is defined based on the word size of the
3058 environment. So in 64-bit mode it's always carry-out of bit 63.
3059 The fallback code using deposit works just as well for 32-bit. */
3060 a0 = args[0], a1 = args[1];
84247357 3061 if (a0 == args[3] || (!const_args[5] && a0 == args[5])) {
6c858762
RH
3062 a0 = TCG_REG_R0;
3063 }
84247357
AB
3064 if (const_args[4]) {
3065 tcg_out32(s, ADDIC | TAI(a0, args[2], args[4]));
6c858762 3066 } else {
84247357 3067 tcg_out32(s, ADDC | TAB(a0, args[2], args[4]));
6c858762
RH
3068 }
3069 if (const_args[5]) {
84247357 3070 tcg_out32(s, (args[5] ? ADDME : ADDZE) | RT(a1) | RA(args[3]));
6c858762 3071 } else {
84247357 3072 tcg_out32(s, ADDE | TAB(a1, args[3], args[5]));
6c858762
RH
3073 }
3074 if (a0 != args[0]) {
de3d636d 3075 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
6c858762
RH
3076 }
3077 break;
3078
796f1a68 3079#if TCG_TARGET_REG_BITS == 64
6c858762 3080 case INDEX_op_sub2_i64:
796f1a68
RH
3081#else
3082 case INDEX_op_sub2_i32:
3083#endif
6c858762 3084 a0 = args[0], a1 = args[1];
b31284ce 3085 if (a0 == args[5] || (!const_args[3] && a0 == args[3])) {
6c858762
RH
3086 a0 = TCG_REG_R0;
3087 }
3088 if (const_args[2]) {
b31284ce 3089 tcg_out32(s, SUBFIC | TAI(a0, args[4], args[2]));
6c858762 3090 } else {
b31284ce 3091 tcg_out32(s, SUBFC | TAB(a0, args[4], args[2]));
6c858762 3092 }
b31284ce
RH
3093 if (const_args[3]) {
3094 tcg_out32(s, (args[3] ? SUBFME : SUBFZE) | RT(a1) | RA(args[5]));
6c858762 3095 } else {
b31284ce 3096 tcg_out32(s, SUBFE | TAB(a1, args[5], args[3]));
6c858762
RH
3097 }
3098 if (a0 != args[0]) {
de3d636d 3099 tcg_out_mov(s, TCG_TYPE_REG, args[0], a0);
6c858762
RH
3100 }
3101 break;
3102
abcf61c4
RH
3103 case INDEX_op_muluh_i32:
3104 tcg_out32(s, MULHWU | TAB(args[0], args[1], args[2]));
3105 break;
8fa391a0
RH
3106 case INDEX_op_mulsh_i32:
3107 tcg_out32(s, MULHW | TAB(args[0], args[1], args[2]));
3108 break;
32f5717f
RH
3109 case INDEX_op_muluh_i64:
3110 tcg_out32(s, MULHDU | TAB(args[0], args[1], args[2]));
3111 break;
3112 case INDEX_op_mulsh_i64:
3113 tcg_out32(s, MULHD | TAB(args[0], args[1], args[2]));
6645c147
RH
3114 break;
3115
7b4af5ee
PK
3116 case INDEX_op_mb:
3117 tcg_out_mb(s, args[0]);
3118 break;
3119
96d0ee7f
RH
3120 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
3121 case INDEX_op_mov_i64:
96d0ee7f 3122 case INDEX_op_call: /* Always emitted via tcg_out_call. */
b55a8d9d 3123 case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */
cf7d6b8e 3124 case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */
678155b2
RH
3125 case INDEX_op_ext8s_i32: /* Always emitted via tcg_reg_alloc_op. */
3126 case INDEX_op_ext8s_i64:
d0e66c89
RH
3127 case INDEX_op_ext8u_i32:
3128 case INDEX_op_ext8u_i64:
753e42ea
RH
3129 case INDEX_op_ext16s_i32:
3130 case INDEX_op_ext16s_i64:
810260a8 3131 default:
732e89f4 3132 g_assert_not_reached();
810260a8 3133 }
3134}
3135
4b06c216
RH
3136int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
3137{
6ef14d7e
RH
3138 switch (opc) {
3139 case INDEX_op_and_vec:
3140 case INDEX_op_or_vec:
3141 case INDEX_op_xor_vec:
3142 case INDEX_op_andc_vec:
3143 case INDEX_op_not_vec:
fa8e90d6
RH
3144 case INDEX_op_nor_vec:
3145 case INDEX_op_eqv_vec:
3146 case INDEX_op_nand_vec:
6ef14d7e 3147 return 1;
64ff1c6d
RH
3148 case INDEX_op_orc_vec:
3149 return have_isa_2_07;
d6750811
RH
3150 case INDEX_op_add_vec:
3151 case INDEX_op_sub_vec:
e2382972
RH
3152 case INDEX_op_smax_vec:
3153 case INDEX_op_smin_vec:
3154 case INDEX_op_umax_vec:
3155 case INDEX_op_umin_vec:
64ff1c6d
RH
3156 case INDEX_op_shlv_vec:
3157 case INDEX_op_shrv_vec:
3158 case INDEX_op_sarv_vec:
ab87a66f 3159 case INDEX_op_rotlv_vec:
64ff1c6d 3160 return vece <= MO_32 || have_isa_2_07;
e9d1a53a
RH
3161 case INDEX_op_ssadd_vec:
3162 case INDEX_op_sssub_vec:
3163 case INDEX_op_usadd_vec:
3164 case INDEX_op_ussub_vec:
e2382972 3165 return vece <= MO_32;
6ef14d7e 3166 case INDEX_op_cmp_vec:
dabae097
RH
3167 case INDEX_op_shli_vec:
3168 case INDEX_op_shri_vec:
3169 case INDEX_op_sari_vec:
ab87a66f 3170 case INDEX_op_rotli_vec:
64ff1c6d 3171 return vece <= MO_32 || have_isa_2_07 ? -1 : 0;
d7cd6a2f
RH
3172 case INDEX_op_neg_vec:
3173 return vece >= MO_32 && have_isa_3_00;
64ff1c6d
RH
3174 case INDEX_op_mul_vec:
3175 switch (vece) {
3176 case MO_8:
3177 case MO_16:
3178 return -1;
3179 case MO_32:
3180 return have_isa_2_07 ? 1 : -1;
73ebe95e
LP
3181 case MO_64:
3182 return have_isa_3_10;
64ff1c6d
RH
3183 }
3184 return 0;
47c906ae
RH
3185 case INDEX_op_bitsel_vec:
3186 return have_vsx;
ab87a66f
RH
3187 case INDEX_op_rotrv_vec:
3188 return -1;
6ef14d7e
RH
3189 default:
3190 return 0;
3191 }
4b06c216
RH
3192}
3193
3194static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
3195 TCGReg dst, TCGReg src)
3196{
6ef14d7e 3197 tcg_debug_assert(dst >= TCG_REG_V0);
b7ce3cff
RH
3198
3199 /* Splat from integer reg allowed via constraints for v3.00. */
3200 if (src < TCG_REG_V0) {
3201 tcg_debug_assert(have_isa_3_00);
3202 switch (vece) {
3203 case MO_64:
3204 tcg_out32(s, MTVSRDD | VRT(dst) | RA(src) | RB(src));
3205 return true;
3206 case MO_32:
3207 tcg_out32(s, MTVSRWS | VRT(dst) | RA(src));
3208 return true;
3209 default:
3210 /* Fail, so that we fall back on either dupm or mov+dup. */
3211 return false;
3212 }
3213 }
6ef14d7e
RH
3214
3215 /*
3216 * Recall we use (or emulate) VSX integer loads, so the integer is
3217 * right justified within the left (zero-index) double-word.
3218 */
3219 switch (vece) {
3220 case MO_8:
3221 tcg_out32(s, VSPLTB | VRT(dst) | VRB(src) | (7 << 16));
3222 break;
3223 case MO_16:
3224 tcg_out32(s, VSPLTH | VRT(dst) | VRB(src) | (3 << 16));
3225 break;
3226 case MO_32:
3227 tcg_out32(s, VSPLTW | VRT(dst) | VRB(src) | (1 << 16));
3228 break;
3229 case MO_64:
47c906ae
RH
3230 if (have_vsx) {
3231 tcg_out32(s, XXPERMDI | VRT(dst) | VRA(src) | VRB(src));
3232 break;
3233 }
6ef14d7e
RH
3234 tcg_out_vsldoi(s, TCG_VEC_TMP1, src, src, 8);
3235 tcg_out_vsldoi(s, dst, TCG_VEC_TMP1, src, 8);
3236 break;
3237 default:
3238 g_assert_not_reached();
3239 }
3240 return true;
4b06c216
RH
3241}
3242
3243static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
3244 TCGReg out, TCGReg base, intptr_t offset)
3245{
6ef14d7e
RH
3246 int elt;
3247
3248 tcg_debug_assert(out >= TCG_REG_V0);
3249 switch (vece) {
3250 case MO_8:
6e11cde1
RH
3251 if (have_isa_3_00) {
3252 tcg_out_mem_long(s, LXV, LVX, out, base, offset & -16);
3253 } else {
3254 tcg_out_mem_long(s, 0, LVEBX, out, base, offset);
3255 }
6ef14d7e 3256 elt = extract32(offset, 0, 4);
e03b5686 3257#if !HOST_BIG_ENDIAN
6ef14d7e
RH
3258 elt ^= 15;
3259#endif
3260 tcg_out32(s, VSPLTB | VRT(out) | VRB(out) | (elt << 16));
3261 break;
3262 case MO_16:
3263 tcg_debug_assert((offset & 1) == 0);
6e11cde1
RH
3264 if (have_isa_3_00) {
3265 tcg_out_mem_long(s, LXV | 8, LVX, out, base, offset & -16);
3266 } else {
3267 tcg_out_mem_long(s, 0, LVEHX, out, base, offset);
3268 }
6ef14d7e 3269 elt = extract32(offset, 1, 3);
e03b5686 3270#if !HOST_BIG_ENDIAN
6ef14d7e
RH
3271 elt ^= 7;
3272#endif
3273 tcg_out32(s, VSPLTH | VRT(out) | VRB(out) | (elt << 16));
3274 break;
3275 case MO_32:
6e11cde1
RH
3276 if (have_isa_3_00) {
3277 tcg_out_mem_long(s, 0, LXVWSX, out, base, offset);
3278 break;
3279 }
6ef14d7e
RH
3280 tcg_debug_assert((offset & 3) == 0);
3281 tcg_out_mem_long(s, 0, LVEWX, out, base, offset);
3282 elt = extract32(offset, 2, 2);
e03b5686 3283#if !HOST_BIG_ENDIAN
6ef14d7e
RH
3284 elt ^= 3;
3285#endif
3286 tcg_out32(s, VSPLTW | VRT(out) | VRB(out) | (elt << 16));
3287 break;
3288 case MO_64:
47c906ae
RH
3289 if (have_vsx) {
3290 tcg_out_mem_long(s, 0, LXVDSX, out, base, offset);
3291 break;
3292 }
6ef14d7e
RH
3293 tcg_debug_assert((offset & 7) == 0);
3294 tcg_out_mem_long(s, 0, LVX, out, base, offset & -16);
3295 tcg_out_vsldoi(s, TCG_VEC_TMP1, out, out, 8);
3296 elt = extract32(offset, 3, 1);
e03b5686 3297#if !HOST_BIG_ENDIAN
6ef14d7e
RH
3298 elt = !elt;
3299#endif
3300 if (elt) {
3301 tcg_out_vsldoi(s, out, out, TCG_VEC_TMP1, 8);
3302 } else {
3303 tcg_out_vsldoi(s, out, TCG_VEC_TMP1, out, 8);
3304 }
3305 break;
3306 default:
3307 g_assert_not_reached();
3308 }
3309 return true;
4b06c216
RH
3310}
3311
3312static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
3313 unsigned vecl, unsigned vece,
5e8892db
MR
3314 const TCGArg args[TCG_MAX_OP_ARGS],
3315 const int const_args[TCG_MAX_OP_ARGS])
4b06c216 3316{
6ef14d7e 3317 static const uint32_t
64ff1c6d
RH
3318 add_op[4] = { VADDUBM, VADDUHM, VADDUWM, VADDUDM },
3319 sub_op[4] = { VSUBUBM, VSUBUHM, VSUBUWM, VSUBUDM },
73ebe95e 3320 mul_op[4] = { 0, 0, VMULUWM, VMULLD },
d7cd6a2f 3321 neg_op[4] = { 0, 0, VNEGW, VNEGD },
64ff1c6d 3322 eq_op[4] = { VCMPEQUB, VCMPEQUH, VCMPEQUW, VCMPEQUD },
d7cd6a2f 3323 ne_op[4] = { VCMPNEB, VCMPNEH, VCMPNEW, 0 },
64ff1c6d
RH
3324 gts_op[4] = { VCMPGTSB, VCMPGTSH, VCMPGTSW, VCMPGTSD },
3325 gtu_op[4] = { VCMPGTUB, VCMPGTUH, VCMPGTUW, VCMPGTUD },
e9d1a53a
RH
3326 ssadd_op[4] = { VADDSBS, VADDSHS, VADDSWS, 0 },
3327 usadd_op[4] = { VADDUBS, VADDUHS, VADDUWS, 0 },
3328 sssub_op[4] = { VSUBSBS, VSUBSHS, VSUBSWS, 0 },
3329 ussub_op[4] = { VSUBUBS, VSUBUHS, VSUBUWS, 0 },
64ff1c6d
RH
3330 umin_op[4] = { VMINUB, VMINUH, VMINUW, VMINUD },
3331 smin_op[4] = { VMINSB, VMINSH, VMINSW, VMINSD },
3332 umax_op[4] = { VMAXUB, VMAXUH, VMAXUW, VMAXUD },
3333 smax_op[4] = { VMAXSB, VMAXSH, VMAXSW, VMAXSD },
3334 shlv_op[4] = { VSLB, VSLH, VSLW, VSLD },
3335 shrv_op[4] = { VSRB, VSRH, VSRW, VSRD },
3336 sarv_op[4] = { VSRAB, VSRAH, VSRAW, VSRAD },
d9897efa
RH
3337 mrgh_op[4] = { VMRGHB, VMRGHH, VMRGHW, 0 },
3338 mrgl_op[4] = { VMRGLB, VMRGLH, VMRGLW, 0 },
64ff1c6d
RH
3339 muleu_op[4] = { VMULEUB, VMULEUH, VMULEUW, 0 },
3340 mulou_op[4] = { VMULOUB, VMULOUH, VMULOUW, 0 },
d9897efa 3341 pkum_op[4] = { VPKUHUM, VPKUWUM, 0, 0 },
64ff1c6d 3342 rotl_op[4] = { VRLB, VRLH, VRLW, VRLD };
6ef14d7e
RH
3343
3344 TCGType type = vecl + TCG_TYPE_V64;
3345 TCGArg a0 = args[0], a1 = args[1], a2 = args[2];
3346 uint32_t insn;
3347
3348 switch (opc) {
3349 case INDEX_op_ld_vec:
3350 tcg_out_ld(s, type, a0, a1, a2);
3351 return;
3352 case INDEX_op_st_vec:
3353 tcg_out_st(s, type, a0, a1, a2);
3354 return;
3355 case INDEX_op_dupm_vec:
3356 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
3357 return;
3358
d6750811
RH
3359 case INDEX_op_add_vec:
3360 insn = add_op[vece];
3361 break;
3362 case INDEX_op_sub_vec:
3363 insn = sub_op[vece];
3364 break;
d7cd6a2f
RH
3365 case INDEX_op_neg_vec:
3366 insn = neg_op[vece];
3367 a2 = a1;
3368 a1 = 0;
3369 break;
64ff1c6d 3370 case INDEX_op_mul_vec:
73ebe95e 3371 insn = mul_op[vece];
64ff1c6d 3372 break;
e9d1a53a
RH
3373 case INDEX_op_ssadd_vec:
3374 insn = ssadd_op[vece];
3375 break;
3376 case INDEX_op_sssub_vec:
3377 insn = sssub_op[vece];
3378 break;
3379 case INDEX_op_usadd_vec:
3380 insn = usadd_op[vece];
3381 break;
3382 case INDEX_op_ussub_vec:
3383 insn = ussub_op[vece];
3384 break;
e2382972
RH
3385 case INDEX_op_smin_vec:
3386 insn = smin_op[vece];
3387 break;
3388 case INDEX_op_umin_vec:
3389 insn = umin_op[vece];
3390 break;
3391 case INDEX_op_smax_vec:
3392 insn = smax_op[vece];
3393 break;
3394 case INDEX_op_umax_vec:
3395 insn = umax_op[vece];
3396 break;
dabae097
RH
3397 case INDEX_op_shlv_vec:
3398 insn = shlv_op[vece];
3399 break;
3400 case INDEX_op_shrv_vec:
3401 insn = shrv_op[vece];
3402 break;
3403 case INDEX_op_sarv_vec:
3404 insn = sarv_op[vece];
3405 break;
6ef14d7e
RH
3406 case INDEX_op_and_vec:
3407 insn = VAND;
3408 break;
3409 case INDEX_op_or_vec:
3410 insn = VOR;
3411 break;
3412 case INDEX_op_xor_vec:
3413 insn = VXOR;
3414 break;
3415 case INDEX_op_andc_vec:
3416 insn = VANDC;
3417 break;
3418 case INDEX_op_not_vec:
3419 insn = VNOR;
3420 a2 = a1;
3421 break;
64ff1c6d
RH
3422 case INDEX_op_orc_vec:
3423 insn = VORC;
3424 break;
fa8e90d6
RH
3425 case INDEX_op_nand_vec:
3426 insn = VNAND;
3427 break;
3428 case INDEX_op_nor_vec:
3429 insn = VNOR;
3430 break;
3431 case INDEX_op_eqv_vec:
3432 insn = VEQV;
3433 break;
6ef14d7e
RH
3434
3435 case INDEX_op_cmp_vec:
3436 switch (args[3]) {
3437 case TCG_COND_EQ:
3438 insn = eq_op[vece];
3439 break;
d7cd6a2f
RH
3440 case TCG_COND_NE:
3441 insn = ne_op[vece];
3442 break;
6ef14d7e
RH
3443 case TCG_COND_GT:
3444 insn = gts_op[vece];
3445 break;
3446 case TCG_COND_GTU:
3447 insn = gtu_op[vece];
3448 break;
3449 default:
3450 g_assert_not_reached();
3451 }
3452 break;
3453
47c906ae
RH
3454 case INDEX_op_bitsel_vec:
3455 tcg_out32(s, XXSEL | VRT(a0) | VRC(a1) | VRB(a2) | VRA(args[3]));
3456 return;
3457
597cf978
RH
3458 case INDEX_op_dup2_vec:
3459 assert(TCG_TARGET_REG_BITS == 32);
3460 /* With inputs a1 = xLxx, a2 = xHxx */
3461 tcg_out32(s, VMRGHW | VRT(a0) | VRA(a2) | VRB(a1)); /* a0 = xxHL */
3462 tcg_out_vsldoi(s, TCG_VEC_TMP1, a0, a0, 8); /* tmp = HLxx */
3463 tcg_out_vsldoi(s, a0, a0, TCG_VEC_TMP1, 8); /* a0 = HLHL */
3464 return;
3465
d9897efa
RH
3466 case INDEX_op_ppc_mrgh_vec:
3467 insn = mrgh_op[vece];
3468 break;
3469 case INDEX_op_ppc_mrgl_vec:
3470 insn = mrgl_op[vece];
3471 break;
3472 case INDEX_op_ppc_muleu_vec:
3473 insn = muleu_op[vece];
3474 break;
3475 case INDEX_op_ppc_mulou_vec:
3476 insn = mulou_op[vece];
3477 break;
3478 case INDEX_op_ppc_pkum_vec:
3479 insn = pkum_op[vece];
3480 break;
ab87a66f 3481 case INDEX_op_rotlv_vec:
d9897efa
RH
3482 insn = rotl_op[vece];
3483 break;
3484 case INDEX_op_ppc_msum_vec:
3485 tcg_debug_assert(vece == MO_16);
3486 tcg_out32(s, VMSUMUHM | VRT(a0) | VRA(a1) | VRB(a2) | VRC(args[3]));
3487 return;
3488
6ef14d7e 3489 case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */
6ef14d7e
RH
3490 case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */
3491 default:
3492 g_assert_not_reached();
3493 }
3494
3495 tcg_debug_assert(insn != 0);
3496 tcg_out32(s, insn | VRT(a0) | VRA(a1) | VRB(a2));
3497}
3498
dabae097
RH
3499static void expand_vec_shi(TCGType type, unsigned vece, TCGv_vec v0,
3500 TCGv_vec v1, TCGArg imm, TCGOpcode opci)
3501{
44aa59a0
RH
3502 TCGv_vec t1;
3503
3504 if (vece == MO_32) {
3505 /*
3506 * Only 5 bits are significant, and VSPLTISB can represent -16..15.
3507 * So using negative numbers gets us the 4th bit easily.
3508 */
3509 imm = sextract32(imm, 0, 5);
3510 } else {
3511 imm &= (8 << vece) - 1;
3512 }
dabae097 3513
44aa59a0
RH
3514 /* Splat w/bytes for xxspltib when 2.07 allows MO_64. */
3515 t1 = tcg_constant_vec(type, MO_8, imm);
dabae097
RH
3516 vec_gen_3(opci, type, vece, tcgv_vec_arg(v0),
3517 tcgv_vec_arg(v1), tcgv_vec_arg(t1));
dabae097
RH
3518}
3519
6ef14d7e
RH
3520static void expand_vec_cmp(TCGType type, unsigned vece, TCGv_vec v0,
3521 TCGv_vec v1, TCGv_vec v2, TCGCond cond)
3522{
3523 bool need_swap = false, need_inv = false;
3524
64ff1c6d 3525 tcg_debug_assert(vece <= MO_32 || have_isa_2_07);
6ef14d7e
RH
3526
3527 switch (cond) {
3528 case TCG_COND_EQ:
3529 case TCG_COND_GT:
3530 case TCG_COND_GTU:
3531 break;
3532 case TCG_COND_NE:
d7cd6a2f
RH
3533 if (have_isa_3_00 && vece <= MO_32) {
3534 break;
3535 }
3536 /* fall through */
6ef14d7e
RH
3537 case TCG_COND_LE:
3538 case TCG_COND_LEU:
3539 need_inv = true;
3540 break;
3541 case TCG_COND_LT:
3542 case TCG_COND_LTU:
3543 need_swap = true;
3544 break;
3545 case TCG_COND_GE:
3546 case TCG_COND_GEU:
3547 need_swap = need_inv = true;
3548 break;
3549 default:
3550 g_assert_not_reached();
3551 }
3552
3553 if (need_inv) {
3554 cond = tcg_invert_cond(cond);
3555 }
3556 if (need_swap) {
3557 TCGv_vec t1;
3558 t1 = v1, v1 = v2, v2 = t1;
3559 cond = tcg_swap_cond(cond);
3560 }
3561
3562 vec_gen_4(INDEX_op_cmp_vec, type, vece, tcgv_vec_arg(v0),
3563 tcgv_vec_arg(v1), tcgv_vec_arg(v2), cond);
3564
3565 if (need_inv) {
3566 tcg_gen_not_vec(vece, v0, v0);
3567 }
4b06c216
RH
3568}
3569
d9897efa
RH
3570static void expand_vec_mul(TCGType type, unsigned vece, TCGv_vec v0,
3571 TCGv_vec v1, TCGv_vec v2)
3572{
3573 TCGv_vec t1 = tcg_temp_new_vec(type);
3574 TCGv_vec t2 = tcg_temp_new_vec(type);
44aa59a0 3575 TCGv_vec c0, c16;
d9897efa
RH
3576
3577 switch (vece) {
3578 case MO_8:
3579 case MO_16:
3580 vec_gen_3(INDEX_op_ppc_muleu_vec, type, vece, tcgv_vec_arg(t1),
3581 tcgv_vec_arg(v1), tcgv_vec_arg(v2));
3582 vec_gen_3(INDEX_op_ppc_mulou_vec, type, vece, tcgv_vec_arg(t2),
3583 tcgv_vec_arg(v1), tcgv_vec_arg(v2));
3584 vec_gen_3(INDEX_op_ppc_mrgh_vec, type, vece + 1, tcgv_vec_arg(v0),
3585 tcgv_vec_arg(t1), tcgv_vec_arg(t2));
3586 vec_gen_3(INDEX_op_ppc_mrgl_vec, type, vece + 1, tcgv_vec_arg(t1),
3587 tcgv_vec_arg(t1), tcgv_vec_arg(t2));
3588 vec_gen_3(INDEX_op_ppc_pkum_vec, type, vece, tcgv_vec_arg(v0),
3589 tcgv_vec_arg(v0), tcgv_vec_arg(t1));
3590 break;
3591
3592 case MO_32:
64ff1c6d 3593 tcg_debug_assert(!have_isa_2_07);
44aa59a0
RH
3594 /*
3595 * Only 5 bits are significant, and VSPLTISB can represent -16..15.
3596 * So using -16 is a quick way to represent 16.
3597 */
3598 c16 = tcg_constant_vec(type, MO_8, -16);
3599 c0 = tcg_constant_vec(type, MO_8, 0);
3600
ab87a66f 3601 vec_gen_3(INDEX_op_rotlv_vec, type, MO_32, tcgv_vec_arg(t1),
44aa59a0 3602 tcgv_vec_arg(v2), tcgv_vec_arg(c16));
d9897efa
RH
3603 vec_gen_3(INDEX_op_ppc_mulou_vec, type, MO_16, tcgv_vec_arg(t2),
3604 tcgv_vec_arg(v1), tcgv_vec_arg(v2));
44aa59a0
RH
3605 vec_gen_4(INDEX_op_ppc_msum_vec, type, MO_16, tcgv_vec_arg(t1),
3606 tcgv_vec_arg(v1), tcgv_vec_arg(t1), tcgv_vec_arg(c0));
3607 vec_gen_3(INDEX_op_shlv_vec, type, MO_32, tcgv_vec_arg(t1),
3608 tcgv_vec_arg(t1), tcgv_vec_arg(c16));
3609 tcg_gen_add_vec(MO_32, v0, t1, t2);
d9897efa
RH
3610 break;
3611
3612 default:
3613 g_assert_not_reached();
3614 }
3615 tcg_temp_free_vec(t1);
3616 tcg_temp_free_vec(t2);
3617}
3618
4b06c216
RH
3619void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
3620 TCGArg a0, ...)
3621{
6ef14d7e 3622 va_list va;
ab87a66f 3623 TCGv_vec v0, v1, v2, t0;
dabae097 3624 TCGArg a2;
6ef14d7e
RH
3625
3626 va_start(va, a0);
3627 v0 = temp_tcgv_vec(arg_temp(a0));
3628 v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
dabae097 3629 a2 = va_arg(va, TCGArg);
6ef14d7e
RH
3630
3631 switch (opc) {
dabae097
RH
3632 case INDEX_op_shli_vec:
3633 expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_shlv_vec);
3634 break;
3635 case INDEX_op_shri_vec:
3636 expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_shrv_vec);
3637 break;
3638 case INDEX_op_sari_vec:
3639 expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_sarv_vec);
3640 break;
ab87a66f
RH
3641 case INDEX_op_rotli_vec:
3642 expand_vec_shi(type, vece, v0, v1, a2, INDEX_op_rotlv_vec);
3643 break;
6ef14d7e 3644 case INDEX_op_cmp_vec:
dabae097 3645 v2 = temp_tcgv_vec(arg_temp(a2));
6ef14d7e
RH
3646 expand_vec_cmp(type, vece, v0, v1, v2, va_arg(va, TCGArg));
3647 break;
d9897efa
RH
3648 case INDEX_op_mul_vec:
3649 v2 = temp_tcgv_vec(arg_temp(a2));
3650 expand_vec_mul(type, vece, v0, v1, v2);
3651 break;
ab87a66f
RH
3652 case INDEX_op_rotlv_vec:
3653 v2 = temp_tcgv_vec(arg_temp(a2));
3654 t0 = tcg_temp_new_vec(type);
3655 tcg_gen_neg_vec(vece, t0, v2);
3656 tcg_gen_rotlv_vec(vece, v0, v1, t0);
3657 tcg_temp_free_vec(t0);
3658 break;
6ef14d7e
RH
3659 default:
3660 g_assert_not_reached();
3661 }
3662 va_end(va);
4b06c216
RH
3663}
3664
6893016b
RH
3665static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
3666{
6cb3658a
RH
3667 switch (op) {
3668 case INDEX_op_goto_ptr:
6893016b 3669 return C_O0_I1(r);
796f1a68 3670
6cb3658a
RH
3671 case INDEX_op_ld8u_i32:
3672 case INDEX_op_ld8s_i32:
3673 case INDEX_op_ld16u_i32:
3674 case INDEX_op_ld16s_i32:
3675 case INDEX_op_ld_i32:
6cb3658a
RH
3676 case INDEX_op_ctpop_i32:
3677 case INDEX_op_neg_i32:
3678 case INDEX_op_not_i32:
3679 case INDEX_op_ext8s_i32:
3680 case INDEX_op_ext16s_i32:
3681 case INDEX_op_bswap16_i32:
3682 case INDEX_op_bswap32_i32:
3683 case INDEX_op_extract_i32:
3684 case INDEX_op_ld8u_i64:
3685 case INDEX_op_ld8s_i64:
3686 case INDEX_op_ld16u_i64:
3687 case INDEX_op_ld16s_i64:
3688 case INDEX_op_ld32u_i64:
3689 case INDEX_op_ld32s_i64:
3690 case INDEX_op_ld_i64:
6cb3658a
RH
3691 case INDEX_op_ctpop_i64:
3692 case INDEX_op_neg_i64:
3693 case INDEX_op_not_i64:
3694 case INDEX_op_ext8s_i64:
3695 case INDEX_op_ext16s_i64:
3696 case INDEX_op_ext32s_i64:
3697 case INDEX_op_ext_i32_i64:
3698 case INDEX_op_extu_i32_i64:
3699 case INDEX_op_bswap16_i64:
3700 case INDEX_op_bswap32_i64:
3701 case INDEX_op_bswap64_i64:
3702 case INDEX_op_extract_i64:
6893016b
RH
3703 return C_O1_I1(r, r);
3704
3705 case INDEX_op_st8_i32:
3706 case INDEX_op_st16_i32:
3707 case INDEX_op_st_i32:
3708 case INDEX_op_st8_i64:
3709 case INDEX_op_st16_i64:
3710 case INDEX_op_st32_i64:
3711 case INDEX_op_st_i64:
3712 return C_O0_I2(r, r);
abcf61c4 3713
6cb3658a
RH
3714 case INDEX_op_add_i32:
3715 case INDEX_op_and_i32:
3716 case INDEX_op_or_i32:
3717 case INDEX_op_xor_i32:
3718 case INDEX_op_andc_i32:
3719 case INDEX_op_orc_i32:
3720 case INDEX_op_eqv_i32:
3721 case INDEX_op_shl_i32:
3722 case INDEX_op_shr_i32:
3723 case INDEX_op_sar_i32:
3724 case INDEX_op_rotl_i32:
3725 case INDEX_op_rotr_i32:
3726 case INDEX_op_setcond_i32:
3727 case INDEX_op_and_i64:
3728 case INDEX_op_andc_i64:
3729 case INDEX_op_shl_i64:
3730 case INDEX_op_shr_i64:
3731 case INDEX_op_sar_i64:
3732 case INDEX_op_rotl_i64:
3733 case INDEX_op_rotr_i64:
3734 case INDEX_op_setcond_i64:
6893016b
RH
3735 return C_O1_I2(r, r, ri);
3736
6cb3658a
RH
3737 case INDEX_op_mul_i32:
3738 case INDEX_op_mul_i64:
6893016b
RH
3739 return C_O1_I2(r, r, rI);
3740
6cb3658a
RH
3741 case INDEX_op_div_i32:
3742 case INDEX_op_divu_i32:
4d573822
MKF
3743 case INDEX_op_rem_i32:
3744 case INDEX_op_remu_i32:
6cb3658a
RH
3745 case INDEX_op_nand_i32:
3746 case INDEX_op_nor_i32:
3747 case INDEX_op_muluh_i32:
3748 case INDEX_op_mulsh_i32:
3749 case INDEX_op_orc_i64:
3750 case INDEX_op_eqv_i64:
3751 case INDEX_op_nand_i64:
3752 case INDEX_op_nor_i64:
3753 case INDEX_op_div_i64:
3754 case INDEX_op_divu_i64:
4d573822
MKF
3755 case INDEX_op_rem_i64:
3756 case INDEX_op_remu_i64:
6cb3658a
RH
3757 case INDEX_op_mulsh_i64:
3758 case INDEX_op_muluh_i64:
6893016b
RH
3759 return C_O1_I2(r, r, r);
3760
6cb3658a 3761 case INDEX_op_sub_i32:
6893016b 3762 return C_O1_I2(r, rI, ri);
6cb3658a 3763 case INDEX_op_add_i64:
6893016b 3764 return C_O1_I2(r, r, rT);
6cb3658a
RH
3765 case INDEX_op_or_i64:
3766 case INDEX_op_xor_i64:
6893016b 3767 return C_O1_I2(r, r, rU);
6cb3658a 3768 case INDEX_op_sub_i64:
6893016b 3769 return C_O1_I2(r, rI, rT);
6cb3658a
RH
3770 case INDEX_op_clz_i32:
3771 case INDEX_op_ctz_i32:
3772 case INDEX_op_clz_i64:
3773 case INDEX_op_ctz_i64:
6893016b 3774 return C_O1_I2(r, r, rZW);
796f1a68 3775
6cb3658a
RH
3776 case INDEX_op_brcond_i32:
3777 case INDEX_op_brcond_i64:
6893016b 3778 return C_O0_I2(r, ri);
6c858762 3779
6cb3658a
RH
3780 case INDEX_op_movcond_i32:
3781 case INDEX_op_movcond_i64:
6893016b 3782 return C_O1_I4(r, r, ri, rZ, rZ);
6cb3658a
RH
3783 case INDEX_op_deposit_i32:
3784 case INDEX_op_deposit_i64:
6893016b 3785 return C_O1_I2(r, 0, rZ);
6cb3658a 3786 case INDEX_op_brcond2_i32:
6893016b 3787 return C_O0_I4(r, r, ri, ri);
6cb3658a 3788 case INDEX_op_setcond2_i32:
6893016b 3789 return C_O1_I4(r, r, r, ri, ri);
6cb3658a
RH
3790 case INDEX_op_add2_i64:
3791 case INDEX_op_add2_i32:
6893016b 3792 return C_O2_I4(r, r, r, r, rI, rZM);
6cb3658a
RH
3793 case INDEX_op_sub2_i64:
3794 case INDEX_op_sub2_i32:
6893016b 3795 return C_O2_I4(r, r, rI, rZM, r, r);
810260a8 3796
6cb3658a
RH
3797 case INDEX_op_qemu_ld_i32:
3798 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
6893016b
RH
3799 ? C_O1_I1(r, L)
3800 : C_O1_I2(r, L, L));
3801
6cb3658a
RH
3802 case INDEX_op_qemu_st_i32:
3803 return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
6893016b
RH
3804 ? C_O0_I2(S, S)
3805 : C_O0_I3(S, S, S));
3806
6cb3658a 3807 case INDEX_op_qemu_ld_i64:
6893016b
RH
3808 return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
3809 : TARGET_LONG_BITS == 32 ? C_O2_I1(L, L, L)
3810 : C_O2_I2(L, L, L, L));
3811
6cb3658a 3812 case INDEX_op_qemu_st_i64:
6893016b
RH
3813 return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(S, S)
3814 : TARGET_LONG_BITS == 32 ? C_O0_I3(S, S, S)
3815 : C_O0_I4(S, S, S, S));
f69d277e 3816
d6750811
RH
3817 case INDEX_op_add_vec:
3818 case INDEX_op_sub_vec:
d9897efa 3819 case INDEX_op_mul_vec:
6ef14d7e
RH
3820 case INDEX_op_and_vec:
3821 case INDEX_op_or_vec:
3822 case INDEX_op_xor_vec:
3823 case INDEX_op_andc_vec:
3824 case INDEX_op_orc_vec:
fa8e90d6
RH
3825 case INDEX_op_nor_vec:
3826 case INDEX_op_eqv_vec:
3827 case INDEX_op_nand_vec:
6ef14d7e 3828 case INDEX_op_cmp_vec:
e9d1a53a
RH
3829 case INDEX_op_ssadd_vec:
3830 case INDEX_op_sssub_vec:
3831 case INDEX_op_usadd_vec:
3832 case INDEX_op_ussub_vec:
e2382972
RH
3833 case INDEX_op_smax_vec:
3834 case INDEX_op_smin_vec:
3835 case INDEX_op_umax_vec:
3836 case INDEX_op_umin_vec:
dabae097
RH
3837 case INDEX_op_shlv_vec:
3838 case INDEX_op_shrv_vec:
3839 case INDEX_op_sarv_vec:
ab87a66f
RH
3840 case INDEX_op_rotlv_vec:
3841 case INDEX_op_rotrv_vec:
d9897efa
RH
3842 case INDEX_op_ppc_mrgh_vec:
3843 case INDEX_op_ppc_mrgl_vec:
3844 case INDEX_op_ppc_muleu_vec:
3845 case INDEX_op_ppc_mulou_vec:
3846 case INDEX_op_ppc_pkum_vec:
597cf978 3847 case INDEX_op_dup2_vec:
6893016b
RH
3848 return C_O1_I2(v, v, v);
3849
6ef14d7e 3850 case INDEX_op_not_vec:
d7cd6a2f 3851 case INDEX_op_neg_vec:
6893016b
RH
3852 return C_O1_I1(v, v);
3853
b7ce3cff 3854 case INDEX_op_dup_vec:
6893016b
RH
3855 return have_isa_3_00 ? C_O1_I1(v, vr) : C_O1_I1(v, v);
3856
6ef14d7e 3857 case INDEX_op_ld_vec:
6ef14d7e 3858 case INDEX_op_dupm_vec:
6893016b
RH
3859 return C_O1_I1(v, r);
3860
3861 case INDEX_op_st_vec:
3862 return C_O0_I2(v, r);
3863
47c906ae 3864 case INDEX_op_bitsel_vec:
d9897efa 3865 case INDEX_op_ppc_msum_vec:
6893016b 3866 return C_O1_I3(v, v, v, v);
6ef14d7e 3867
6cb3658a 3868 default:
6893016b 3869 g_assert_not_reached();
f69d277e 3870 }
f69d277e
RH
3871}
3872
541dd4ce 3873static void tcg_target_init(TCGContext *s)
810260a8 3874{
cd629de1 3875 unsigned long hwcap = qemu_getauxval(AT_HWCAP);
d0b07481
RH
3876 unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
3877
7d9dae0a 3878 have_isa = tcg_isa_base;
1e6e9aca 3879 if (hwcap & PPC_FEATURE_ARCH_2_06) {
7d9dae0a 3880 have_isa = tcg_isa_2_06;
1e6e9aca 3881 }
64ff1c6d
RH
3882#ifdef PPC_FEATURE2_ARCH_2_07
3883 if (hwcap2 & PPC_FEATURE2_ARCH_2_07) {
3884 have_isa = tcg_isa_2_07;
3885 }
3886#endif
d0b07481
RH
3887#ifdef PPC_FEATURE2_ARCH_3_00
3888 if (hwcap2 & PPC_FEATURE2_ARCH_3_00) {
7d9dae0a 3889 have_isa = tcg_isa_3_00;
d0b07481
RH
3890 }
3891#endif
73ebe95e
LP
3892#ifdef PPC_FEATURE2_ARCH_3_10
3893 if (hwcap2 & PPC_FEATURE2_ARCH_3_10) {
3894 have_isa = tcg_isa_3_10;
3895 }
3896#endif
1e6e9aca 3897
63922f46
RH
3898#ifdef PPC_FEATURE2_HAS_ISEL
3899 /* Prefer explicit instruction from the kernel. */
3900 have_isel = (hwcap2 & PPC_FEATURE2_HAS_ISEL) != 0;
3901#else
3902 /* Fall back to knowing Power7 (2.06) has ISEL. */
3903 have_isel = have_isa_2_06;
3904#endif
3905
68f340d4
RH
3906 if (hwcap & PPC_FEATURE_HAS_ALTIVEC) {
3907 have_altivec = true;
47c906ae
RH
3908 /* We only care about the portion of VSX that overlaps Altivec. */
3909 if (hwcap & PPC_FEATURE_HAS_VSX) {
3910 have_vsx = true;
3911 }
68f340d4
RH
3912 }
3913
f46934df
RH
3914 tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
3915 tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
4b06c216
RH
3916 if (have_altivec) {
3917 tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
3918 tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
3919 }
f46934df
RH
3920
3921 tcg_target_call_clobber_regs = 0;
3922 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
3923 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R2);
3924 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R3);
3925 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R4);
3926 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R5);
3927 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R6);
3928 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R7);
3929 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
3930 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
3931 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
3932 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
3933 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R12);
810260a8 3934
42281ec6
RH
3935 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
3936 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
3937 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V2);
3938 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V3);
3939 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V4);
3940 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V5);
3941 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V6);
3942 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V7);
3943 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V8);
3944 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V9);
3945 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V10);
3946 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V11);
3947 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V12);
3948 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V13);
3949 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V14);
3950 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V15);
3951 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V16);
3952 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V17);
3953 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V18);
3954 tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V19);
3955
ccb1bb66 3956 s->reserved_regs = 0;
5e1702b0
RH
3957 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* tcg temp */
3958 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* stack pointer */
dfca1778
RH
3959#if defined(_CALL_SYSV)
3960 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* toc pointer */
5d7ff5bb 3961#endif
dfca1778 3962#if defined(_CALL_SYSV) || TCG_TARGET_REG_BITS == 64
5e1702b0 3963 tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
dfca1778
RH
3964#endif
3965 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1); /* mem temp */
42281ec6
RH
3966 tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP1);
3967 tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP2);
5964fca8
RH
3968 if (USE_REG_TB) {
3969 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); /* tb->tc_ptr */
a84ac4cb 3970 }
810260a8 3971}
fa94c3be 3972
ffcfbece 3973#ifdef __ELF__
fa94c3be
RH
3974typedef struct {
3975 DebugFrameCIE cie;
3976 DebugFrameFDEHeader fde;
3977 uint8_t fde_def_cfa[4];
3978 uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2 + 3];
3979} DebugFrame;
3980
3981/* We're expecting a 2 byte uleb128 encoded value. */
3982QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
3983
ffcfbece
RH
3984#if TCG_TARGET_REG_BITS == 64
3985# define ELF_HOST_MACHINE EM_PPC64
3986#else
3987# define ELF_HOST_MACHINE EM_PPC
3988#endif
fa94c3be
RH
3989
3990static DebugFrame debug_frame = {
3991 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
3992 .cie.id = -1,
3993 .cie.version = 1,
3994 .cie.code_align = 1,
802ca56e 3995 .cie.data_align = (-SZR & 0x7f), /* sleb128 -SZR */
fa94c3be
RH
3996 .cie.return_column = 65,
3997
3998 /* Total FDE size does not include the "len" member. */
3999 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
4000
4001 .fde_def_cfa = {
802ca56e 4002 12, TCG_REG_R1, /* DW_CFA_def_cfa r1, ... */
fa94c3be
RH
4003 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
4004 (FRAME_SIZE >> 7)
4005 },
4006 .fde_reg_ofs = {
802ca56e
RH
4007 /* DW_CFA_offset_extended_sf, lr, LR_OFFSET */
4008 0x11, 65, (LR_OFFSET / -SZR) & 0x7f,
fa94c3be
RH
4009 }
4010};
4011
755bf9e5 4012void tcg_register_jit(const void *buf, size_t buf_size)
fa94c3be
RH
4013{
4014 uint8_t *p = &debug_frame.fde_reg_ofs[3];
4015 int i;
4016
4017 for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); ++i, p += 2) {
4018 p[0] = 0x80 + tcg_target_callee_save_regs[i];
802ca56e 4019 p[1] = (FRAME_SIZE - (REG_SAVE_BOT + i * SZR)) / SZR;
fa94c3be
RH
4020 }
4021
802ca56e 4022 debug_frame.fde.func_start = (uintptr_t)buf;
fa94c3be
RH
4023 debug_frame.fde.func_len = buf_size;
4024
4025 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
4026}
ffcfbece 4027#endif /* __ELF__ */
80eca687
LMC
4028#undef VMULEUB
4029#undef VMULEUH
4030#undef VMULEUW
4031#undef VMULOUB
4032#undef VMULOUH
4033#undef VMULOUW
89a5a1ae 4034#undef VMSUMUHM