xref: /openbmc/qemu/tcg/mips/tcg-target.c.inc (revision 03e4bc0bc02779fdf6f8e8d83197f05e70881abf)
1139c1837SPaolo Bonzini/*
2139c1837SPaolo Bonzini * Tiny Code Generator for QEMU
3139c1837SPaolo Bonzini *
4139c1837SPaolo Bonzini * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
5139c1837SPaolo Bonzini * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
6139c1837SPaolo Bonzini * Based on i386/tcg-target.c - Copyright (c) 2008 Fabrice Bellard
7139c1837SPaolo Bonzini *
8139c1837SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
9139c1837SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
10139c1837SPaolo Bonzini * in the Software without restriction, including without limitation the rights
11139c1837SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12139c1837SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
13139c1837SPaolo Bonzini * furnished to do so, subject to the following conditions:
14139c1837SPaolo Bonzini *
15139c1837SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
16139c1837SPaolo Bonzini * all copies or substantial portions of the Software.
17139c1837SPaolo Bonzini *
18139c1837SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19139c1837SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21139c1837SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22139c1837SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23139c1837SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24139c1837SPaolo Bonzini * THE SOFTWARE.
25139c1837SPaolo Bonzini */
26139c1837SPaolo Bonzini
2723a79c11SRichard Henderson#include "../tcg-ldst.c.inc"
2848c12ba7SRichard Henderson#include "../tcg-pool.c.inc"
2923a79c11SRichard Henderson
30139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 32
31b56d5a8aSRichard Henderson# define LO_OFF  (HOST_BIG_ENDIAN * 4)
32139c1837SPaolo Bonzini# define HI_OFF  (4 - LO_OFF)
33139c1837SPaolo Bonzini#else
34c64ed451SRichard Henderson/* Assert at compile-time that these values are never used for 64-bit. */
35c64ed451SRichard Henderson# define LO_OFF  ({ qemu_build_not_reached(); 0; })
36c64ed451SRichard Henderson# define HI_OFF  ({ qemu_build_not_reached(); 0; })
37139c1837SPaolo Bonzini#endif
38139c1837SPaolo Bonzini
39139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG
40139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
41139c1837SPaolo Bonzini    "zero",
42139c1837SPaolo Bonzini    "at",
43139c1837SPaolo Bonzini    "v0",
44139c1837SPaolo Bonzini    "v1",
45139c1837SPaolo Bonzini    "a0",
46139c1837SPaolo Bonzini    "a1",
47139c1837SPaolo Bonzini    "a2",
48139c1837SPaolo Bonzini    "a3",
49139c1837SPaolo Bonzini    "t0",
50139c1837SPaolo Bonzini    "t1",
51139c1837SPaolo Bonzini    "t2",
52139c1837SPaolo Bonzini    "t3",
53139c1837SPaolo Bonzini    "t4",
54139c1837SPaolo Bonzini    "t5",
55139c1837SPaolo Bonzini    "t6",
56139c1837SPaolo Bonzini    "t7",
57139c1837SPaolo Bonzini    "s0",
58139c1837SPaolo Bonzini    "s1",
59139c1837SPaolo Bonzini    "s2",
60139c1837SPaolo Bonzini    "s3",
61139c1837SPaolo Bonzini    "s4",
62139c1837SPaolo Bonzini    "s5",
63139c1837SPaolo Bonzini    "s6",
64139c1837SPaolo Bonzini    "s7",
65139c1837SPaolo Bonzini    "t8",
66139c1837SPaolo Bonzini    "t9",
67139c1837SPaolo Bonzini    "k0",
68139c1837SPaolo Bonzini    "k1",
69139c1837SPaolo Bonzini    "gp",
70139c1837SPaolo Bonzini    "sp",
71139c1837SPaolo Bonzini    "s8",
72139c1837SPaolo Bonzini    "ra",
73139c1837SPaolo Bonzini};
74139c1837SPaolo Bonzini#endif
75139c1837SPaolo Bonzini
76139c1837SPaolo Bonzini#define TCG_TMP0  TCG_REG_AT
77139c1837SPaolo Bonzini#define TCG_TMP1  TCG_REG_T9
78139c1837SPaolo Bonzini#define TCG_TMP2  TCG_REG_T8
79139c1837SPaolo Bonzini#define TCG_TMP3  TCG_REG_T7
80139c1837SPaolo Bonzini
8143b4cd97SRichard Henderson#define TCG_GUEST_BASE_REG TCG_REG_S7
8253c4fa27SRichard Henderson#if TCG_TARGET_REG_BITS == 64
8353c4fa27SRichard Henderson#define TCG_REG_TB         TCG_REG_S6
8453c4fa27SRichard Henderson#else
85e3a650cdSRichard Henderson#define TCG_REG_TB         ({ qemu_build_not_reached(); TCG_REG_ZERO; })
8653c4fa27SRichard Henderson#endif
87139c1837SPaolo Bonzini
88139c1837SPaolo Bonzini/* check if we really need so many registers :P */
89139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = {
90139c1837SPaolo Bonzini    /* Call saved registers.  */
91139c1837SPaolo Bonzini    TCG_REG_S0,
92139c1837SPaolo Bonzini    TCG_REG_S1,
93139c1837SPaolo Bonzini    TCG_REG_S2,
94139c1837SPaolo Bonzini    TCG_REG_S3,
95139c1837SPaolo Bonzini    TCG_REG_S4,
96139c1837SPaolo Bonzini    TCG_REG_S5,
97139c1837SPaolo Bonzini    TCG_REG_S6,
98139c1837SPaolo Bonzini    TCG_REG_S7,
99139c1837SPaolo Bonzini    TCG_REG_S8,
100139c1837SPaolo Bonzini
101139c1837SPaolo Bonzini    /* Call clobbered registers.  */
102139c1837SPaolo Bonzini    TCG_REG_T4,
103139c1837SPaolo Bonzini    TCG_REG_T5,
104139c1837SPaolo Bonzini    TCG_REG_T6,
105139c1837SPaolo Bonzini    TCG_REG_T7,
106139c1837SPaolo Bonzini    TCG_REG_T8,
107139c1837SPaolo Bonzini    TCG_REG_T9,
108139c1837SPaolo Bonzini    TCG_REG_V1,
109139c1837SPaolo Bonzini    TCG_REG_V0,
110139c1837SPaolo Bonzini
111139c1837SPaolo Bonzini    /* Argument registers, opposite order of allocation.  */
112139c1837SPaolo Bonzini    TCG_REG_T3,
113139c1837SPaolo Bonzini    TCG_REG_T2,
114139c1837SPaolo Bonzini    TCG_REG_T1,
115139c1837SPaolo Bonzini    TCG_REG_T0,
116139c1837SPaolo Bonzini    TCG_REG_A3,
117139c1837SPaolo Bonzini    TCG_REG_A2,
118139c1837SPaolo Bonzini    TCG_REG_A1,
119139c1837SPaolo Bonzini    TCG_REG_A0,
120139c1837SPaolo Bonzini};
121139c1837SPaolo Bonzini
122139c1837SPaolo Bonzinistatic const TCGReg tcg_target_call_iarg_regs[] = {
123139c1837SPaolo Bonzini    TCG_REG_A0,
124139c1837SPaolo Bonzini    TCG_REG_A1,
125139c1837SPaolo Bonzini    TCG_REG_A2,
126139c1837SPaolo Bonzini    TCG_REG_A3,
127139c1837SPaolo Bonzini#if _MIPS_SIM == _ABIN32 || _MIPS_SIM == _ABI64
128139c1837SPaolo Bonzini    TCG_REG_T0,
129139c1837SPaolo Bonzini    TCG_REG_T1,
130139c1837SPaolo Bonzini    TCG_REG_T2,
131139c1837SPaolo Bonzini    TCG_REG_T3,
132139c1837SPaolo Bonzini#endif
133139c1837SPaolo Bonzini};
134139c1837SPaolo Bonzini
1355e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
1365e3d0c19SRichard Henderson{
1375e3d0c19SRichard Henderson    tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
1385e3d0c19SRichard Henderson    tcg_debug_assert(slot >= 0 && slot <= 1);
1395e3d0c19SRichard Henderson    return TCG_REG_V0 + slot;
1405e3d0c19SRichard Henderson}
141139c1837SPaolo Bonzini
142df5af130SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
143df5af130SRichard Hendersonstatic const tcg_insn_unit *bswap32_addr;
144df5af130SRichard Hendersonstatic const tcg_insn_unit *bswap32u_addr;
145df5af130SRichard Hendersonstatic const tcg_insn_unit *bswap64_addr;
146139c1837SPaolo Bonzini
147df5af130SRichard Hendersonstatic bool reloc_pc16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
148139c1837SPaolo Bonzini{
149139c1837SPaolo Bonzini    /* Let the compiler perform the right-shift as part of the arithmetic.  */
150df5af130SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
151df5af130SRichard Henderson    ptrdiff_t disp = target - (src_rx + 1);
15291a7fd1fSRichard Henderson    if (disp == (int16_t)disp) {
153df5af130SRichard Henderson        *src_rw = deposit32(*src_rw, 0, 16, disp);
15491a7fd1fSRichard Henderson        return true;
155139c1837SPaolo Bonzini    }
15691a7fd1fSRichard Henderson    return false;
157139c1837SPaolo Bonzini}
158139c1837SPaolo Bonzini
159139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
160139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
161139c1837SPaolo Bonzini{
16248c12ba7SRichard Henderson    value += addend;
16348c12ba7SRichard Henderson    switch (type) {
16448c12ba7SRichard Henderson    case R_MIPS_PC16:
16591a7fd1fSRichard Henderson        return reloc_pc16(code_ptr, (const tcg_insn_unit *)value);
16648c12ba7SRichard Henderson    case R_MIPS_16:
16748c12ba7SRichard Henderson        if (value != (int16_t)value) {
16848c12ba7SRichard Henderson            return false;
16948c12ba7SRichard Henderson        }
17048c12ba7SRichard Henderson        *code_ptr = deposit32(*code_ptr, 0, 16, value);
17148c12ba7SRichard Henderson        return true;
17248c12ba7SRichard Henderson    }
17348c12ba7SRichard Henderson    g_assert_not_reached();
174139c1837SPaolo Bonzini}
175139c1837SPaolo Bonzini
176139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO 0x100
177139c1837SPaolo Bonzini#define TCG_CT_CONST_U16  0x200    /* Unsigned 16-bit: 0 - 0xffff.  */
178139c1837SPaolo Bonzini#define TCG_CT_CONST_S16  0x400    /* Signed 16-bit: -32768 - 32767 */
179139c1837SPaolo Bonzini#define TCG_CT_CONST_P2M1 0x800    /* Power of 2 minus 1.  */
180139c1837SPaolo Bonzini#define TCG_CT_CONST_N16  0x1000   /* "Negatable" 16-bit: -32767 - 32767 */
181139c1837SPaolo Bonzini#define TCG_CT_CONST_WSZ  0x2000   /* word size */
182139c1837SPaolo Bonzini
18351800e43SRichard Henderson#define ALL_GENERAL_REGS  0xffffffffu
18451800e43SRichard Henderson
18510d4af58SRichard Hendersonstatic bool is_p2m1(tcg_target_long val)
186139c1837SPaolo Bonzini{
187139c1837SPaolo Bonzini    return val && ((val + 1) & val) == 0;
188139c1837SPaolo Bonzini}
189139c1837SPaolo Bonzini
190139c1837SPaolo Bonzini/* test if a constant matches the constraint */
191*21e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct,
192*21e9a8aeSRichard Henderson                                   TCGType type, TCGCond cond, int vece)
193139c1837SPaolo Bonzini{
194139c1837SPaolo Bonzini    if (ct & TCG_CT_CONST) {
195139c1837SPaolo Bonzini        return 1;
196139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
197139c1837SPaolo Bonzini        return 1;
198139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_U16) && val == (uint16_t)val) {
199139c1837SPaolo Bonzini        return 1;
200139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_S16) && val == (int16_t)val) {
201139c1837SPaolo Bonzini        return 1;
202139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_N16) && val >= -32767 && val <= 32767) {
203139c1837SPaolo Bonzini        return 1;
204139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_P2M1)
205139c1837SPaolo Bonzini               && use_mips32r2_instructions && is_p2m1(val)) {
206139c1837SPaolo Bonzini        return 1;
207139c1837SPaolo Bonzini    } else if ((ct & TCG_CT_CONST_WSZ)
208139c1837SPaolo Bonzini               && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
209139c1837SPaolo Bonzini        return 1;
210139c1837SPaolo Bonzini    }
211139c1837SPaolo Bonzini    return 0;
212139c1837SPaolo Bonzini}
213139c1837SPaolo Bonzini
214139c1837SPaolo Bonzini/* instruction opcodes */
215139c1837SPaolo Bonzinitypedef enum {
216139c1837SPaolo Bonzini    OPC_J        = 002 << 26,
217139c1837SPaolo Bonzini    OPC_JAL      = 003 << 26,
218139c1837SPaolo Bonzini    OPC_BEQ      = 004 << 26,
219139c1837SPaolo Bonzini    OPC_BNE      = 005 << 26,
220139c1837SPaolo Bonzini    OPC_BLEZ     = 006 << 26,
221139c1837SPaolo Bonzini    OPC_BGTZ     = 007 << 26,
222139c1837SPaolo Bonzini    OPC_ADDIU    = 011 << 26,
223139c1837SPaolo Bonzini    OPC_SLTI     = 012 << 26,
224139c1837SPaolo Bonzini    OPC_SLTIU    = 013 << 26,
225139c1837SPaolo Bonzini    OPC_ANDI     = 014 << 26,
226139c1837SPaolo Bonzini    OPC_ORI      = 015 << 26,
227139c1837SPaolo Bonzini    OPC_XORI     = 016 << 26,
228139c1837SPaolo Bonzini    OPC_LUI      = 017 << 26,
22923a79c11SRichard Henderson    OPC_BNEL     = 025 << 26,
23023a79c11SRichard Henderson    OPC_BNEZALC_R6 = 030 << 26,
231139c1837SPaolo Bonzini    OPC_DADDIU   = 031 << 26,
23223a79c11SRichard Henderson    OPC_LDL      = 032 << 26,
23323a79c11SRichard Henderson    OPC_LDR      = 033 << 26,
234139c1837SPaolo Bonzini    OPC_LB       = 040 << 26,
235139c1837SPaolo Bonzini    OPC_LH       = 041 << 26,
23623a79c11SRichard Henderson    OPC_LWL      = 042 << 26,
237139c1837SPaolo Bonzini    OPC_LW       = 043 << 26,
238139c1837SPaolo Bonzini    OPC_LBU      = 044 << 26,
239139c1837SPaolo Bonzini    OPC_LHU      = 045 << 26,
24023a79c11SRichard Henderson    OPC_LWR      = 046 << 26,
241139c1837SPaolo Bonzini    OPC_LWU      = 047 << 26,
242139c1837SPaolo Bonzini    OPC_SB       = 050 << 26,
243139c1837SPaolo Bonzini    OPC_SH       = 051 << 26,
24423a79c11SRichard Henderson    OPC_SWL      = 052 << 26,
245139c1837SPaolo Bonzini    OPC_SW       = 053 << 26,
24623a79c11SRichard Henderson    OPC_SDL      = 054 << 26,
24723a79c11SRichard Henderson    OPC_SDR      = 055 << 26,
24823a79c11SRichard Henderson    OPC_SWR      = 056 << 26,
249139c1837SPaolo Bonzini    OPC_LD       = 067 << 26,
250139c1837SPaolo Bonzini    OPC_SD       = 077 << 26,
251139c1837SPaolo Bonzini
252139c1837SPaolo Bonzini    OPC_SPECIAL  = 000 << 26,
253139c1837SPaolo Bonzini    OPC_SLL      = OPC_SPECIAL | 000,
254139c1837SPaolo Bonzini    OPC_SRL      = OPC_SPECIAL | 002,
255139c1837SPaolo Bonzini    OPC_ROTR     = OPC_SPECIAL | 002 | (1 << 21),
256139c1837SPaolo Bonzini    OPC_SRA      = OPC_SPECIAL | 003,
257139c1837SPaolo Bonzini    OPC_SLLV     = OPC_SPECIAL | 004,
258139c1837SPaolo Bonzini    OPC_SRLV     = OPC_SPECIAL | 006,
259139c1837SPaolo Bonzini    OPC_ROTRV    = OPC_SPECIAL | 006 | 0100,
260139c1837SPaolo Bonzini    OPC_SRAV     = OPC_SPECIAL | 007,
261139c1837SPaolo Bonzini    OPC_JR_R5    = OPC_SPECIAL | 010,
262139c1837SPaolo Bonzini    OPC_JALR     = OPC_SPECIAL | 011,
263139c1837SPaolo Bonzini    OPC_MOVZ     = OPC_SPECIAL | 012,
264139c1837SPaolo Bonzini    OPC_MOVN     = OPC_SPECIAL | 013,
265139c1837SPaolo Bonzini    OPC_SYNC     = OPC_SPECIAL | 017,
266139c1837SPaolo Bonzini    OPC_MFHI     = OPC_SPECIAL | 020,
267139c1837SPaolo Bonzini    OPC_MFLO     = OPC_SPECIAL | 022,
268139c1837SPaolo Bonzini    OPC_DSLLV    = OPC_SPECIAL | 024,
269139c1837SPaolo Bonzini    OPC_DSRLV    = OPC_SPECIAL | 026,
270139c1837SPaolo Bonzini    OPC_DROTRV   = OPC_SPECIAL | 026 | 0100,
271139c1837SPaolo Bonzini    OPC_DSRAV    = OPC_SPECIAL | 027,
272139c1837SPaolo Bonzini    OPC_MULT     = OPC_SPECIAL | 030,
273139c1837SPaolo Bonzini    OPC_MUL_R6   = OPC_SPECIAL | 030 | 0200,
274139c1837SPaolo Bonzini    OPC_MUH      = OPC_SPECIAL | 030 | 0300,
275139c1837SPaolo Bonzini    OPC_MULTU    = OPC_SPECIAL | 031,
276139c1837SPaolo Bonzini    OPC_MULU     = OPC_SPECIAL | 031 | 0200,
277139c1837SPaolo Bonzini    OPC_MUHU     = OPC_SPECIAL | 031 | 0300,
278139c1837SPaolo Bonzini    OPC_DIV      = OPC_SPECIAL | 032,
279139c1837SPaolo Bonzini    OPC_DIV_R6   = OPC_SPECIAL | 032 | 0200,
280139c1837SPaolo Bonzini    OPC_MOD      = OPC_SPECIAL | 032 | 0300,
281139c1837SPaolo Bonzini    OPC_DIVU     = OPC_SPECIAL | 033,
282139c1837SPaolo Bonzini    OPC_DIVU_R6  = OPC_SPECIAL | 033 | 0200,
283139c1837SPaolo Bonzini    OPC_MODU     = OPC_SPECIAL | 033 | 0300,
284139c1837SPaolo Bonzini    OPC_DMULT    = OPC_SPECIAL | 034,
285139c1837SPaolo Bonzini    OPC_DMUL     = OPC_SPECIAL | 034 | 0200,
286139c1837SPaolo Bonzini    OPC_DMUH     = OPC_SPECIAL | 034 | 0300,
287139c1837SPaolo Bonzini    OPC_DMULTU   = OPC_SPECIAL | 035,
288139c1837SPaolo Bonzini    OPC_DMULU    = OPC_SPECIAL | 035 | 0200,
289139c1837SPaolo Bonzini    OPC_DMUHU    = OPC_SPECIAL | 035 | 0300,
290139c1837SPaolo Bonzini    OPC_DDIV     = OPC_SPECIAL | 036,
291139c1837SPaolo Bonzini    OPC_DDIV_R6  = OPC_SPECIAL | 036 | 0200,
292139c1837SPaolo Bonzini    OPC_DMOD     = OPC_SPECIAL | 036 | 0300,
293139c1837SPaolo Bonzini    OPC_DDIVU    = OPC_SPECIAL | 037,
294139c1837SPaolo Bonzini    OPC_DDIVU_R6 = OPC_SPECIAL | 037 | 0200,
295139c1837SPaolo Bonzini    OPC_DMODU    = OPC_SPECIAL | 037 | 0300,
296139c1837SPaolo Bonzini    OPC_ADDU     = OPC_SPECIAL | 041,
297139c1837SPaolo Bonzini    OPC_SUBU     = OPC_SPECIAL | 043,
298139c1837SPaolo Bonzini    OPC_AND      = OPC_SPECIAL | 044,
299139c1837SPaolo Bonzini    OPC_OR       = OPC_SPECIAL | 045,
300139c1837SPaolo Bonzini    OPC_XOR      = OPC_SPECIAL | 046,
301139c1837SPaolo Bonzini    OPC_NOR      = OPC_SPECIAL | 047,
302139c1837SPaolo Bonzini    OPC_SLT      = OPC_SPECIAL | 052,
303139c1837SPaolo Bonzini    OPC_SLTU     = OPC_SPECIAL | 053,
304139c1837SPaolo Bonzini    OPC_DADDU    = OPC_SPECIAL | 055,
305139c1837SPaolo Bonzini    OPC_DSUBU    = OPC_SPECIAL | 057,
306139c1837SPaolo Bonzini    OPC_SELEQZ   = OPC_SPECIAL | 065,
307139c1837SPaolo Bonzini    OPC_SELNEZ   = OPC_SPECIAL | 067,
308139c1837SPaolo Bonzini    OPC_DSLL     = OPC_SPECIAL | 070,
309139c1837SPaolo Bonzini    OPC_DSRL     = OPC_SPECIAL | 072,
310139c1837SPaolo Bonzini    OPC_DROTR    = OPC_SPECIAL | 072 | (1 << 21),
311139c1837SPaolo Bonzini    OPC_DSRA     = OPC_SPECIAL | 073,
312139c1837SPaolo Bonzini    OPC_DSLL32   = OPC_SPECIAL | 074,
313139c1837SPaolo Bonzini    OPC_DSRL32   = OPC_SPECIAL | 076,
314139c1837SPaolo Bonzini    OPC_DROTR32  = OPC_SPECIAL | 076 | (1 << 21),
315139c1837SPaolo Bonzini    OPC_DSRA32   = OPC_SPECIAL | 077,
316139c1837SPaolo Bonzini    OPC_CLZ_R6   = OPC_SPECIAL | 0120,
317139c1837SPaolo Bonzini    OPC_DCLZ_R6  = OPC_SPECIAL | 0122,
318139c1837SPaolo Bonzini
319139c1837SPaolo Bonzini    OPC_REGIMM   = 001 << 26,
320139c1837SPaolo Bonzini    OPC_BLTZ     = OPC_REGIMM | (000 << 16),
321139c1837SPaolo Bonzini    OPC_BGEZ     = OPC_REGIMM | (001 << 16),
322139c1837SPaolo Bonzini
323139c1837SPaolo Bonzini    OPC_SPECIAL2 = 034 << 26,
324139c1837SPaolo Bonzini    OPC_MUL_R5   = OPC_SPECIAL2 | 002,
325139c1837SPaolo Bonzini    OPC_CLZ      = OPC_SPECIAL2 | 040,
326139c1837SPaolo Bonzini    OPC_DCLZ     = OPC_SPECIAL2 | 044,
327139c1837SPaolo Bonzini
328139c1837SPaolo Bonzini    OPC_SPECIAL3 = 037 << 26,
329139c1837SPaolo Bonzini    OPC_EXT      = OPC_SPECIAL3 | 000,
330139c1837SPaolo Bonzini    OPC_DEXTM    = OPC_SPECIAL3 | 001,
331139c1837SPaolo Bonzini    OPC_DEXTU    = OPC_SPECIAL3 | 002,
332139c1837SPaolo Bonzini    OPC_DEXT     = OPC_SPECIAL3 | 003,
333139c1837SPaolo Bonzini    OPC_INS      = OPC_SPECIAL3 | 004,
334139c1837SPaolo Bonzini    OPC_DINSM    = OPC_SPECIAL3 | 005,
335139c1837SPaolo Bonzini    OPC_DINSU    = OPC_SPECIAL3 | 006,
336139c1837SPaolo Bonzini    OPC_DINS     = OPC_SPECIAL3 | 007,
337139c1837SPaolo Bonzini    OPC_WSBH     = OPC_SPECIAL3 | 00240,
338139c1837SPaolo Bonzini    OPC_DSBH     = OPC_SPECIAL3 | 00244,
339139c1837SPaolo Bonzini    OPC_DSHD     = OPC_SPECIAL3 | 00544,
340139c1837SPaolo Bonzini    OPC_SEB      = OPC_SPECIAL3 | 02040,
341139c1837SPaolo Bonzini    OPC_SEH      = OPC_SPECIAL3 | 03040,
342139c1837SPaolo Bonzini
343139c1837SPaolo Bonzini    /* MIPS r6 doesn't have JR, JALR should be used instead */
344139c1837SPaolo Bonzini    OPC_JR       = use_mips32r6_instructions ? OPC_JALR : OPC_JR_R5,
345139c1837SPaolo Bonzini
346139c1837SPaolo Bonzini    /*
347139c1837SPaolo Bonzini     * MIPS r6 replaces MUL with an alternative encoding which is
348139c1837SPaolo Bonzini     * backwards-compatible at the assembly level.
349139c1837SPaolo Bonzini     */
350139c1837SPaolo Bonzini    OPC_MUL      = use_mips32r6_instructions ? OPC_MUL_R6 : OPC_MUL_R5,
351139c1837SPaolo Bonzini
352139c1837SPaolo Bonzini    /* MIPS r6 introduced names for weaker variants of SYNC.  These are
353139c1837SPaolo Bonzini       backward compatible to previous architecture revisions.  */
354139c1837SPaolo Bonzini    OPC_SYNC_WMB     = OPC_SYNC | 0x04 << 6,
355139c1837SPaolo Bonzini    OPC_SYNC_MB      = OPC_SYNC | 0x10 << 6,
356139c1837SPaolo Bonzini    OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 6,
357139c1837SPaolo Bonzini    OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 6,
358139c1837SPaolo Bonzini    OPC_SYNC_RMB     = OPC_SYNC | 0x13 << 6,
359139c1837SPaolo Bonzini
360139c1837SPaolo Bonzini    /* Aliases for convenience.  */
361139c1837SPaolo Bonzini    ALIAS_PADD     = sizeof(void *) == 4 ? OPC_ADDU : OPC_DADDU,
362139c1837SPaolo Bonzini    ALIAS_PADDI    = sizeof(void *) == 4 ? OPC_ADDIU : OPC_DADDIU,
363139c1837SPaolo Bonzini} MIPSInsn;
364139c1837SPaolo Bonzini
365139c1837SPaolo Bonzini/*
366139c1837SPaolo Bonzini * Type reg
367139c1837SPaolo Bonzini */
36810d4af58SRichard Hendersonstatic void tcg_out_opc_reg(TCGContext *s, MIPSInsn opc,
369139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs, TCGReg rt)
370139c1837SPaolo Bonzini{
371139c1837SPaolo Bonzini    int32_t inst;
372139c1837SPaolo Bonzini
373139c1837SPaolo Bonzini    inst = opc;
374139c1837SPaolo Bonzini    inst |= (rs & 0x1F) << 21;
375139c1837SPaolo Bonzini    inst |= (rt & 0x1F) << 16;
376139c1837SPaolo Bonzini    inst |= (rd & 0x1F) << 11;
377139c1837SPaolo Bonzini    tcg_out32(s, inst);
378139c1837SPaolo Bonzini}
379139c1837SPaolo Bonzini
380139c1837SPaolo Bonzini/*
381139c1837SPaolo Bonzini * Type immediate
382139c1837SPaolo Bonzini */
38310d4af58SRichard Hendersonstatic void tcg_out_opc_imm(TCGContext *s, MIPSInsn opc,
384139c1837SPaolo Bonzini                            TCGReg rt, TCGReg rs, TCGArg imm)
385139c1837SPaolo Bonzini{
386139c1837SPaolo Bonzini    int32_t inst;
387139c1837SPaolo Bonzini
388139c1837SPaolo Bonzini    inst = opc;
389139c1837SPaolo Bonzini    inst |= (rs & 0x1F) << 21;
390139c1837SPaolo Bonzini    inst |= (rt & 0x1F) << 16;
391139c1837SPaolo Bonzini    inst |= (imm & 0xffff);
392139c1837SPaolo Bonzini    tcg_out32(s, inst);
393139c1837SPaolo Bonzini}
394139c1837SPaolo Bonzini
395139c1837SPaolo Bonzini/*
396139c1837SPaolo Bonzini * Type bitfield
397139c1837SPaolo Bonzini */
39810d4af58SRichard Hendersonstatic void tcg_out_opc_bf(TCGContext *s, MIPSInsn opc, TCGReg rt,
399139c1837SPaolo Bonzini                           TCGReg rs, int msb, int lsb)
400139c1837SPaolo Bonzini{
401139c1837SPaolo Bonzini    int32_t inst;
402139c1837SPaolo Bonzini
403139c1837SPaolo Bonzini    inst = opc;
404139c1837SPaolo Bonzini    inst |= (rs & 0x1F) << 21;
405139c1837SPaolo Bonzini    inst |= (rt & 0x1F) << 16;
406139c1837SPaolo Bonzini    inst |= (msb & 0x1F) << 11;
407139c1837SPaolo Bonzini    inst |= (lsb & 0x1F) << 6;
408139c1837SPaolo Bonzini    tcg_out32(s, inst);
409139c1837SPaolo Bonzini}
410139c1837SPaolo Bonzini
41110d4af58SRichard Hendersonstatic void tcg_out_opc_bf64(TCGContext *s, MIPSInsn opc, MIPSInsn opm,
412139c1837SPaolo Bonzini                             MIPSInsn oph, TCGReg rt, TCGReg rs,
413139c1837SPaolo Bonzini                                    int msb, int lsb)
414139c1837SPaolo Bonzini{
415139c1837SPaolo Bonzini    if (lsb >= 32) {
416139c1837SPaolo Bonzini        opc = oph;
417139c1837SPaolo Bonzini        msb -= 32;
418139c1837SPaolo Bonzini        lsb -= 32;
419139c1837SPaolo Bonzini    } else if (msb >= 32) {
420139c1837SPaolo Bonzini        opc = opm;
421139c1837SPaolo Bonzini        msb -= 32;
422139c1837SPaolo Bonzini    }
423139c1837SPaolo Bonzini    tcg_out_opc_bf(s, opc, rt, rs, msb, lsb);
424139c1837SPaolo Bonzini}
425139c1837SPaolo Bonzini
426139c1837SPaolo Bonzini/*
427139c1837SPaolo Bonzini * Type branch
428139c1837SPaolo Bonzini */
42910d4af58SRichard Hendersonstatic void tcg_out_opc_br(TCGContext *s, MIPSInsn opc, TCGReg rt, TCGReg rs)
430139c1837SPaolo Bonzini{
431139c1837SPaolo Bonzini    tcg_out_opc_imm(s, opc, rt, rs, 0);
432139c1837SPaolo Bonzini}
433139c1837SPaolo Bonzini
434139c1837SPaolo Bonzini/*
435139c1837SPaolo Bonzini * Type sa
436139c1837SPaolo Bonzini */
43710d4af58SRichard Hendersonstatic void tcg_out_opc_sa(TCGContext *s, MIPSInsn opc,
438139c1837SPaolo Bonzini                           TCGReg rd, TCGReg rt, TCGArg sa)
439139c1837SPaolo Bonzini{
440139c1837SPaolo Bonzini    int32_t inst;
441139c1837SPaolo Bonzini
442139c1837SPaolo Bonzini    inst = opc;
443139c1837SPaolo Bonzini    inst |= (rt & 0x1F) << 16;
444139c1837SPaolo Bonzini    inst |= (rd & 0x1F) << 11;
445139c1837SPaolo Bonzini    inst |= (sa & 0x1F) <<  6;
446139c1837SPaolo Bonzini    tcg_out32(s, inst);
447139c1837SPaolo Bonzini
448139c1837SPaolo Bonzini}
449139c1837SPaolo Bonzini
450139c1837SPaolo Bonzinistatic void tcg_out_opc_sa64(TCGContext *s, MIPSInsn opc1, MIPSInsn opc2,
451139c1837SPaolo Bonzini                             TCGReg rd, TCGReg rt, TCGArg sa)
452139c1837SPaolo Bonzini{
453139c1837SPaolo Bonzini    int32_t inst;
454139c1837SPaolo Bonzini
455139c1837SPaolo Bonzini    inst = (sa & 32 ? opc2 : opc1);
456139c1837SPaolo Bonzini    inst |= (rt & 0x1F) << 16;
457139c1837SPaolo Bonzini    inst |= (rd & 0x1F) << 11;
458139c1837SPaolo Bonzini    inst |= (sa & 0x1F) <<  6;
459139c1837SPaolo Bonzini    tcg_out32(s, inst);
460139c1837SPaolo Bonzini}
461139c1837SPaolo Bonzini
462139c1837SPaolo Bonzini/*
463139c1837SPaolo Bonzini * Type jump.
464139c1837SPaolo Bonzini * Returns true if the branch was in range and the insn was emitted.
465139c1837SPaolo Bonzini */
4662be7d76bSRichard Hendersonstatic bool tcg_out_opc_jmp(TCGContext *s, MIPSInsn opc, const void *target)
467139c1837SPaolo Bonzini{
468139c1837SPaolo Bonzini    uintptr_t dest = (uintptr_t)target;
469df5af130SRichard Henderson    uintptr_t from = (uintptr_t)tcg_splitwx_to_rx(s->code_ptr) + 4;
470139c1837SPaolo Bonzini    int32_t inst;
471139c1837SPaolo Bonzini
472139c1837SPaolo Bonzini    /* The pc-region branch happens within the 256MB region of
473139c1837SPaolo Bonzini       the delay slot (thus the +4).  */
474139c1837SPaolo Bonzini    if ((from ^ dest) & -(1 << 28)) {
475139c1837SPaolo Bonzini        return false;
476139c1837SPaolo Bonzini    }
477139c1837SPaolo Bonzini    tcg_debug_assert((dest & 3) == 0);
478139c1837SPaolo Bonzini
479139c1837SPaolo Bonzini    inst = opc;
480139c1837SPaolo Bonzini    inst |= (dest >> 2) & 0x3ffffff;
481139c1837SPaolo Bonzini    tcg_out32(s, inst);
482139c1837SPaolo Bonzini    return true;
483139c1837SPaolo Bonzini}
484139c1837SPaolo Bonzini
48510d4af58SRichard Hendersonstatic void tcg_out_nop(TCGContext *s)
486139c1837SPaolo Bonzini{
487139c1837SPaolo Bonzini    tcg_out32(s, 0);
488139c1837SPaolo Bonzini}
489139c1837SPaolo Bonzini
49048c12ba7SRichard Hendersonstatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
49148c12ba7SRichard Henderson{
49248c12ba7SRichard Henderson    memset(p, 0, count * sizeof(tcg_insn_unit));
49348c12ba7SRichard Henderson}
49448c12ba7SRichard Henderson
49510d4af58SRichard Hendersonstatic void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
496139c1837SPaolo Bonzini{
497139c1837SPaolo Bonzini    tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa);
498139c1837SPaolo Bonzini}
499139c1837SPaolo Bonzini
50010d4af58SRichard Hendersonstatic void tcg_out_dsrl(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
501139c1837SPaolo Bonzini{
502139c1837SPaolo Bonzini    tcg_out_opc_sa64(s, OPC_DSRL, OPC_DSRL32, rd, rt, sa);
503139c1837SPaolo Bonzini}
504139c1837SPaolo Bonzini
50510d4af58SRichard Hendersonstatic void tcg_out_dsra(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa)
506139c1837SPaolo Bonzini{
507139c1837SPaolo Bonzini    tcg_out_opc_sa64(s, OPC_DSRA, OPC_DSRA32, rd, rt, sa);
508139c1837SPaolo Bonzini}
509139c1837SPaolo Bonzini
51010d4af58SRichard Hendersonstatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
511139c1837SPaolo Bonzini{
512139c1837SPaolo Bonzini    /* Simple reg-reg move, optimising out the 'do nothing' case */
513139c1837SPaolo Bonzini    if (ret != arg) {
514139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_OR, ret, arg, TCG_REG_ZERO);
515139c1837SPaolo Bonzini    }
516139c1837SPaolo Bonzini    return true;
517139c1837SPaolo Bonzini}
518139c1837SPaolo Bonzini
51947a57286SRichard Hendersonstatic bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg)
52047a57286SRichard Henderson{
52147a57286SRichard Henderson    if (arg == (int16_t)arg) {
52247a57286SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg);
52347a57286SRichard Henderson        return true;
52447a57286SRichard Henderson    }
52547a57286SRichard Henderson    if (arg == (uint16_t)arg) {
52647a57286SRichard Henderson        tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg);
52747a57286SRichard Henderson        return true;
52847a57286SRichard Henderson    }
52947a57286SRichard Henderson    if (arg == (int32_t)arg && (arg & 0xffff) == 0) {
53047a57286SRichard Henderson        tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
53147a57286SRichard Henderson        return true;
53247a57286SRichard Henderson    }
53347a57286SRichard Henderson    return false;
53447a57286SRichard Henderson}
53547a57286SRichard Henderson
5361d9c5b30SRichard Hendersonstatic bool tcg_out_movi_two(TCGContext *s, TCGReg ret, tcg_target_long arg)
5371d9c5b30SRichard Henderson{
5381d9c5b30SRichard Henderson    /*
5391d9c5b30SRichard Henderson     * All signed 32-bit constants are loadable with two immediates,
5401d9c5b30SRichard Henderson     * and everything else requires more work.
5411d9c5b30SRichard Henderson     */
5421d9c5b30SRichard Henderson    if (arg == (int32_t)arg) {
5431d9c5b30SRichard Henderson        if (!tcg_out_movi_one(s, ret, arg)) {
5441d9c5b30SRichard Henderson            tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16);
5451d9c5b30SRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff);
5461d9c5b30SRichard Henderson        }
5471d9c5b30SRichard Henderson        return true;
5481d9c5b30SRichard Henderson    }
5491d9c5b30SRichard Henderson    return false;
5501d9c5b30SRichard Henderson}
5511d9c5b30SRichard Henderson
55248c12ba7SRichard Hendersonstatic void tcg_out_movi_pool(TCGContext *s, TCGReg ret,
55348c12ba7SRichard Henderson                              tcg_target_long arg, TCGReg tbreg)
55448c12ba7SRichard Henderson{
55548c12ba7SRichard Henderson    new_pool_label(s, arg, R_MIPS_16, s->code_ptr, tcg_tbrel_diff(s, NULL));
55648c12ba7SRichard Henderson    tcg_out_opc_imm(s, OPC_LD, ret, tbreg, 0);
55748c12ba7SRichard Henderson}
55848c12ba7SRichard Henderson
55948c12ba7SRichard Hendersonstatic void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret,
56048c12ba7SRichard Henderson                             tcg_target_long arg, TCGReg tbreg)
561139c1837SPaolo Bonzini{
5621d159e64SRichard Henderson    tcg_target_long tmp;
563269e93abSRichard Henderson    int sh, lo;
5641d159e64SRichard Henderson
565139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
566139c1837SPaolo Bonzini        arg = (int32_t)arg;
567139c1837SPaolo Bonzini    }
56847a57286SRichard Henderson
5691d9c5b30SRichard Henderson    /* Load all 32-bit constants. */
5701d9c5b30SRichard Henderson    if (tcg_out_movi_two(s, ret, arg)) {
571139c1837SPaolo Bonzini        return;
572139c1837SPaolo Bonzini    }
57348c12ba7SRichard Henderson    assert(TCG_TARGET_REG_BITS == 64);
57447a57286SRichard Henderson
5751d159e64SRichard Henderson    /* Load addresses within 2GB of TB with 1 or 3 insns. */
5761d159e64SRichard Henderson    tmp = tcg_tbrel_diff(s, (void *)arg);
5771d159e64SRichard Henderson    if (tmp == (int16_t)tmp) {
5781d159e64SRichard Henderson        tcg_out_opc_imm(s, OPC_DADDIU, ret, tbreg, tmp);
5791d159e64SRichard Henderson        return;
5801d159e64SRichard Henderson    }
5811d159e64SRichard Henderson    if (tcg_out_movi_two(s, ret, tmp)) {
5821d159e64SRichard Henderson        tcg_out_opc_reg(s, OPC_DADDU, ret, ret, tbreg);
5831d159e64SRichard Henderson        return;
5841d159e64SRichard Henderson    }
5851d159e64SRichard Henderson
586269e93abSRichard Henderson    /*
587269e93abSRichard Henderson     * Load bitmasks with a right-shift.  This is good for things
588269e93abSRichard Henderson     * like 0x0fff_ffff_ffff_fff0: ADDUI r,0,0xff00 + DSRL r,r,4.
589269e93abSRichard Henderson     * or similarly using LUI.  For this to work, bit 31 must be set.
590269e93abSRichard Henderson     */
591269e93abSRichard Henderson    if (arg > 0 && (int32_t)arg < 0) {
592269e93abSRichard Henderson        sh = clz64(arg);
593269e93abSRichard Henderson        if (tcg_out_movi_one(s, ret, arg << sh)) {
594269e93abSRichard Henderson            tcg_out_dsrl(s, ret, ret, sh);
595269e93abSRichard Henderson            return;
596269e93abSRichard Henderson        }
597269e93abSRichard Henderson    }
598269e93abSRichard Henderson
599269e93abSRichard Henderson    /*
600269e93abSRichard Henderson     * Load slightly larger constants using left-shift.
601269e93abSRichard Henderson     * Limit this sequence to 3 insns to avoid too much expansion.
602269e93abSRichard Henderson     */
603269e93abSRichard Henderson    sh = ctz64(arg);
604269e93abSRichard Henderson    if (sh && tcg_out_movi_two(s, ret, arg >> sh)) {
605269e93abSRichard Henderson        tcg_out_dsll(s, ret, ret, sh);
606269e93abSRichard Henderson        return;
607269e93abSRichard Henderson    }
608269e93abSRichard Henderson
609269e93abSRichard Henderson    /*
610269e93abSRichard Henderson     * Load slightly larger constants using left-shift and add/or.
611269e93abSRichard Henderson     * Prefer addi with a negative immediate when that would produce
612269e93abSRichard Henderson     * a larger shift.  For this to work, bits 15 and 16 must be set.
613269e93abSRichard Henderson     */
614269e93abSRichard Henderson    lo = arg & 0xffff;
615269e93abSRichard Henderson    if (lo) {
616269e93abSRichard Henderson        if ((arg & 0x18000) == 0x18000) {
617269e93abSRichard Henderson            lo = (int16_t)arg;
618269e93abSRichard Henderson        }
619269e93abSRichard Henderson        tmp = arg - lo;
620269e93abSRichard Henderson        sh = ctz64(tmp);
621269e93abSRichard Henderson        tmp >>= sh;
622269e93abSRichard Henderson        if (tcg_out_movi_one(s, ret, tmp)) {
623269e93abSRichard Henderson            tcg_out_dsll(s, ret, ret, sh);
624269e93abSRichard Henderson            tcg_out_opc_imm(s, lo < 0 ? OPC_DADDIU : OPC_ORI, ret, ret, lo);
625269e93abSRichard Henderson            return;
626269e93abSRichard Henderson        }
627269e93abSRichard Henderson    }
628269e93abSRichard Henderson
62948c12ba7SRichard Henderson    /* Otherwise, put 64-bit constants into the constant pool. */
63048c12ba7SRichard Henderson    tcg_out_movi_pool(s, ret, arg, tbreg);
631139c1837SPaolo Bonzini}
63248c12ba7SRichard Henderson
63348c12ba7SRichard Hendersonstatic void tcg_out_movi(TCGContext *s, TCGType type,
63448c12ba7SRichard Henderson                         TCGReg ret, tcg_target_long arg)
63548c12ba7SRichard Henderson{
63648c12ba7SRichard Henderson    TCGReg tbreg = TCG_TARGET_REG_BITS == 64 ? TCG_REG_TB : 0;
63748c12ba7SRichard Henderson    tcg_out_movi_int(s, type, ret, arg, tbreg);
638139c1837SPaolo Bonzini}
639139c1837SPaolo Bonzini
640678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
641678155b2SRichard Henderson{
642678155b2SRichard Henderson    tcg_debug_assert(TCG_TARGET_HAS_ext8s_i32);
643678155b2SRichard Henderson    tcg_out_opc_reg(s, OPC_SEB, rd, TCG_REG_ZERO, rs);
644678155b2SRichard Henderson}
645678155b2SRichard Henderson
646d0e66c89SRichard Hendersonstatic void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rs)
647d0e66c89SRichard Henderson{
648d0e66c89SRichard Henderson    tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xff);
649d0e66c89SRichard Henderson}
650d0e66c89SRichard Henderson
651753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs)
652753e42eaSRichard Henderson{
653753e42eaSRichard Henderson    tcg_debug_assert(TCG_TARGET_HAS_ext16s_i32);
654753e42eaSRichard Henderson    tcg_out_opc_reg(s, OPC_SEH, rd, TCG_REG_ZERO, rs);
655753e42eaSRichard Henderson}
656753e42eaSRichard Henderson
657379afdffSRichard Hendersonstatic void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rs)
658379afdffSRichard Henderson{
659379afdffSRichard Henderson    tcg_out_opc_imm(s, OPC_ANDI, rd, rs, 0xffff);
660379afdffSRichard Henderson}
661379afdffSRichard Henderson
66252bf3398SRichard Hendersonstatic void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rs)
66352bf3398SRichard Henderson{
66452bf3398SRichard Henderson    tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
66552bf3398SRichard Henderson    tcg_out_opc_sa(s, OPC_SLL, rd, rs, 0);
66652bf3398SRichard Henderson}
66752bf3398SRichard Henderson
6689c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
6699c6aa274SRichard Henderson{
670c6a98619SRichard Henderson    if (rd != rs) {
6719c6aa274SRichard Henderson        tcg_out_ext32s(s, rd, rs);
6729c6aa274SRichard Henderson    }
673c6a98619SRichard Henderson}
6749c6aa274SRichard Henderson
675b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rs)
676b9bfe000SRichard Henderson{
677b9bfe000SRichard Henderson    tcg_out_ext32u(s, rd, rs);
678b9bfe000SRichard Henderson}
679b9bfe000SRichard Henderson
680b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rs)
681b8b94ac6SRichard Henderson{
682b8b94ac6SRichard Henderson    tcg_out_ext32s(s, rd, rs);
683b8b94ac6SRichard Henderson}
684b8b94ac6SRichard Henderson
685767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
686767c2503SRichard Henderson{
687767c2503SRichard Henderson    return false;
688767c2503SRichard Henderson}
689767c2503SRichard Henderson
6906a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
6916a6d772eSRichard Henderson                             tcg_target_long imm)
6926a6d772eSRichard Henderson{
6936a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
6946a6d772eSRichard Henderson    g_assert_not_reached();
6956a6d772eSRichard Henderson}
6966a6d772eSRichard Henderson
69727362b7bSRichard Hendersonstatic void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
698139c1837SPaolo Bonzini{
69927362b7bSRichard Henderson    /* ret and arg can't be register tmp0 */
70027362b7bSRichard Henderson    tcg_debug_assert(ret != TCG_TMP0);
70127362b7bSRichard Henderson    tcg_debug_assert(arg != TCG_TMP0);
70227362b7bSRichard Henderson
70327362b7bSRichard Henderson    /* With arg = abcd: */
704139c1837SPaolo Bonzini    if (use_mips32r2_instructions) {
70527362b7bSRichard Henderson        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);                 /* badc */
70627362b7bSRichard Henderson        if (flags & TCG_BSWAP_OS) {
70727362b7bSRichard Henderson            tcg_out_opc_reg(s, OPC_SEH, ret, 0, ret);              /* ssdc */
70827362b7bSRichard Henderson        } else if ((flags & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
70927362b7bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xffff);        /* 00dc */
71027362b7bSRichard Henderson        }
71127362b7bSRichard Henderson        return;
71227362b7bSRichard Henderson    }
71327362b7bSRichard Henderson
71427362b7bSRichard Henderson    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, arg, 8);                  /* 0abc */
71527362b7bSRichard Henderson    if (!(flags & TCG_BSWAP_IZ)) {
71627362b7bSRichard Henderson        tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, TCG_TMP0, 0x00ff);  /* 000c */
71727362b7bSRichard Henderson    }
71827362b7bSRichard Henderson    if (flags & TCG_BSWAP_OS) {
71927362b7bSRichard Henderson        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 24);                  /* d000 */
72027362b7bSRichard Henderson        tcg_out_opc_sa(s, OPC_SRA, ret, ret, 16);                  /* ssd0 */
721139c1837SPaolo Bonzini    } else {
72227362b7bSRichard Henderson        tcg_out_opc_sa(s, OPC_SLL, ret, arg, 8);                   /* bcd0 */
72327362b7bSRichard Henderson        if (flags & TCG_BSWAP_OZ) {
72427362b7bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, ret, ret, 0xff00);        /* 00d0 */
725139c1837SPaolo Bonzini        }
726139c1837SPaolo Bonzini    }
72727362b7bSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP0);                /* ssdc */
728139c1837SPaolo Bonzini}
729139c1837SPaolo Bonzini
730df5af130SRichard Hendersonstatic void tcg_out_bswap_subr(TCGContext *s, const tcg_insn_unit *sub)
731139c1837SPaolo Bonzini{
732d7fc9f48SRichard Henderson    if (!tcg_out_opc_jmp(s, OPC_JAL, sub)) {
733d7fc9f48SRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP1, (uintptr_t)sub);
734d7fc9f48SRichard Henderson        tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_TMP1, 0);
735d7fc9f48SRichard Henderson    }
736139c1837SPaolo Bonzini}
737139c1837SPaolo Bonzini
7381fce6534SRichard Hendersonstatic void tcg_out_bswap32(TCGContext *s, TCGReg ret, TCGReg arg, int flags)
739139c1837SPaolo Bonzini{
740139c1837SPaolo Bonzini    if (use_mips32r2_instructions) {
741139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_WSBH, ret, 0, arg);
742139c1837SPaolo Bonzini        tcg_out_opc_sa(s, OPC_ROTR, ret, ret, 16);
7431fce6534SRichard Henderson        if (flags & TCG_BSWAP_OZ) {
7441fce6534SRichard Henderson            tcg_out_opc_bf(s, OPC_DEXT, ret, ret, 31, 0);
7451fce6534SRichard Henderson        }
7461fce6534SRichard Henderson    } else {
7471fce6534SRichard Henderson        if (flags & TCG_BSWAP_OZ) {
7481fce6534SRichard Henderson            tcg_out_bswap_subr(s, bswap32u_addr);
749139c1837SPaolo Bonzini        } else {
750139c1837SPaolo Bonzini            tcg_out_bswap_subr(s, bswap32_addr);
751139c1837SPaolo Bonzini        }
752139c1837SPaolo Bonzini        /* delay slot -- never omit the insn, like tcg_out_mov might.  */
753139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
754139c1837SPaolo Bonzini        tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
755139c1837SPaolo Bonzini    }
756139c1837SPaolo Bonzini}
757139c1837SPaolo Bonzini
758139c1837SPaolo Bonzinistatic void tcg_out_bswap64(TCGContext *s, TCGReg ret, TCGReg arg)
759139c1837SPaolo Bonzini{
760139c1837SPaolo Bonzini    if (use_mips32r2_instructions) {
761139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DSBH, ret, 0, arg);
762139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DSHD, ret, 0, ret);
763139c1837SPaolo Bonzini    } else {
764139c1837SPaolo Bonzini        tcg_out_bswap_subr(s, bswap64_addr);
765139c1837SPaolo Bonzini        /* delay slot -- never omit the insn, like tcg_out_mov might.  */
766139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_OR, TCG_TMP0, arg, TCG_REG_ZERO);
767139c1837SPaolo Bonzini        tcg_out_mov(s, TCG_TYPE_I32, ret, TCG_TMP3);
768139c1837SPaolo Bonzini    }
769139c1837SPaolo Bonzini}
770139c1837SPaolo Bonzini
77110d4af58SRichard Hendersonstatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
772139c1837SPaolo Bonzini{
7739ecf5f61SRichard Henderson    tcg_debug_assert(TCG_TARGET_REG_BITS == 64);
774139c1837SPaolo Bonzini    if (use_mips32r2_instructions) {
775139c1837SPaolo Bonzini        tcg_out_opc_bf(s, OPC_DEXT, ret, arg, 31, 0);
776139c1837SPaolo Bonzini    } else {
777139c1837SPaolo Bonzini        tcg_out_dsll(s, ret, arg, 32);
778139c1837SPaolo Bonzini        tcg_out_dsrl(s, ret, ret, 32);
779139c1837SPaolo Bonzini    }
780139c1837SPaolo Bonzini}
781139c1837SPaolo Bonzini
782139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, MIPSInsn opc, TCGReg data,
783139c1837SPaolo Bonzini                         TCGReg addr, intptr_t ofs)
784139c1837SPaolo Bonzini{
785139c1837SPaolo Bonzini    int16_t lo = ofs;
786139c1837SPaolo Bonzini    if (ofs != lo) {
787139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
788139c1837SPaolo Bonzini        if (addr != TCG_REG_ZERO) {
789139c1837SPaolo Bonzini            tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP0, TCG_TMP0, addr);
790139c1837SPaolo Bonzini        }
791139c1837SPaolo Bonzini        addr = TCG_TMP0;
792139c1837SPaolo Bonzini    }
793139c1837SPaolo Bonzini    tcg_out_opc_imm(s, opc, data, addr, lo);
794139c1837SPaolo Bonzini}
795139c1837SPaolo Bonzini
79610d4af58SRichard Hendersonstatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
797139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
798139c1837SPaolo Bonzini{
799139c1837SPaolo Bonzini    MIPSInsn opc = OPC_LD;
800139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
801139c1837SPaolo Bonzini        opc = OPC_LW;
802139c1837SPaolo Bonzini    }
803139c1837SPaolo Bonzini    tcg_out_ldst(s, opc, arg, arg1, arg2);
804139c1837SPaolo Bonzini}
805139c1837SPaolo Bonzini
80610d4af58SRichard Hendersonstatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
807139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
808139c1837SPaolo Bonzini{
809139c1837SPaolo Bonzini    MIPSInsn opc = OPC_SD;
810139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32) {
811139c1837SPaolo Bonzini        opc = OPC_SW;
812139c1837SPaolo Bonzini    }
813139c1837SPaolo Bonzini    tcg_out_ldst(s, opc, arg, arg1, arg2);
814139c1837SPaolo Bonzini}
815139c1837SPaolo Bonzini
81610d4af58SRichard Hendersonstatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
817139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
818139c1837SPaolo Bonzini{
819139c1837SPaolo Bonzini    if (val == 0) {
820139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
821139c1837SPaolo Bonzini        return true;
822139c1837SPaolo Bonzini    }
823139c1837SPaolo Bonzini    return false;
824139c1837SPaolo Bonzini}
825139c1837SPaolo Bonzini
826139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
827139c1837SPaolo Bonzini                            TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
828139c1837SPaolo Bonzini                            bool cbh, bool is_sub)
829139c1837SPaolo Bonzini{
830139c1837SPaolo Bonzini    TCGReg th = TCG_TMP1;
831139c1837SPaolo Bonzini
832139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
833139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
834139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
835139c1837SPaolo Bonzini        bl = -bl;
836139c1837SPaolo Bonzini        bh = 0;
837139c1837SPaolo Bonzini        is_sub = !is_sub;
838139c1837SPaolo Bonzini    }
839139c1837SPaolo Bonzini
840139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
841139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
842139c1837SPaolo Bonzini    if (!cbh) {
843139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? OPC_SUBU : OPC_ADDU), th, ah, bh);
844139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
845139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDIU, th, ah, (is_sub ? -bh : bh));
846139c1837SPaolo Bonzini    } else {
847139c1837SPaolo Bonzini        th = ah;
848139c1837SPaolo Bonzini    }
849139c1837SPaolo Bonzini
850139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
851139c1837SPaolo Bonzini    if (is_sub) {
852139c1837SPaolo Bonzini        if (cbl) {
853139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, al, bl);
854139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, -bl);
855139c1837SPaolo Bonzini        } else {
856139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, al, bl);
857139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBU, rl, al, bl);
858139c1837SPaolo Bonzini        }
859139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBU, rh, th, TCG_TMP0);
860139c1837SPaolo Bonzini    } else {
861139c1837SPaolo Bonzini        if (cbl) {
862139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIU, rl, al, bl);
863139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_TMP0, rl, bl);
864139c1837SPaolo Bonzini        } else if (rl == al && rl == bl) {
865139c1837SPaolo Bonzini            tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, al, TCG_TARGET_REG_BITS - 1);
866139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
867139c1837SPaolo Bonzini        } else {
868139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDU, rl, al, bl);
869139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_TMP0, rl, (rl == bl ? al : bl));
870139c1837SPaolo Bonzini        }
871139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADDU, rh, th, TCG_TMP0);
872139c1837SPaolo Bonzini    }
873139c1837SPaolo Bonzini}
874139c1837SPaolo Bonzini
87542221a64SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
87642221a64SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
87742221a64SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
878139c1837SPaolo Bonzini
87942221a64SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
88042221a64SRichard Henderson                               TCGReg arg1, TCGReg arg2)
88142221a64SRichard Henderson{
88242221a64SRichard Henderson    int flags = 0;
88342221a64SRichard Henderson
88442221a64SRichard Henderson    switch (cond) {
88542221a64SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
88642221a64SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
88742221a64SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
88842221a64SRichard Henderson    case TCG_COND_LE:    /* -> GT  */
88942221a64SRichard Henderson    case TCG_COND_LEU:   /* -> GTU */
89042221a64SRichard Henderson        cond = tcg_invert_cond(cond);
89142221a64SRichard Henderson        flags ^= SETCOND_INV;
89242221a64SRichard Henderson        break;
89342221a64SRichard Henderson    default:
89442221a64SRichard Henderson        break;
89542221a64SRichard Henderson    }
89642221a64SRichard Henderson
89742221a64SRichard Henderson    switch (cond) {
89842221a64SRichard Henderson    case TCG_COND_NE:
89942221a64SRichard Henderson        flags |= SETCOND_NEZ;
90042221a64SRichard Henderson        if (arg2 == 0) {
90142221a64SRichard Henderson            return arg1 | flags;
90242221a64SRichard Henderson        }
90342221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
90442221a64SRichard Henderson        break;
90542221a64SRichard Henderson    case TCG_COND_LT:
90642221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
90742221a64SRichard Henderson        break;
90842221a64SRichard Henderson    case TCG_COND_LTU:
90942221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
91042221a64SRichard Henderson        break;
91142221a64SRichard Henderson    case TCG_COND_GT:
91242221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
91342221a64SRichard Henderson        break;
91442221a64SRichard Henderson    case TCG_COND_GTU:
91542221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
91642221a64SRichard Henderson        break;
91742221a64SRichard Henderson    default:
91842221a64SRichard Henderson        g_assert_not_reached();
91942221a64SRichard Henderson    }
92042221a64SRichard Henderson    return ret | flags;
92142221a64SRichard Henderson}
92242221a64SRichard Henderson
92342221a64SRichard Hendersonstatic void tcg_out_setcond_end(TCGContext *s, TCGReg ret, int tmpflags)
92442221a64SRichard Henderson{
92542221a64SRichard Henderson    if (tmpflags != ret) {
92642221a64SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
92742221a64SRichard Henderson
92842221a64SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
92942221a64SRichard Henderson        case SETCOND_INV:
93042221a64SRichard Henderson            /* Intermediate result is boolean: simply invert. */
93142221a64SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
93242221a64SRichard Henderson            break;
93342221a64SRichard Henderson        case SETCOND_NEZ:
93442221a64SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
93542221a64SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
93642221a64SRichard Henderson            break;
93742221a64SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
93842221a64SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
93942221a64SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
94042221a64SRichard Henderson            break;
94142221a64SRichard Henderson        default:
94242221a64SRichard Henderson            g_assert_not_reached();
94342221a64SRichard Henderson        }
94442221a64SRichard Henderson    }
94542221a64SRichard Henderson}
946139c1837SPaolo Bonzini
947139c1837SPaolo Bonzinistatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
948139c1837SPaolo Bonzini                            TCGReg arg1, TCGReg arg2)
949139c1837SPaolo Bonzini{
95042221a64SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2);
95142221a64SRichard Henderson    tcg_out_setcond_end(s, ret, tmpflags);
952139c1837SPaolo Bonzini}
953139c1837SPaolo Bonzini
954139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
955139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
956139c1837SPaolo Bonzini{
957139c1837SPaolo Bonzini    static const MIPSInsn b_zero[16] = {
958139c1837SPaolo Bonzini        [TCG_COND_LT] = OPC_BLTZ,
959139c1837SPaolo Bonzini        [TCG_COND_GT] = OPC_BGTZ,
960139c1837SPaolo Bonzini        [TCG_COND_LE] = OPC_BLEZ,
961139c1837SPaolo Bonzini        [TCG_COND_GE] = OPC_BGEZ,
962139c1837SPaolo Bonzini    };
963139c1837SPaolo Bonzini
96442221a64SRichard Henderson    MIPSInsn b_opc = 0;
965139c1837SPaolo Bonzini
966139c1837SPaolo Bonzini    switch (cond) {
967139c1837SPaolo Bonzini    case TCG_COND_EQ:
968139c1837SPaolo Bonzini        b_opc = OPC_BEQ;
969139c1837SPaolo Bonzini        break;
970139c1837SPaolo Bonzini    case TCG_COND_NE:
971139c1837SPaolo Bonzini        b_opc = OPC_BNE;
972139c1837SPaolo Bonzini        break;
973139c1837SPaolo Bonzini    case TCG_COND_LT:
974139c1837SPaolo Bonzini    case TCG_COND_GT:
975139c1837SPaolo Bonzini    case TCG_COND_LE:
976139c1837SPaolo Bonzini    case TCG_COND_GE:
977139c1837SPaolo Bonzini        if (arg2 == 0) {
978139c1837SPaolo Bonzini            b_opc = b_zero[cond];
979139c1837SPaolo Bonzini            arg2 = arg1;
980139c1837SPaolo Bonzini            arg1 = 0;
981139c1837SPaolo Bonzini        }
982139c1837SPaolo Bonzini        break;
983139c1837SPaolo Bonzini    default:
984139c1837SPaolo Bonzini        break;
985139c1837SPaolo Bonzini    }
986139c1837SPaolo Bonzini
98742221a64SRichard Henderson    if (b_opc == 0) {
98842221a64SRichard Henderson        int tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, arg1, arg2);
98942221a64SRichard Henderson
99042221a64SRichard Henderson        arg2 = TCG_REG_ZERO;
99142221a64SRichard Henderson        arg1 = tmpflags & ~SETCOND_FLAGS;
99242221a64SRichard Henderson        b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
99342221a64SRichard Henderson    }
99442221a64SRichard Henderson
99542221a64SRichard Henderson    tcg_out_reloc(s, s->code_ptr, R_MIPS_PC16, l, 0);
996139c1837SPaolo Bonzini    tcg_out_opc_br(s, b_opc, arg1, arg2);
997139c1837SPaolo Bonzini    tcg_out_nop(s);
998139c1837SPaolo Bonzini}
999139c1837SPaolo Bonzini
100042221a64SRichard Hendersonstatic int tcg_out_setcond2_int(TCGContext *s, TCGCond cond, TCGReg ret,
100142221a64SRichard Henderson                                TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
1002139c1837SPaolo Bonzini{
100342221a64SRichard Henderson    int flags = 0;
100442221a64SRichard Henderson
100542221a64SRichard Henderson    switch (cond) {
100642221a64SRichard Henderson    case TCG_COND_EQ:
100742221a64SRichard Henderson        flags |= SETCOND_INV;
100842221a64SRichard Henderson        /* fall through */
100942221a64SRichard Henderson    case TCG_COND_NE:
101042221a64SRichard Henderson        flags |= SETCOND_NEZ;
101142221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_XOR, TCG_TMP0, al, bl);
101242221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_XOR, TCG_TMP1, ah, bh);
101342221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
101442221a64SRichard Henderson        break;
101542221a64SRichard Henderson
101642221a64SRichard Henderson    default:
101742221a64SRichard Henderson        tcg_out_setcond(s, TCG_COND_EQ, TCG_TMP0, ah, bh);
101842221a64SRichard Henderson        tcg_out_setcond(s, tcg_unsigned_cond(cond), TCG_TMP1, al, bl);
101942221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP0);
102042221a64SRichard Henderson        tcg_out_setcond(s, tcg_high_cond(cond), TCG_TMP0, ah, bh);
102142221a64SRichard Henderson        tcg_out_opc_reg(s, OPC_OR, ret, TCG_TMP0, TCG_TMP1);
102242221a64SRichard Henderson        break;
1023139c1837SPaolo Bonzini    }
102442221a64SRichard Henderson    return ret | flags;
1025139c1837SPaolo Bonzini}
1026139c1837SPaolo Bonzini
1027139c1837SPaolo Bonzinistatic void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
1028139c1837SPaolo Bonzini                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
1029139c1837SPaolo Bonzini{
103042221a64SRichard Henderson    int tmpflags = tcg_out_setcond2_int(s, cond, ret, al, ah, bl, bh);
103142221a64SRichard Henderson    tcg_out_setcond_end(s, ret, tmpflags);
1032139c1837SPaolo Bonzini}
1033139c1837SPaolo Bonzini
1034139c1837SPaolo Bonzinistatic void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
1035139c1837SPaolo Bonzini                            TCGReg bl, TCGReg bh, TCGLabel *l)
1036139c1837SPaolo Bonzini{
103742221a64SRichard Henderson    int tmpflags = tcg_out_setcond2_int(s, cond, TCG_TMP0, al, ah, bl, bh);
103842221a64SRichard Henderson    TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
103942221a64SRichard Henderson    MIPSInsn b_opc = tmpflags & SETCOND_INV ? OPC_BEQ : OPC_BNE;
1040139c1837SPaolo Bonzini
104142221a64SRichard Henderson    tcg_out_reloc(s, s->code_ptr, R_MIPS_PC16, l, 0);
104242221a64SRichard Henderson    tcg_out_opc_br(s, b_opc, tmp, TCG_REG_ZERO);
104342221a64SRichard Henderson    tcg_out_nop(s);
1044139c1837SPaolo Bonzini}
1045139c1837SPaolo Bonzini
1046139c1837SPaolo Bonzinistatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1047139c1837SPaolo Bonzini                            TCGReg c1, TCGReg c2, TCGReg v1, TCGReg v2)
1048139c1837SPaolo Bonzini{
104942221a64SRichard Henderson    int tmpflags;
105042221a64SRichard Henderson    bool eqz;
1051139c1837SPaolo Bonzini
1052139c1837SPaolo Bonzini    /* If one of the values is zero, put it last to match SEL*Z instructions */
1053139c1837SPaolo Bonzini    if (use_mips32r6_instructions && v1 == 0) {
1054139c1837SPaolo Bonzini        v1 = v2;
1055139c1837SPaolo Bonzini        v2 = 0;
1056139c1837SPaolo Bonzini        cond = tcg_invert_cond(cond);
1057139c1837SPaolo Bonzini    }
1058139c1837SPaolo Bonzini
105942221a64SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_TMP0, c1, c2);
106042221a64SRichard Henderson    c1 = tmpflags & ~SETCOND_FLAGS;
106142221a64SRichard Henderson    eqz = tmpflags & SETCOND_INV;
1062139c1837SPaolo Bonzini
1063139c1837SPaolo Bonzini    if (use_mips32r6_instructions) {
1064139c1837SPaolo Bonzini        MIPSInsn m_opc_t = eqz ? OPC_SELEQZ : OPC_SELNEZ;
1065139c1837SPaolo Bonzini        MIPSInsn m_opc_f = eqz ? OPC_SELNEZ : OPC_SELEQZ;
1066139c1837SPaolo Bonzini
1067139c1837SPaolo Bonzini        if (v2 != 0) {
1068139c1837SPaolo Bonzini            tcg_out_opc_reg(s, m_opc_f, TCG_TMP1, v2, c1);
1069139c1837SPaolo Bonzini        }
1070139c1837SPaolo Bonzini        tcg_out_opc_reg(s, m_opc_t, ret, v1, c1);
1071139c1837SPaolo Bonzini        if (v2 != 0) {
1072139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, ret, ret, TCG_TMP1);
1073139c1837SPaolo Bonzini        }
10742cff741dSRichard Henderson        return;
10752cff741dSRichard Henderson    }
1076139c1837SPaolo Bonzini
1077139c1837SPaolo Bonzini    /* This should be guaranteed via constraints */
1078139c1837SPaolo Bonzini    tcg_debug_assert(v2 == ret);
10792cff741dSRichard Henderson
10802cff741dSRichard Henderson    if (use_movnz_instructions) {
10812cff741dSRichard Henderson        MIPSInsn m_opc = eqz ? OPC_MOVZ : OPC_MOVN;
10822cff741dSRichard Henderson        tcg_out_opc_reg(s, m_opc, ret, v1, c1);
10832cff741dSRichard Henderson    } else {
10842cff741dSRichard Henderson        /* Invert the condition in order to branch over the move. */
10852cff741dSRichard Henderson        MIPSInsn b_opc = eqz ? OPC_BNE : OPC_BEQ;
10862cff741dSRichard Henderson        tcg_out_opc_imm(s, b_opc, c1, TCG_REG_ZERO, 2);
10872cff741dSRichard Henderson        tcg_out_nop(s);
10882cff741dSRichard Henderson        /* Open-code tcg_out_mov, without the nop-move check. */
10892cff741dSRichard Henderson        tcg_out_opc_reg(s, OPC_OR, ret, v1, TCG_REG_ZERO);
1090139c1837SPaolo Bonzini    }
1091139c1837SPaolo Bonzini}
1092139c1837SPaolo Bonzini
10932be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1094139c1837SPaolo Bonzini{
10954316de32SRichard Henderson    /*
10964316de32SRichard Henderson     * Note that __mips_abicalls requires the called function's address
10974316de32SRichard Henderson     * to be loaded into $25 (t9), even if a direct branch is in range.
10984316de32SRichard Henderson     *
10994316de32SRichard Henderson     * For n64, always drop the pointer into the constant pool.
11004316de32SRichard Henderson     * We can re-use helper addresses often and do not want any
11014316de32SRichard Henderson     * of the longer sequences tcg_out_movi may try.
11024316de32SRichard Henderson     */
11034316de32SRichard Henderson    if (sizeof(uintptr_t) == 8) {
11044316de32SRichard Henderson        tcg_out_movi_pool(s, TCG_REG_T9, (uintptr_t)arg, TCG_REG_TB);
11054316de32SRichard Henderson    } else {
1106139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg);
11074316de32SRichard Henderson    }
1108139c1837SPaolo Bonzini
1109139c1837SPaolo Bonzini    /* But do try a direct branch, allowing the cpu better insn prefetch.  */
1110139c1837SPaolo Bonzini    if (tail) {
1111139c1837SPaolo Bonzini        if (!tcg_out_opc_jmp(s, OPC_J, arg)) {
1112139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_T9, 0);
1113139c1837SPaolo Bonzini        }
1114139c1837SPaolo Bonzini    } else {
1115139c1837SPaolo Bonzini        if (!tcg_out_opc_jmp(s, OPC_JAL, arg)) {
1116139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_JALR, TCG_REG_RA, TCG_REG_T9, 0);
1117139c1837SPaolo Bonzini        }
1118139c1837SPaolo Bonzini    }
1119139c1837SPaolo Bonzini}
1120139c1837SPaolo Bonzini
1121cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1122cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1123139c1837SPaolo Bonzini{
1124139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1125139c1837SPaolo Bonzini    tcg_out_nop(s);
1126139c1837SPaolo Bonzini}
1127139c1837SPaolo Bonzini
1128f07aaf48SRichard Henderson/* We have four temps, we might as well expose three of them. */
1129f07aaf48SRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
1130f07aaf48SRichard Henderson    .ntmp = 3, .tmp = { TCG_TMP0, TCG_TMP1, TCG_TMP2 }
1131f07aaf48SRichard Henderson};
1132139c1837SPaolo Bonzini
1133139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1134139c1837SPaolo Bonzini{
1135df5af130SRichard Henderson    const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
1136f07aaf48SRichard Henderson    MemOp opc = get_memop(l->oi);
1137139c1837SPaolo Bonzini
1138139c1837SPaolo Bonzini    /* resolve label address */
1139df5af130SRichard Henderson    if (!reloc_pc16(l->label_ptr[0], tgt_rx)
114030feb7eeSRichard Henderson        || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
114191a7fd1fSRichard Henderson        return false;
1142139c1837SPaolo Bonzini    }
1143139c1837SPaolo Bonzini
1144f07aaf48SRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1145f07aaf48SRichard Henderson
1146a7995621SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
1147139c1837SPaolo Bonzini    /* delay slot */
1148f07aaf48SRichard Henderson    tcg_out_nop(s);
1149139c1837SPaolo Bonzini
1150f07aaf48SRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1151139c1837SPaolo Bonzini
1152139c1837SPaolo Bonzini    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
115391a7fd1fSRichard Henderson    if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
115491a7fd1fSRichard Henderson        return false;
115591a7fd1fSRichard Henderson    }
1156139c1837SPaolo Bonzini
1157139c1837SPaolo Bonzini    /* delay slot */
1158f07aaf48SRichard Henderson    tcg_out_nop(s);
1159139c1837SPaolo Bonzini    return true;
1160139c1837SPaolo Bonzini}
1161139c1837SPaolo Bonzini
1162139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1163139c1837SPaolo Bonzini{
1164df5af130SRichard Henderson    const tcg_insn_unit *tgt_rx = tcg_splitwx_to_rx(s->code_ptr);
1165f07aaf48SRichard Henderson    MemOp opc = get_memop(l->oi);
1166139c1837SPaolo Bonzini
1167139c1837SPaolo Bonzini    /* resolve label address */
1168df5af130SRichard Henderson    if (!reloc_pc16(l->label_ptr[0], tgt_rx)
116930feb7eeSRichard Henderson        || (l->label_ptr[1] && !reloc_pc16(l->label_ptr[1], tgt_rx))) {
117091a7fd1fSRichard Henderson        return false;
1171139c1837SPaolo Bonzini    }
1172139c1837SPaolo Bonzini
1173f07aaf48SRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1174139c1837SPaolo Bonzini
1175a7995621SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1176139c1837SPaolo Bonzini    /* delay slot */
1177f07aaf48SRichard Henderson    tcg_out_nop(s);
1178f07aaf48SRichard Henderson
1179f07aaf48SRichard Henderson    tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
1180f07aaf48SRichard Henderson    if (!reloc_pc16(s->code_ptr - 1, l->raddr)) {
1181f07aaf48SRichard Henderson        return false;
1182f07aaf48SRichard Henderson    }
1183f07aaf48SRichard Henderson
1184f07aaf48SRichard Henderson    /* delay slot */
1185f07aaf48SRichard Henderson    tcg_out_nop(s);
1186139c1837SPaolo Bonzini    return true;
1187139c1837SPaolo Bonzini}
118823a79c11SRichard Henderson
11895b7208daSRichard Hendersontypedef struct {
11905b7208daSRichard Henderson    TCGReg base;
1191c0cafab5SRichard Henderson    TCGAtomAlign aa;
11925b7208daSRichard Henderson} HostAddress;
11935b7208daSRichard Henderson
11947b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
11957b880107SRichard Henderson{
11967b880107SRichard Henderson    return false;
11977b880107SRichard Henderson}
11987b880107SRichard Henderson
1199d0a9bb5eSRichard Henderson/* We expect to use a 16-bit negative offset from ENV.  */
1200d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -32768
1201d0a9bb5eSRichard Henderson
12025b7208daSRichard Henderson/*
12037893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
12047893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
12055b7208daSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
12065b7208daSRichard Henderson * is required and fill in @h with the host address for the fast path.
12075b7208daSRichard Henderson */
12085b7208daSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
12095b7208daSRichard Henderson                                           TCGReg addrlo, TCGReg addrhi,
12105b7208daSRichard Henderson                                           MemOpIdx oi, bool is_ld)
12115b7208daSRichard Henderson{
12125e983cbcSRichard Henderson    TCGType addr_type = s->addr_type;
12135b7208daSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
12145b7208daSRichard Henderson    MemOp opc = get_memop(oi);
1215c0cafab5SRichard Henderson    MemOp a_bits;
12165b7208daSRichard Henderson    unsigned s_bits = opc & MO_SIZE;
1217c0cafab5SRichard Henderson    unsigned a_mask;
12185b7208daSRichard Henderson    TCGReg base;
12195b7208daSRichard Henderson
1220c0cafab5SRichard Henderson    h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
1221c0cafab5SRichard Henderson    a_bits = h->aa.align;
1222c0cafab5SRichard Henderson    a_mask = (1 << a_bits) - 1;
1223c0cafab5SRichard Henderson
1224e3a650cdSRichard Henderson    if (tcg_use_softmmu) {
12255b7208daSRichard Henderson        unsigned s_mask = (1 << s_bits) - 1;
12265b7208daSRichard Henderson        int mem_index = get_mmuidx(oi);
1227d0a9bb5eSRichard Henderson        int fast_off = tlb_mask_table_ofs(s, mem_index);
12285b7208daSRichard Henderson        int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
12295b7208daSRichard Henderson        int table_off = fast_off + offsetof(CPUTLBDescFast, table);
12305b7208daSRichard Henderson        int add_off = offsetof(CPUTLBEntry, addend);
12315b7208daSRichard Henderson        int cmp_off = is_ld ? offsetof(CPUTLBEntry, addr_read)
12325b7208daSRichard Henderson                            : offsetof(CPUTLBEntry, addr_write);
12335b7208daSRichard Henderson
12345b7208daSRichard Henderson        ldst = new_ldst_label(s);
12355b7208daSRichard Henderson        ldst->is_ld = is_ld;
12365b7208daSRichard Henderson        ldst->oi = oi;
12375b7208daSRichard Henderson        ldst->addrlo_reg = addrlo;
12385b7208daSRichard Henderson        ldst->addrhi_reg = addrhi;
12395b7208daSRichard Henderson
12405b7208daSRichard Henderson        /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx].  */
12415b7208daSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
12425b7208daSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP1, TCG_AREG0, table_off);
12435b7208daSRichard Henderson
12445b7208daSRichard Henderson        /* Extract the TLB index from the address into TMP3.  */
12455e983cbcSRichard Henderson        if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
12465e983cbcSRichard Henderson            tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, addrlo,
1247aece72b7SRichard Henderson                           s->page_bits - CPU_TLB_ENTRY_BITS);
12485e983cbcSRichard Henderson        } else {
12495e983cbcSRichard Henderson            tcg_out_dsrl(s, TCG_TMP3, addrlo,
1250aece72b7SRichard Henderson                         s->page_bits - CPU_TLB_ENTRY_BITS);
12515e983cbcSRichard Henderson        }
12525b7208daSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_TMP3, TCG_TMP3, TCG_TMP0);
12535b7208daSRichard Henderson
1254e3a650cdSRichard Henderson        /* Add the tlb_table pointer, creating the CPUTLBEntry address.  */
12555b7208daSRichard Henderson        tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
12565b7208daSRichard Henderson
1257238f4380SRichard Henderson        if (TCG_TARGET_REG_BITS == 32 || addr_type == TCG_TYPE_I32) {
1258238f4380SRichard Henderson            /* Load the (low half) tlb comparator.  */
1259238f4380SRichard Henderson            tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3,
1260238f4380SRichard Henderson                       cmp_off + HOST_BIG_ENDIAN * 4);
1261238f4380SRichard Henderson        } else {
1262238f4380SRichard Henderson            tcg_out_ld(s, TCG_TYPE_I64, TCG_TMP0, TCG_TMP3, cmp_off);
1263238f4380SRichard Henderson        }
1264238f4380SRichard Henderson
12655e983cbcSRichard Henderson        if (TCG_TARGET_REG_BITS == 64 || addr_type == TCG_TYPE_I32) {
12662f2a3d1dSRichard Henderson            /* Load the tlb addend for the fast path.  */
12672f2a3d1dSRichard Henderson            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
12685b7208daSRichard Henderson        }
12695b7208daSRichard Henderson
12705b7208daSRichard Henderson        /*
12715b7208daSRichard Henderson         * Mask the page bits, keeping the alignment bits to compare against.
12725b7208daSRichard Henderson         * For unaligned accesses, compare against the end of the access to
12735b7208daSRichard Henderson         * verify that it does not cross a page boundary.
12745b7208daSRichard Henderson         */
1275aece72b7SRichard Henderson        tcg_out_movi(s, addr_type, TCG_TMP1, s->page_mask | a_mask);
12762f2a3d1dSRichard Henderson        if (a_mask < s_mask) {
1277e3a650cdSRichard Henderson            tcg_out_opc_imm(s, (TCG_TARGET_REG_BITS == 32
1278e3a650cdSRichard Henderson                                || addr_type == TCG_TYPE_I32
1279e3a650cdSRichard Henderson                                ? OPC_ADDIU : OPC_DADDIU),
1280e3a650cdSRichard Henderson                            TCG_TMP2, addrlo, s_mask - a_mask);
12815b7208daSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
12822f2a3d1dSRichard Henderson        } else {
12832f2a3d1dSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrlo);
12845b7208daSRichard Henderson        }
12855b7208daSRichard Henderson
12862f2a3d1dSRichard Henderson        /* Zero extend a 32-bit guest address for a 64-bit host. */
12875e983cbcSRichard Henderson        if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
12882f2a3d1dSRichard Henderson            tcg_out_ext32u(s, TCG_TMP2, addrlo);
12892f2a3d1dSRichard Henderson            addrlo = TCG_TMP2;
12905b7208daSRichard Henderson        }
12915b7208daSRichard Henderson
12925b7208daSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
12935b7208daSRichard Henderson        tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
12945b7208daSRichard Henderson
12955b7208daSRichard Henderson        /* Load and test the high half tlb comparator.  */
12965e983cbcSRichard Henderson        if (TCG_TARGET_REG_BITS == 32 && addr_type != TCG_TYPE_I32) {
12975b7208daSRichard Henderson            /* delay slot */
12985b7208daSRichard Henderson            tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
12995b7208daSRichard Henderson
13005b7208daSRichard Henderson            /* Load the tlb addend for the fast path.  */
13012f2a3d1dSRichard Henderson            tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP3, TCG_TMP3, add_off);
13025b7208daSRichard Henderson
13035b7208daSRichard Henderson            ldst->label_ptr[1] = s->code_ptr;
13045b7208daSRichard Henderson            tcg_out_opc_br(s, OPC_BNE, addrhi, TCG_TMP0);
13055b7208daSRichard Henderson        }
13065b7208daSRichard Henderson
13075b7208daSRichard Henderson        /* delay slot */
13082f2a3d1dSRichard Henderson        base = TCG_TMP3;
13092f2a3d1dSRichard Henderson        tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP3, addrlo);
1310e3a650cdSRichard Henderson    } else {
13115b7208daSRichard Henderson        if (a_mask && (use_mips32r6_instructions || a_bits != s_bits)) {
13125b7208daSRichard Henderson            ldst = new_ldst_label(s);
13135b7208daSRichard Henderson
13145b7208daSRichard Henderson            ldst->is_ld = is_ld;
13155b7208daSRichard Henderson            ldst->oi = oi;
13165b7208daSRichard Henderson            ldst->addrlo_reg = addrlo;
13175b7208daSRichard Henderson            ldst->addrhi_reg = addrhi;
13185b7208daSRichard Henderson
13195b7208daSRichard Henderson            /* We are expecting a_bits to max out at 7, much lower than ANDI. */
13205b7208daSRichard Henderson            tcg_debug_assert(a_bits < 16);
13215b7208daSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP0, addrlo, a_mask);
13225b7208daSRichard Henderson
13235b7208daSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
13245b7208daSRichard Henderson            if (use_mips32r6_instructions) {
13255b7208daSRichard Henderson                tcg_out_opc_br(s, OPC_BNEZALC_R6, TCG_REG_ZERO, TCG_TMP0);
13265b7208daSRichard Henderson            } else {
13275b7208daSRichard Henderson                tcg_out_opc_br(s, OPC_BNEL, TCG_TMP0, TCG_REG_ZERO);
13285b7208daSRichard Henderson                tcg_out_nop(s);
13295b7208daSRichard Henderson            }
13305b7208daSRichard Henderson        }
13315b7208daSRichard Henderson
13325b7208daSRichard Henderson        base = addrlo;
13335e983cbcSRichard Henderson        if (TCG_TARGET_REG_BITS == 64 && addr_type == TCG_TYPE_I32) {
13345b7208daSRichard Henderson            tcg_out_ext32u(s, TCG_REG_A0, base);
13355b7208daSRichard Henderson            base = TCG_REG_A0;
13365b7208daSRichard Henderson        }
13375b7208daSRichard Henderson        if (guest_base) {
13385b7208daSRichard Henderson            if (guest_base == (int16_t)guest_base) {
13395b7208daSRichard Henderson                tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_A0, base, guest_base);
13405b7208daSRichard Henderson            } else {
13415b7208daSRichard Henderson                tcg_out_opc_reg(s, ALIAS_PADD, TCG_REG_A0, base,
13425b7208daSRichard Henderson                                TCG_GUEST_BASE_REG);
13435b7208daSRichard Henderson            }
13445b7208daSRichard Henderson            base = TCG_REG_A0;
13455b7208daSRichard Henderson        }
1346e3a650cdSRichard Henderson    }
13475b7208daSRichard Henderson
13485b7208daSRichard Henderson    h->base = base;
13495b7208daSRichard Henderson    return ldst;
13505b7208daSRichard Henderson}
13515b7208daSRichard Henderson
1352139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1353eb664d0cSRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1354139c1837SPaolo Bonzini{
1355a7995621SRichard Henderson    switch (opc & MO_SSIZE) {
1356139c1837SPaolo Bonzini    case MO_UB:
1357139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1358139c1837SPaolo Bonzini        break;
1359139c1837SPaolo Bonzini    case MO_SB:
1360139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1361139c1837SPaolo Bonzini        break;
1362139c1837SPaolo Bonzini    case MO_UW:
1363139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1364139c1837SPaolo Bonzini        break;
1365139c1837SPaolo Bonzini    case MO_SW:
1366139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1367139c1837SPaolo Bonzini        break;
1368139c1837SPaolo Bonzini    case MO_UL:
1369eb664d0cSRichard Henderson        if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64) {
1370139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1371139c1837SPaolo Bonzini            break;
1372139c1837SPaolo Bonzini        }
1373139c1837SPaolo Bonzini        /* FALLTHRU */
1374139c1837SPaolo Bonzini    case MO_SL:
1375139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1376139c1837SPaolo Bonzini        break;
1377fc313c64SFrédéric Pétrot    case MO_UQ:
1378139c1837SPaolo Bonzini        /* Prefer to load from offset 0 first, but allow for overlap.  */
1379139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1380139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1381b56d5a8aSRichard Henderson        } else if (HOST_BIG_ENDIAN ? hi != base : lo == base) {
1382139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1383139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1384139c1837SPaolo Bonzini        } else {
1385139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF);
1386139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF);
1387139c1837SPaolo Bonzini        }
1388139c1837SPaolo Bonzini        break;
1389139c1837SPaolo Bonzini    default:
1390732e89f4SRichard Henderson        g_assert_not_reached();
1391139c1837SPaolo Bonzini    }
1392139c1837SPaolo Bonzini}
1393139c1837SPaolo Bonzini
1394d9e52834SRichard Hendersonstatic void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
1395eb664d0cSRichard Henderson                                    TCGReg base, MemOp opc, TCGType type)
139623a79c11SRichard Henderson{
1397b56d5a8aSRichard Henderson    const MIPSInsn lw1 = HOST_BIG_ENDIAN ? OPC_LWL : OPC_LWR;
1398b56d5a8aSRichard Henderson    const MIPSInsn lw2 = HOST_BIG_ENDIAN ? OPC_LWR : OPC_LWL;
1399b56d5a8aSRichard Henderson    const MIPSInsn ld1 = HOST_BIG_ENDIAN ? OPC_LDL : OPC_LDR;
1400b56d5a8aSRichard Henderson    const MIPSInsn ld2 = HOST_BIG_ENDIAN ? OPC_LDR : OPC_LDL;
1401a7995621SRichard Henderson    bool sgn = opc & MO_SIGN;
140223a79c11SRichard Henderson
1403a7995621SRichard Henderson    switch (opc & MO_SIZE) {
1404a7995621SRichard Henderson    case MO_16:
1405a7995621SRichard Henderson        if (HOST_BIG_ENDIAN) {
140623a79c11SRichard Henderson            tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 0);
140723a79c11SRichard Henderson            tcg_out_opc_imm(s, OPC_LBU, lo, base, 1);
140823a79c11SRichard Henderson            if (use_mips32r2_instructions) {
140923a79c11SRichard Henderson                tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
141023a79c11SRichard Henderson            } else {
141123a79c11SRichard Henderson                tcg_out_opc_sa(s, OPC_SLL, TCG_TMP0, TCG_TMP0, 8);
1412a7995621SRichard Henderson                tcg_out_opc_reg(s, OPC_OR, lo, lo, TCG_TMP0);
141323a79c11SRichard Henderson            }
1414a7995621SRichard Henderson        } else if (use_mips32r2_instructions && lo != base) {
141523a79c11SRichard Henderson            tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
141623a79c11SRichard Henderson            tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP0, base, 1);
141723a79c11SRichard Henderson            tcg_out_opc_bf(s, OPC_INS, lo, TCG_TMP0, 31, 8);
141823a79c11SRichard Henderson        } else {
141923a79c11SRichard Henderson            tcg_out_opc_imm(s, OPC_LBU, TCG_TMP0, base, 0);
142023a79c11SRichard Henderson            tcg_out_opc_imm(s, sgn ? OPC_LB : OPC_LBU, TCG_TMP1, base, 1);
142123a79c11SRichard Henderson            tcg_out_opc_sa(s, OPC_SLL, TCG_TMP1, TCG_TMP1, 8);
142223a79c11SRichard Henderson            tcg_out_opc_reg(s, OPC_OR, lo, TCG_TMP0, TCG_TMP1);
142323a79c11SRichard Henderson        }
142423a79c11SRichard Henderson        break;
142523a79c11SRichard Henderson
1426a7995621SRichard Henderson    case MO_32:
142723a79c11SRichard Henderson        tcg_out_opc_imm(s, lw1, lo, base, 0);
142823a79c11SRichard Henderson        tcg_out_opc_imm(s, lw2, lo, base, 3);
1429eb664d0cSRichard Henderson        if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I64 && !sgn) {
143023a79c11SRichard Henderson            tcg_out_ext32u(s, lo, lo);
143123a79c11SRichard Henderson        }
143223a79c11SRichard Henderson        break;
143323a79c11SRichard Henderson
1434a7995621SRichard Henderson    case MO_64:
143523a79c11SRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
143623a79c11SRichard Henderson            tcg_out_opc_imm(s, ld1, lo, base, 0);
143723a79c11SRichard Henderson            tcg_out_opc_imm(s, ld2, lo, base, 7);
143823a79c11SRichard Henderson        } else {
1439b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, lw1, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 0);
1440b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, lw2, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 3);
1441b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, lw1, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 0);
1442b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, lw2, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 3);
144323a79c11SRichard Henderson        }
144423a79c11SRichard Henderson        break;
144523a79c11SRichard Henderson
144623a79c11SRichard Henderson    default:
144723a79c11SRichard Henderson        g_assert_not_reached();
144823a79c11SRichard Henderson    }
144923a79c11SRichard Henderson}
145023a79c11SRichard Henderson
1451eb664d0cSRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg datalo, TCGReg datahi,
1452eb664d0cSRichard Henderson                            TCGReg addrlo, TCGReg addrhi,
1453eb664d0cSRichard Henderson                            MemOpIdx oi, TCGType data_type)
1454139c1837SPaolo Bonzini{
1455eb664d0cSRichard Henderson    MemOp opc = get_memop(oi);
14565b7208daSRichard Henderson    TCGLabelQemuLdst *ldst;
14575b7208daSRichard Henderson    HostAddress h;
1458139c1837SPaolo Bonzini
14595b7208daSRichard Henderson    ldst = prepare_host_addr(s, &h, addrlo, addrhi, oi, true);
1460eb664d0cSRichard Henderson
1461c0cafab5SRichard Henderson    if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
14625b7208daSRichard Henderson        tcg_out_qemu_ld_direct(s, datalo, datahi, h.base, opc, data_type);
1463d9e52834SRichard Henderson    } else {
14645b7208daSRichard Henderson        tcg_out_qemu_ld_unalign(s, datalo, datahi, h.base, opc, data_type);
1465d9e52834SRichard Henderson    }
14665b7208daSRichard Henderson
14675b7208daSRichard Henderson    if (ldst) {
14685b7208daSRichard Henderson        ldst->type = data_type;
14695b7208daSRichard Henderson        ldst->datalo_reg = datalo;
14705b7208daSRichard Henderson        ldst->datahi_reg = datahi;
14715b7208daSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1472139c1837SPaolo Bonzini    }
1473139c1837SPaolo Bonzini}
1474139c1837SPaolo Bonzini
1475139c1837SPaolo Bonzinistatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1476139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1477139c1837SPaolo Bonzini{
1478a7995621SRichard Henderson    switch (opc & MO_SIZE) {
1479139c1837SPaolo Bonzini    case MO_8:
1480139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SB, lo, base, 0);
1481139c1837SPaolo Bonzini        break;
1482139c1837SPaolo Bonzini    case MO_16:
1483139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SH, lo, base, 0);
1484139c1837SPaolo Bonzini        break;
1485139c1837SPaolo Bonzini    case MO_32:
1486139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SW, lo, base, 0);
1487139c1837SPaolo Bonzini        break;
1488139c1837SPaolo Bonzini    case MO_64:
1489139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1490139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SD, lo, base, 0);
1491139c1837SPaolo Bonzini        } else {
1492b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, OPC_SW, HOST_BIG_ENDIAN ? hi : lo, base, 0);
1493b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, OPC_SW, HOST_BIG_ENDIAN ? lo : hi, base, 4);
1494139c1837SPaolo Bonzini        }
1495139c1837SPaolo Bonzini        break;
1496139c1837SPaolo Bonzini    default:
1497732e89f4SRichard Henderson        g_assert_not_reached();
1498139c1837SPaolo Bonzini    }
1499139c1837SPaolo Bonzini}
1500139c1837SPaolo Bonzini
1501d9e52834SRichard Hendersonstatic void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
150223a79c11SRichard Henderson                                    TCGReg base, MemOp opc)
150323a79c11SRichard Henderson{
1504b56d5a8aSRichard Henderson    const MIPSInsn sw1 = HOST_BIG_ENDIAN ? OPC_SWL : OPC_SWR;
1505b56d5a8aSRichard Henderson    const MIPSInsn sw2 = HOST_BIG_ENDIAN ? OPC_SWR : OPC_SWL;
1506b56d5a8aSRichard Henderson    const MIPSInsn sd1 = HOST_BIG_ENDIAN ? OPC_SDL : OPC_SDR;
1507b56d5a8aSRichard Henderson    const MIPSInsn sd2 = HOST_BIG_ENDIAN ? OPC_SDR : OPC_SDL;
150823a79c11SRichard Henderson
1509a7995621SRichard Henderson    switch (opc & MO_SIZE) {
1510a7995621SRichard Henderson    case MO_16:
151123a79c11SRichard Henderson        tcg_out_opc_sa(s, OPC_SRL, TCG_TMP0, lo, 8);
1512a7995621SRichard Henderson        tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? TCG_TMP0 : lo, base, 0);
1513a7995621SRichard Henderson        tcg_out_opc_imm(s, OPC_SB, HOST_BIG_ENDIAN ? lo : TCG_TMP0, base, 1);
151423a79c11SRichard Henderson        break;
151523a79c11SRichard Henderson
151623a79c11SRichard Henderson    case MO_32:
151723a79c11SRichard Henderson        tcg_out_opc_imm(s, sw1, lo, base, 0);
151823a79c11SRichard Henderson        tcg_out_opc_imm(s, sw2, lo, base, 3);
151923a79c11SRichard Henderson        break;
152023a79c11SRichard Henderson
152123a79c11SRichard Henderson    case MO_64:
152223a79c11SRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
152323a79c11SRichard Henderson            tcg_out_opc_imm(s, sd1, lo, base, 0);
152423a79c11SRichard Henderson            tcg_out_opc_imm(s, sd2, lo, base, 7);
152523a79c11SRichard Henderson        } else {
1526b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, sw1, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 0);
1527b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, sw2, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 3);
1528b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, sw1, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 0);
1529b56d5a8aSRichard Henderson            tcg_out_opc_imm(s, sw2, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 3);
153023a79c11SRichard Henderson        }
153123a79c11SRichard Henderson        break;
153223a79c11SRichard Henderson
153323a79c11SRichard Henderson    default:
1534732e89f4SRichard Henderson        g_assert_not_reached();
153523a79c11SRichard Henderson    }
153623a79c11SRichard Henderson}
1537139c1837SPaolo Bonzini
1538eb664d0cSRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg datalo, TCGReg datahi,
1539eb664d0cSRichard Henderson                            TCGReg addrlo, TCGReg addrhi,
1540eb664d0cSRichard Henderson                            MemOpIdx oi, TCGType data_type)
1541eb664d0cSRichard Henderson{
1542eb664d0cSRichard Henderson    MemOp opc = get_memop(oi);
15435b7208daSRichard Henderson    TCGLabelQemuLdst *ldst;
15445b7208daSRichard Henderson    HostAddress h;
1545139c1837SPaolo Bonzini
15465b7208daSRichard Henderson    ldst = prepare_host_addr(s, &h, addrlo, addrhi, oi, false);
1547eb664d0cSRichard Henderson
1548c0cafab5SRichard Henderson    if (use_mips32r6_instructions || h.aa.align >= (opc & MO_SIZE)) {
15495b7208daSRichard Henderson        tcg_out_qemu_st_direct(s, datalo, datahi, h.base, opc);
1550d9e52834SRichard Henderson    } else {
15515b7208daSRichard Henderson        tcg_out_qemu_st_unalign(s, datalo, datahi, h.base, opc);
1552d9e52834SRichard Henderson    }
15535b7208daSRichard Henderson
15545b7208daSRichard Henderson    if (ldst) {
15555b7208daSRichard Henderson        ldst->type = data_type;
15565b7208daSRichard Henderson        ldst->datalo_reg = datalo;
15575b7208daSRichard Henderson        ldst->datahi_reg = datahi;
15585b7208daSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1559139c1837SPaolo Bonzini    }
1560139c1837SPaolo Bonzini}
1561139c1837SPaolo Bonzini
1562139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1563139c1837SPaolo Bonzini{
1564139c1837SPaolo Bonzini    static const MIPSInsn sync[] = {
1565139c1837SPaolo Bonzini        /* Note that SYNC_MB is a slightly weaker than SYNC 0,
1566139c1837SPaolo Bonzini           as the former is an ordering barrier and the latter
1567139c1837SPaolo Bonzini           is a completion barrier.  */
1568139c1837SPaolo Bonzini        [0 ... TCG_MO_ALL]            = OPC_SYNC_MB,
1569139c1837SPaolo Bonzini        [TCG_MO_LD_LD]                = OPC_SYNC_RMB,
1570139c1837SPaolo Bonzini        [TCG_MO_ST_ST]                = OPC_SYNC_WMB,
1571139c1837SPaolo Bonzini        [TCG_MO_LD_ST]                = OPC_SYNC_RELEASE,
1572139c1837SPaolo Bonzini        [TCG_MO_LD_ST | TCG_MO_ST_ST] = OPC_SYNC_RELEASE,
1573139c1837SPaolo Bonzini        [TCG_MO_LD_ST | TCG_MO_LD_LD] = OPC_SYNC_ACQUIRE,
1574139c1837SPaolo Bonzini    };
1575139c1837SPaolo Bonzini    tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1576139c1837SPaolo Bonzini}
1577139c1837SPaolo Bonzini
1578139c1837SPaolo Bonzinistatic void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6,
1579139c1837SPaolo Bonzini                        int width, TCGReg a0, TCGReg a1, TCGArg a2)
1580139c1837SPaolo Bonzini{
1581139c1837SPaolo Bonzini    if (use_mips32r6_instructions) {
1582139c1837SPaolo Bonzini        if (a2 == width) {
1583139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv6, a0, a1, 0);
1584139c1837SPaolo Bonzini        } else {
1585139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv6, TCG_TMP0, a1, 0);
1586139c1837SPaolo Bonzini            tcg_out_movcond(s, TCG_COND_EQ, a0, a1, 0, a2, TCG_TMP0);
1587139c1837SPaolo Bonzini        }
1588139c1837SPaolo Bonzini    } else {
1589139c1837SPaolo Bonzini        if (a2 == width) {
1590139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1591139c1837SPaolo Bonzini        } else if (a0 == a2) {
1592139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1593139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MOVN, a0, TCG_TMP0, a1);
1594139c1837SPaolo Bonzini        } else if (a0 != a1) {
1595139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv2, a0, a1, a1);
1596139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MOVZ, a0, a2, a1);
1597139c1837SPaolo Bonzini        } else {
1598139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opcv2, TCG_TMP0, a1, a1);
1599139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MOVZ, TCG_TMP0, a2, a1);
1600139c1837SPaolo Bonzini            tcg_out_mov(s, TCG_TYPE_REG, a0, TCG_TMP0);
1601139c1837SPaolo Bonzini        }
1602139c1837SPaolo Bonzini    }
1603139c1837SPaolo Bonzini}
1604139c1837SPaolo Bonzini
1605b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1606b55a8d9dSRichard Henderson{
160753c4fa27SRichard Henderson    TCGReg base = TCG_REG_ZERO;
160853c4fa27SRichard Henderson    int16_t lo = 0;
1609b55a8d9dSRichard Henderson
161053c4fa27SRichard Henderson    if (a0) {
161153c4fa27SRichard Henderson        intptr_t ofs;
161253c4fa27SRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
161353c4fa27SRichard Henderson            ofs = tcg_tbrel_diff(s, (void *)a0);
161453c4fa27SRichard Henderson            lo = ofs;
161553c4fa27SRichard Henderson            if (ofs == lo) {
161653c4fa27SRichard Henderson                base = TCG_REG_TB;
161753c4fa27SRichard Henderson            } else {
161853c4fa27SRichard Henderson                base = TCG_REG_V0;
161953c4fa27SRichard Henderson                tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
162053c4fa27SRichard Henderson                tcg_out_opc_reg(s, ALIAS_PADD, base, base, TCG_REG_TB);
162153c4fa27SRichard Henderson            }
162253c4fa27SRichard Henderson        } else {
162353c4fa27SRichard Henderson            ofs = a0;
162453c4fa27SRichard Henderson            lo = ofs;
162553c4fa27SRichard Henderson            base = TCG_REG_V0;
162653c4fa27SRichard Henderson            tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo);
162753c4fa27SRichard Henderson        }
1628b55a8d9dSRichard Henderson    }
1629b55a8d9dSRichard Henderson    if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) {
1630b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr);
1631b55a8d9dSRichard Henderson        tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0);
1632b55a8d9dSRichard Henderson    }
163353c4fa27SRichard Henderson    /* delay slot */
163453c4fa27SRichard Henderson    tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_V0, base, lo);
1635b55a8d9dSRichard Henderson}
1636b55a8d9dSRichard Henderson
1637cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1638cf7d6b8eSRichard Henderson{
163953c4fa27SRichard Henderson    intptr_t ofs = get_jmp_target_addr(s, which);
164053c4fa27SRichard Henderson    TCGReg base, dest;
164153c4fa27SRichard Henderson
1642cf7d6b8eSRichard Henderson    /* indirect jump method */
164353c4fa27SRichard Henderson    if (TCG_TARGET_REG_BITS == 64) {
164453c4fa27SRichard Henderson        dest = TCG_REG_TB;
164553c4fa27SRichard Henderson        base = TCG_REG_TB;
164653c4fa27SRichard Henderson        ofs = tcg_tbrel_diff(s, (void *)ofs);
164753c4fa27SRichard Henderson    } else {
164853c4fa27SRichard Henderson        dest = TCG_TMP0;
164953c4fa27SRichard Henderson        base = TCG_REG_ZERO;
165053c4fa27SRichard Henderson    }
165153c4fa27SRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, dest, base, ofs);
165253c4fa27SRichard Henderson    tcg_out_opc_reg(s, OPC_JR, 0, dest, 0);
165353c4fa27SRichard Henderson    /* delay slot */
1654cf7d6b8eSRichard Henderson    tcg_out_nop(s);
165553c4fa27SRichard Henderson
1656cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
165753c4fa27SRichard Henderson    if (TCG_TARGET_REG_BITS == 64) {
165853c4fa27SRichard Henderson        /* For the unlinked case, need to reset TCG_REG_TB. */
165953c4fa27SRichard Henderson        tcg_out_ldst(s, ALIAS_PADDI, TCG_REG_TB, TCG_REG_TB,
166053c4fa27SRichard Henderson                     -tcg_current_code_size(s));
166153c4fa27SRichard Henderson    }
1662cf7d6b8eSRichard Henderson}
1663cf7d6b8eSRichard Henderson
166490c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
166590c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
166690c0fee3SRichard Henderson{
166790c0fee3SRichard Henderson    /* Always indirect, nothing to do */
166890c0fee3SRichard Henderson}
166990c0fee3SRichard Henderson
167010d4af58SRichard Hendersonstatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
16715e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
16725e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1673139c1837SPaolo Bonzini{
1674139c1837SPaolo Bonzini    MIPSInsn i1, i2;
1675139c1837SPaolo Bonzini    TCGArg a0, a1, a2;
1676139c1837SPaolo Bonzini    int c2;
1677139c1837SPaolo Bonzini
167851800e43SRichard Henderson    /*
167951800e43SRichard Henderson     * Note that many operands use the constraint set "rZ".
168051800e43SRichard Henderson     * We make use of the fact that 0 is the ZERO register,
168151800e43SRichard Henderson     * and hence such cases need not check for const_args.
168251800e43SRichard Henderson     */
1683139c1837SPaolo Bonzini    a0 = args[0];
1684139c1837SPaolo Bonzini    a1 = args[1];
1685139c1837SPaolo Bonzini    a2 = args[2];
1686139c1837SPaolo Bonzini    c2 = const_args[2];
1687139c1837SPaolo Bonzini
1688139c1837SPaolo Bonzini    switch (opc) {
1689139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1690139c1837SPaolo Bonzini        /* jmp to the given host address (could be epilogue) */
1691139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_JR, 0, a0, 0);
169253c4fa27SRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
169353c4fa27SRichard Henderson            tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, a0);
169453c4fa27SRichard Henderson        } else {
1695139c1837SPaolo Bonzini            tcg_out_nop(s);
169653c4fa27SRichard Henderson        }
1697139c1837SPaolo Bonzini        break;
1698139c1837SPaolo Bonzini    case INDEX_op_br:
1699139c1837SPaolo Bonzini        tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO,
1700139c1837SPaolo Bonzini                       arg_label(a0));
1701139c1837SPaolo Bonzini        break;
1702139c1837SPaolo Bonzini
1703139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1704139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1705139c1837SPaolo Bonzini        i1 = OPC_LBU;
1706139c1837SPaolo Bonzini        goto do_ldst;
1707139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1708139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1709139c1837SPaolo Bonzini        i1 = OPC_LB;
1710139c1837SPaolo Bonzini        goto do_ldst;
1711139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1712139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1713139c1837SPaolo Bonzini        i1 = OPC_LHU;
1714139c1837SPaolo Bonzini        goto do_ldst;
1715139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1716139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1717139c1837SPaolo Bonzini        i1 = OPC_LH;
1718139c1837SPaolo Bonzini        goto do_ldst;
1719139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1720139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1721139c1837SPaolo Bonzini        i1 = OPC_LW;
1722139c1837SPaolo Bonzini        goto do_ldst;
1723139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1724139c1837SPaolo Bonzini        i1 = OPC_LWU;
1725139c1837SPaolo Bonzini        goto do_ldst;
1726139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1727139c1837SPaolo Bonzini        i1 = OPC_LD;
1728139c1837SPaolo Bonzini        goto do_ldst;
1729139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1730139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1731139c1837SPaolo Bonzini        i1 = OPC_SB;
1732139c1837SPaolo Bonzini        goto do_ldst;
1733139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1734139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1735139c1837SPaolo Bonzini        i1 = OPC_SH;
1736139c1837SPaolo Bonzini        goto do_ldst;
1737139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1738139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1739139c1837SPaolo Bonzini        i1 = OPC_SW;
1740139c1837SPaolo Bonzini        goto do_ldst;
1741139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1742139c1837SPaolo Bonzini        i1 = OPC_SD;
1743139c1837SPaolo Bonzini    do_ldst:
1744139c1837SPaolo Bonzini        tcg_out_ldst(s, i1, a0, a1, a2);
1745139c1837SPaolo Bonzini        break;
1746139c1837SPaolo Bonzini
1747139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1748139c1837SPaolo Bonzini        i1 = OPC_ADDU, i2 = OPC_ADDIU;
1749139c1837SPaolo Bonzini        goto do_binary;
1750139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1751139c1837SPaolo Bonzini        i1 = OPC_DADDU, i2 = OPC_DADDIU;
1752139c1837SPaolo Bonzini        goto do_binary;
1753139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1754139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1755139c1837SPaolo Bonzini        i1 = OPC_OR, i2 = OPC_ORI;
1756139c1837SPaolo Bonzini        goto do_binary;
1757139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1758139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1759139c1837SPaolo Bonzini        i1 = OPC_XOR, i2 = OPC_XORI;
1760139c1837SPaolo Bonzini    do_binary:
1761139c1837SPaolo Bonzini        if (c2) {
1762139c1837SPaolo Bonzini            tcg_out_opc_imm(s, i2, a0, a1, a2);
1763139c1837SPaolo Bonzini            break;
1764139c1837SPaolo Bonzini        }
1765139c1837SPaolo Bonzini    do_binaryv:
1766139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i1, a0, a1, a2);
1767139c1837SPaolo Bonzini        break;
1768139c1837SPaolo Bonzini
1769139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1770139c1837SPaolo Bonzini        i1 = OPC_SUBU, i2 = OPC_ADDIU;
1771139c1837SPaolo Bonzini        goto do_subtract;
1772139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1773139c1837SPaolo Bonzini        i1 = OPC_DSUBU, i2 = OPC_DADDIU;
1774139c1837SPaolo Bonzini    do_subtract:
1775139c1837SPaolo Bonzini        if (c2) {
1776139c1837SPaolo Bonzini            tcg_out_opc_imm(s, i2, a0, a1, -a2);
1777139c1837SPaolo Bonzini            break;
1778139c1837SPaolo Bonzini        }
1779139c1837SPaolo Bonzini        goto do_binaryv;
1780139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1781139c1837SPaolo Bonzini        if (c2 && a2 != (uint16_t)a2) {
1782139c1837SPaolo Bonzini            int msb = ctz32(~a2) - 1;
1783139c1837SPaolo Bonzini            tcg_debug_assert(use_mips32r2_instructions);
1784139c1837SPaolo Bonzini            tcg_debug_assert(is_p2m1(a2));
1785139c1837SPaolo Bonzini            tcg_out_opc_bf(s, OPC_EXT, a0, a1, msb, 0);
1786139c1837SPaolo Bonzini            break;
1787139c1837SPaolo Bonzini        }
1788139c1837SPaolo Bonzini        i1 = OPC_AND, i2 = OPC_ANDI;
1789139c1837SPaolo Bonzini        goto do_binary;
1790139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1791139c1837SPaolo Bonzini        if (c2 && a2 != (uint16_t)a2) {
1792139c1837SPaolo Bonzini            int msb = ctz64(~a2) - 1;
1793139c1837SPaolo Bonzini            tcg_debug_assert(use_mips32r2_instructions);
1794139c1837SPaolo Bonzini            tcg_debug_assert(is_p2m1(a2));
1795139c1837SPaolo Bonzini            tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1, msb, 0);
1796139c1837SPaolo Bonzini            break;
1797139c1837SPaolo Bonzini        }
1798139c1837SPaolo Bonzini        i1 = OPC_AND, i2 = OPC_ANDI;
1799139c1837SPaolo Bonzini        goto do_binary;
1800139c1837SPaolo Bonzini    case INDEX_op_nor_i32:
1801139c1837SPaolo Bonzini    case INDEX_op_nor_i64:
1802139c1837SPaolo Bonzini        i1 = OPC_NOR;
1803139c1837SPaolo Bonzini        goto do_binaryv;
1804139c1837SPaolo Bonzini
1805139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1806139c1837SPaolo Bonzini        if (use_mips32_instructions) {
1807139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1808139c1837SPaolo Bonzini            break;
1809139c1837SPaolo Bonzini        }
1810139c1837SPaolo Bonzini        i1 = OPC_MULT, i2 = OPC_MFLO;
1811139c1837SPaolo Bonzini        goto do_hilo1;
1812139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
1813139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1814139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MUH, a0, a1, a2);
1815139c1837SPaolo Bonzini            break;
1816139c1837SPaolo Bonzini        }
1817139c1837SPaolo Bonzini        i1 = OPC_MULT, i2 = OPC_MFHI;
1818139c1837SPaolo Bonzini        goto do_hilo1;
1819139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
1820139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1821139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MUHU, a0, a1, a2);
1822139c1837SPaolo Bonzini            break;
1823139c1837SPaolo Bonzini        }
1824139c1837SPaolo Bonzini        i1 = OPC_MULTU, i2 = OPC_MFHI;
1825139c1837SPaolo Bonzini        goto do_hilo1;
1826139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1827139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1828139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DIV_R6, a0, a1, a2);
1829139c1837SPaolo Bonzini            break;
1830139c1837SPaolo Bonzini        }
1831139c1837SPaolo Bonzini        i1 = OPC_DIV, i2 = OPC_MFLO;
1832139c1837SPaolo Bonzini        goto do_hilo1;
1833139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1834139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1835139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DIVU_R6, a0, a1, a2);
1836139c1837SPaolo Bonzini            break;
1837139c1837SPaolo Bonzini        }
1838139c1837SPaolo Bonzini        i1 = OPC_DIVU, i2 = OPC_MFLO;
1839139c1837SPaolo Bonzini        goto do_hilo1;
1840139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1841139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1842139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MOD, a0, a1, a2);
1843139c1837SPaolo Bonzini            break;
1844139c1837SPaolo Bonzini        }
1845139c1837SPaolo Bonzini        i1 = OPC_DIV, i2 = OPC_MFHI;
1846139c1837SPaolo Bonzini        goto do_hilo1;
1847139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1848139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1849139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_MODU, a0, a1, a2);
1850139c1837SPaolo Bonzini            break;
1851139c1837SPaolo Bonzini        }
1852139c1837SPaolo Bonzini        i1 = OPC_DIVU, i2 = OPC_MFHI;
1853139c1837SPaolo Bonzini        goto do_hilo1;
1854139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1855139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1856139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DMUL, a0, a1, a2);
1857139c1837SPaolo Bonzini            break;
1858139c1837SPaolo Bonzini        }
1859139c1837SPaolo Bonzini        i1 = OPC_DMULT, i2 = OPC_MFLO;
1860139c1837SPaolo Bonzini        goto do_hilo1;
1861139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
1862139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1863139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DMUH, a0, a1, a2);
1864139c1837SPaolo Bonzini            break;
1865139c1837SPaolo Bonzini        }
1866139c1837SPaolo Bonzini        i1 = OPC_DMULT, i2 = OPC_MFHI;
1867139c1837SPaolo Bonzini        goto do_hilo1;
1868139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
1869139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1870139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DMUHU, a0, a1, a2);
1871139c1837SPaolo Bonzini            break;
1872139c1837SPaolo Bonzini        }
1873139c1837SPaolo Bonzini        i1 = OPC_DMULTU, i2 = OPC_MFHI;
1874139c1837SPaolo Bonzini        goto do_hilo1;
1875139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1876139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1877139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DDIV_R6, a0, a1, a2);
1878139c1837SPaolo Bonzini            break;
1879139c1837SPaolo Bonzini        }
1880139c1837SPaolo Bonzini        i1 = OPC_DDIV, i2 = OPC_MFLO;
1881139c1837SPaolo Bonzini        goto do_hilo1;
1882139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1883139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1884139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DDIVU_R6, a0, a1, a2);
1885139c1837SPaolo Bonzini            break;
1886139c1837SPaolo Bonzini        }
1887139c1837SPaolo Bonzini        i1 = OPC_DDIVU, i2 = OPC_MFLO;
1888139c1837SPaolo Bonzini        goto do_hilo1;
1889139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1890139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1891139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DMOD, a0, a1, a2);
1892139c1837SPaolo Bonzini            break;
1893139c1837SPaolo Bonzini        }
1894139c1837SPaolo Bonzini        i1 = OPC_DDIV, i2 = OPC_MFHI;
1895139c1837SPaolo Bonzini        goto do_hilo1;
1896139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1897139c1837SPaolo Bonzini        if (use_mips32r6_instructions) {
1898139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DMODU, a0, a1, a2);
1899139c1837SPaolo Bonzini            break;
1900139c1837SPaolo Bonzini        }
1901139c1837SPaolo Bonzini        i1 = OPC_DDIVU, i2 = OPC_MFHI;
1902139c1837SPaolo Bonzini    do_hilo1:
1903139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i1, 0, a1, a2);
1904139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i2, a0, 0, 0);
1905139c1837SPaolo Bonzini        break;
1906139c1837SPaolo Bonzini
1907139c1837SPaolo Bonzini    case INDEX_op_muls2_i32:
1908139c1837SPaolo Bonzini        i1 = OPC_MULT;
1909139c1837SPaolo Bonzini        goto do_hilo2;
1910139c1837SPaolo Bonzini    case INDEX_op_mulu2_i32:
1911139c1837SPaolo Bonzini        i1 = OPC_MULTU;
1912139c1837SPaolo Bonzini        goto do_hilo2;
1913139c1837SPaolo Bonzini    case INDEX_op_muls2_i64:
1914139c1837SPaolo Bonzini        i1 = OPC_DMULT;
1915139c1837SPaolo Bonzini        goto do_hilo2;
1916139c1837SPaolo Bonzini    case INDEX_op_mulu2_i64:
1917139c1837SPaolo Bonzini        i1 = OPC_DMULTU;
1918139c1837SPaolo Bonzini    do_hilo2:
1919139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i1, 0, a2, args[3]);
1920139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MFLO, a0, 0, 0);
1921139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MFHI, a1, 0, 0);
1922139c1837SPaolo Bonzini        break;
1923139c1837SPaolo Bonzini
1924e0448a8bSRichard Henderson    case INDEX_op_neg_i32:
1925e0448a8bSRichard Henderson        i1 = OPC_SUBU;
1926e0448a8bSRichard Henderson        goto do_unary;
1927e0448a8bSRichard Henderson    case INDEX_op_neg_i64:
1928e0448a8bSRichard Henderson        i1 = OPC_DSUBU;
1929e0448a8bSRichard Henderson        goto do_unary;
1930139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1931139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1932139c1837SPaolo Bonzini        i1 = OPC_NOR;
1933139c1837SPaolo Bonzini        goto do_unary;
1934139c1837SPaolo Bonzini    do_unary:
1935139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i1, a0, TCG_REG_ZERO, a1);
1936139c1837SPaolo Bonzini        break;
1937139c1837SPaolo Bonzini
193827362b7bSRichard Henderson    case INDEX_op_bswap16_i32:
193927362b7bSRichard Henderson    case INDEX_op_bswap16_i64:
194027362b7bSRichard Henderson        tcg_out_bswap16(s, a0, a1, a2);
194127362b7bSRichard Henderson        break;
1942139c1837SPaolo Bonzini    case INDEX_op_bswap32_i32:
19431fce6534SRichard Henderson        tcg_out_bswap32(s, a0, a1, 0);
1944139c1837SPaolo Bonzini        break;
1945139c1837SPaolo Bonzini    case INDEX_op_bswap32_i64:
19461fce6534SRichard Henderson        tcg_out_bswap32(s, a0, a1, a2);
1947139c1837SPaolo Bonzini        break;
1948139c1837SPaolo Bonzini    case INDEX_op_bswap64_i64:
1949139c1837SPaolo Bonzini        tcg_out_bswap64(s, a0, a1);
1950139c1837SPaolo Bonzini        break;
1951139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
1952139c1837SPaolo Bonzini        tcg_out_dsra(s, a0, a1, 32);
1953139c1837SPaolo Bonzini        break;
1954139c1837SPaolo Bonzini
1955139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1956139c1837SPaolo Bonzini        i1 = OPC_SRAV, i2 = OPC_SRA;
1957139c1837SPaolo Bonzini        goto do_shift;
1958139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1959139c1837SPaolo Bonzini        i1 = OPC_SLLV, i2 = OPC_SLL;
1960139c1837SPaolo Bonzini        goto do_shift;
1961139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1962139c1837SPaolo Bonzini        i1 = OPC_SRLV, i2 = OPC_SRL;
1963139c1837SPaolo Bonzini        goto do_shift;
1964139c1837SPaolo Bonzini    case INDEX_op_rotr_i32:
1965139c1837SPaolo Bonzini        i1 = OPC_ROTRV, i2 = OPC_ROTR;
1966139c1837SPaolo Bonzini    do_shift:
1967139c1837SPaolo Bonzini        if (c2) {
1968139c1837SPaolo Bonzini            tcg_out_opc_sa(s, i2, a0, a1, a2);
1969139c1837SPaolo Bonzini            break;
1970139c1837SPaolo Bonzini        }
1971139c1837SPaolo Bonzini    do_shiftv:
1972139c1837SPaolo Bonzini        tcg_out_opc_reg(s, i1, a0, a2, a1);
1973139c1837SPaolo Bonzini        break;
1974139c1837SPaolo Bonzini    case INDEX_op_rotl_i32:
1975139c1837SPaolo Bonzini        if (c2) {
1976139c1837SPaolo Bonzini            tcg_out_opc_sa(s, OPC_ROTR, a0, a1, 32 - a2);
1977139c1837SPaolo Bonzini        } else {
1978139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBU, TCG_TMP0, TCG_REG_ZERO, a2);
1979139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ROTRV, a0, TCG_TMP0, a1);
1980139c1837SPaolo Bonzini        }
1981139c1837SPaolo Bonzini        break;
1982139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1983139c1837SPaolo Bonzini        if (c2) {
1984139c1837SPaolo Bonzini            tcg_out_dsra(s, a0, a1, a2);
1985139c1837SPaolo Bonzini            break;
1986139c1837SPaolo Bonzini        }
1987139c1837SPaolo Bonzini        i1 = OPC_DSRAV;
1988139c1837SPaolo Bonzini        goto do_shiftv;
1989139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1990139c1837SPaolo Bonzini        if (c2) {
1991139c1837SPaolo Bonzini            tcg_out_dsll(s, a0, a1, a2);
1992139c1837SPaolo Bonzini            break;
1993139c1837SPaolo Bonzini        }
1994139c1837SPaolo Bonzini        i1 = OPC_DSLLV;
1995139c1837SPaolo Bonzini        goto do_shiftv;
1996139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1997139c1837SPaolo Bonzini        if (c2) {
1998139c1837SPaolo Bonzini            tcg_out_dsrl(s, a0, a1, a2);
1999139c1837SPaolo Bonzini            break;
2000139c1837SPaolo Bonzini        }
2001139c1837SPaolo Bonzini        i1 = OPC_DSRLV;
2002139c1837SPaolo Bonzini        goto do_shiftv;
2003139c1837SPaolo Bonzini    case INDEX_op_rotr_i64:
2004139c1837SPaolo Bonzini        if (c2) {
2005139c1837SPaolo Bonzini            tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, a2);
2006139c1837SPaolo Bonzini            break;
2007139c1837SPaolo Bonzini        }
2008139c1837SPaolo Bonzini        i1 = OPC_DROTRV;
2009139c1837SPaolo Bonzini        goto do_shiftv;
2010139c1837SPaolo Bonzini    case INDEX_op_rotl_i64:
2011139c1837SPaolo Bonzini        if (c2) {
2012139c1837SPaolo Bonzini            tcg_out_opc_sa64(s, OPC_DROTR, OPC_DROTR32, a0, a1, 64 - a2);
2013139c1837SPaolo Bonzini        } else {
2014139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DSUBU, TCG_TMP0, TCG_REG_ZERO, a2);
2015139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_DROTRV, a0, TCG_TMP0, a1);
2016139c1837SPaolo Bonzini        }
2017139c1837SPaolo Bonzini        break;
2018139c1837SPaolo Bonzini
2019139c1837SPaolo Bonzini    case INDEX_op_clz_i32:
2020139c1837SPaolo Bonzini        tcg_out_clz(s, OPC_CLZ, OPC_CLZ_R6, 32, a0, a1, a2);
2021139c1837SPaolo Bonzini        break;
2022139c1837SPaolo Bonzini    case INDEX_op_clz_i64:
2023139c1837SPaolo Bonzini        tcg_out_clz(s, OPC_DCLZ, OPC_DCLZ_R6, 64, a0, a1, a2);
2024139c1837SPaolo Bonzini        break;
2025139c1837SPaolo Bonzini
2026139c1837SPaolo Bonzini    case INDEX_op_deposit_i32:
2027139c1837SPaolo Bonzini        tcg_out_opc_bf(s, OPC_INS, a0, a2, args[3] + args[4] - 1, args[3]);
2028139c1837SPaolo Bonzini        break;
2029139c1837SPaolo Bonzini    case INDEX_op_deposit_i64:
2030139c1837SPaolo Bonzini        tcg_out_opc_bf64(s, OPC_DINS, OPC_DINSM, OPC_DINSU, a0, a2,
2031139c1837SPaolo Bonzini                         args[3] + args[4] - 1, args[3]);
2032139c1837SPaolo Bonzini        break;
2033139c1837SPaolo Bonzini    case INDEX_op_extract_i32:
2034139c1837SPaolo Bonzini        tcg_out_opc_bf(s, OPC_EXT, a0, a1, args[3] - 1, a2);
2035139c1837SPaolo Bonzini        break;
2036139c1837SPaolo Bonzini    case INDEX_op_extract_i64:
2037139c1837SPaolo Bonzini        tcg_out_opc_bf64(s, OPC_DEXT, OPC_DEXTM, OPC_DEXTU, a0, a1,
2038139c1837SPaolo Bonzini                         args[3] - 1, a2);
2039139c1837SPaolo Bonzini        break;
2040139c1837SPaolo Bonzini
2041139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2042139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2043139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2044139c1837SPaolo Bonzini        break;
2045139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
2046139c1837SPaolo Bonzini        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
2047139c1837SPaolo Bonzini        break;
2048139c1837SPaolo Bonzini
2049139c1837SPaolo Bonzini    case INDEX_op_movcond_i32:
2050139c1837SPaolo Bonzini    case INDEX_op_movcond_i64:
2051139c1837SPaolo Bonzini        tcg_out_movcond(s, args[5], a0, a1, a2, args[3], args[4]);
2052139c1837SPaolo Bonzini        break;
2053139c1837SPaolo Bonzini
2054139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2055139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2056139c1837SPaolo Bonzini        tcg_out_setcond(s, args[3], a0, a1, a2);
2057139c1837SPaolo Bonzini        break;
2058139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
2059139c1837SPaolo Bonzini        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
2060139c1837SPaolo Bonzini        break;
2061139c1837SPaolo Bonzini
2062fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2063fecccfccSRichard Henderson        if (TCG_TARGET_REG_BITS == 32) {
2064eb664d0cSRichard Henderson            tcg_out_qemu_ld(s, a0, 0, a1, a2, args[3], TCG_TYPE_I32);
2065139c1837SPaolo Bonzini            break;
2066fecccfccSRichard Henderson        }
2067fecccfccSRichard Henderson        /* fall through */
2068fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2069fecccfccSRichard Henderson        tcg_out_qemu_ld(s, a0, 0, a1, 0, a2, TCG_TYPE_I32);
2070fecccfccSRichard Henderson        break;
2071fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2072eb664d0cSRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
2073eb664d0cSRichard Henderson            tcg_out_qemu_ld(s, a0, 0, a1, 0, a2, TCG_TYPE_I64);
2074fecccfccSRichard Henderson        } else {
2075eb664d0cSRichard Henderson            tcg_out_qemu_ld(s, a0, a1, a2, 0, args[3], TCG_TYPE_I64);
2076fecccfccSRichard Henderson        }
2077fecccfccSRichard Henderson        break;
2078fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2079fecccfccSRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
2080fecccfccSRichard Henderson            tcg_out_qemu_ld(s, a0, 0, a1, 0, a2, TCG_TYPE_I64);
2081eb664d0cSRichard Henderson        } else {
2082eb664d0cSRichard Henderson            tcg_out_qemu_ld(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64);
2083eb664d0cSRichard Henderson        }
2084139c1837SPaolo Bonzini        break;
2085fecccfccSRichard Henderson
2086fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2087fecccfccSRichard Henderson        if (TCG_TARGET_REG_BITS == 32) {
2088eb664d0cSRichard Henderson            tcg_out_qemu_st(s, a0, 0, a1, a2, args[3], TCG_TYPE_I32);
2089139c1837SPaolo Bonzini            break;
2090fecccfccSRichard Henderson        }
2091fecccfccSRichard Henderson        /* fall through */
2092fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2093fecccfccSRichard Henderson        tcg_out_qemu_st(s, a0, 0, a1, 0, a2, TCG_TYPE_I32);
2094fecccfccSRichard Henderson        break;
2095fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2096eb664d0cSRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
2097eb664d0cSRichard Henderson            tcg_out_qemu_st(s, a0, 0, a1, 0, a2, TCG_TYPE_I64);
2098fecccfccSRichard Henderson        } else {
2099eb664d0cSRichard Henderson            tcg_out_qemu_st(s, a0, a1, a2, 0, args[3], TCG_TYPE_I64);
2100fecccfccSRichard Henderson        }
2101fecccfccSRichard Henderson        break;
2102fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2103fecccfccSRichard Henderson        if (TCG_TARGET_REG_BITS == 64) {
2104fecccfccSRichard Henderson            tcg_out_qemu_st(s, a0, 0, a1, 0, a2, TCG_TYPE_I64);
2105eb664d0cSRichard Henderson        } else {
2106eb664d0cSRichard Henderson            tcg_out_qemu_st(s, a0, a1, a2, args[3], args[4], TCG_TYPE_I64);
2107eb664d0cSRichard Henderson        }
2108139c1837SPaolo Bonzini        break;
2109139c1837SPaolo Bonzini
2110139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2111139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2112139c1837SPaolo Bonzini                        const_args[4], const_args[5], false);
2113139c1837SPaolo Bonzini        break;
2114139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2115139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2116139c1837SPaolo Bonzini                        const_args[4], const_args[5], true);
2117139c1837SPaolo Bonzini        break;
2118139c1837SPaolo Bonzini
2119139c1837SPaolo Bonzini    case INDEX_op_mb:
2120139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2121139c1837SPaolo Bonzini        break;
2122139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2123139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2124139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2125b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2126cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2127678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2128678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2129d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2130d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2131753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2132753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
213352bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
21349ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
21359c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2136b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2137b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2138139c1837SPaolo Bonzini    default:
2139732e89f4SRichard Henderson        g_assert_not_reached();
2140139c1837SPaolo Bonzini    }
2141139c1837SPaolo Bonzini}
2142139c1837SPaolo Bonzini
21430263330bSRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2144139c1837SPaolo Bonzini{
2145139c1837SPaolo Bonzini    switch (op) {
2146139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
21470263330bSRichard Henderson        return C_O0_I1(r);
2148139c1837SPaolo Bonzini
2149139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2150139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2151139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2152139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2153139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2154e0448a8bSRichard Henderson    case INDEX_op_neg_i32:
2155139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2156139c1837SPaolo Bonzini    case INDEX_op_bswap16_i32:
2157139c1837SPaolo Bonzini    case INDEX_op_bswap32_i32:
2158139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2159139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2160139c1837SPaolo Bonzini    case INDEX_op_extract_i32:
2161139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2162139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2163139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2164139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2165139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2166139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2167139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2168e0448a8bSRichard Henderson    case INDEX_op_neg_i64:
2169139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2170139c1837SPaolo Bonzini    case INDEX_op_bswap16_i64:
2171139c1837SPaolo Bonzini    case INDEX_op_bswap32_i64:
2172139c1837SPaolo Bonzini    case INDEX_op_bswap64_i64:
2173139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2174139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2175139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2176139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2177139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
2178139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2179139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2180139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2181139c1837SPaolo Bonzini    case INDEX_op_extract_i64:
21820263330bSRichard Henderson        return C_O1_I1(r, r);
2183139c1837SPaolo Bonzini
2184139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2185139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2186139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2187139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2188139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2189139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2190139c1837SPaolo Bonzini    case INDEX_op_st_i64:
21910263330bSRichard Henderson        return C_O0_I2(rZ, r);
2192139c1837SPaolo Bonzini
2193139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2194139c1837SPaolo Bonzini    case INDEX_op_add_i64:
21950263330bSRichard Henderson        return C_O1_I2(r, r, rJ);
2196139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2197139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
21980263330bSRichard Henderson        return C_O1_I2(r, rZ, rN);
2199139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2200139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2201139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2202139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2203139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2204139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2205139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2206139c1837SPaolo Bonzini    case INDEX_op_nor_i32:
2207139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2208139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2209139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2210139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2211139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2212139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2213139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2214139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2215139c1837SPaolo Bonzini    case INDEX_op_nor_i64:
2216139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
22170263330bSRichard Henderson        return C_O1_I2(r, rZ, rZ);
2218139c1837SPaolo Bonzini    case INDEX_op_muls2_i32:
2219139c1837SPaolo Bonzini    case INDEX_op_mulu2_i32:
2220139c1837SPaolo Bonzini    case INDEX_op_muls2_i64:
2221139c1837SPaolo Bonzini    case INDEX_op_mulu2_i64:
22220263330bSRichard Henderson        return C_O2_I2(r, r, r, r);
2223139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2224139c1837SPaolo Bonzini    case INDEX_op_and_i64:
22250263330bSRichard Henderson        return C_O1_I2(r, r, rIK);
2226139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2227139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2228139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2229139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
22300263330bSRichard Henderson        return C_O1_I2(r, r, rI);
2231139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2232139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2233139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2234139c1837SPaolo Bonzini    case INDEX_op_rotr_i32:
2235139c1837SPaolo Bonzini    case INDEX_op_rotl_i32:
2236139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2237139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2238139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2239139c1837SPaolo Bonzini    case INDEX_op_rotr_i64:
2240139c1837SPaolo Bonzini    case INDEX_op_rotl_i64:
22410263330bSRichard Henderson        return C_O1_I2(r, r, ri);
2242139c1837SPaolo Bonzini    case INDEX_op_clz_i32:
2243139c1837SPaolo Bonzini    case INDEX_op_clz_i64:
22440263330bSRichard Henderson        return C_O1_I2(r, r, rWZ);
2245139c1837SPaolo Bonzini
2246139c1837SPaolo Bonzini    case INDEX_op_deposit_i32:
2247139c1837SPaolo Bonzini    case INDEX_op_deposit_i64:
22480263330bSRichard Henderson        return C_O1_I2(r, 0, rZ);
2249139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2250139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
22510263330bSRichard Henderson        return C_O0_I2(rZ, rZ);
2252139c1837SPaolo Bonzini    case INDEX_op_movcond_i32:
2253139c1837SPaolo Bonzini    case INDEX_op_movcond_i64:
22540263330bSRichard Henderson        return (use_mips32r6_instructions
22550263330bSRichard Henderson                ? C_O1_I4(r, rZ, rZ, rZ, rZ)
22560263330bSRichard Henderson                : C_O1_I4(r, rZ, rZ, rZ, 0));
2257139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2258139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
22590263330bSRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rN, rN);
2260139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
22610263330bSRichard Henderson        return C_O1_I4(r, rZ, rZ, rZ, rZ);
2262139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
22630263330bSRichard Henderson        return C_O0_I4(rZ, rZ, rZ, rZ);
2264139c1837SPaolo Bonzini
2265fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2266fecccfccSRichard Henderson        return C_O1_I1(r, r);
2267fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2268fecccfccSRichard Henderson        return TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r) : C_O1_I2(r, r, r);
2269fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2270fecccfccSRichard Henderson        return C_O0_I2(rZ, r);
2271fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2272fecccfccSRichard Henderson        return TCG_TARGET_REG_BITS == 64 ? C_O0_I2(rZ, r) : C_O0_I3(rZ, r, r);
2273fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2274fecccfccSRichard Henderson        return TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r) : C_O2_I1(r, r, r);
2275fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2276fecccfccSRichard Henderson        return TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r) : C_O2_I2(r, r, r, r);
2277fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2278fecccfccSRichard Henderson        return TCG_TARGET_REG_BITS == 64 ? C_O0_I2(rZ, r) : C_O0_I3(rZ, rZ, r);
2279fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2280f48cc902SRichard Henderson        return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(rZ, r)
2281f48cc902SRichard Henderson                : C_O0_I4(rZ, rZ, r, r));
2282139c1837SPaolo Bonzini
2283139c1837SPaolo Bonzini    default:
22840263330bSRichard Henderson        g_assert_not_reached();
2285139c1837SPaolo Bonzini    }
2286139c1837SPaolo Bonzini}
2287139c1837SPaolo Bonzini
2288139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2289d721cc94SRichard Henderson    TCG_REG_S0,
2290139c1837SPaolo Bonzini    TCG_REG_S1,
2291139c1837SPaolo Bonzini    TCG_REG_S2,
2292139c1837SPaolo Bonzini    TCG_REG_S3,
2293139c1837SPaolo Bonzini    TCG_REG_S4,
2294139c1837SPaolo Bonzini    TCG_REG_S5,
229553c4fa27SRichard Henderson    TCG_REG_S6,       /* used for the tb base (TCG_REG_TB) */
229643b4cd97SRichard Henderson    TCG_REG_S7,       /* used for guest_base */
2297d721cc94SRichard Henderson    TCG_REG_S8,       /* used for the global env (TCG_AREG0) */
2298139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2299139c1837SPaolo Bonzini};
2300139c1837SPaolo Bonzini
2301139c1837SPaolo Bonzini/* The Linux kernel doesn't provide any information about the available
2302139c1837SPaolo Bonzini   instruction set. Probe it using a signal handler. */
2303139c1837SPaolo Bonzini
2304139c1837SPaolo Bonzini
2305139c1837SPaolo Bonzini#ifndef use_movnz_instructions
2306139c1837SPaolo Bonzinibool use_movnz_instructions = false;
2307139c1837SPaolo Bonzini#endif
2308139c1837SPaolo Bonzini
2309139c1837SPaolo Bonzini#ifndef use_mips32_instructions
2310139c1837SPaolo Bonzinibool use_mips32_instructions = false;
2311139c1837SPaolo Bonzini#endif
2312139c1837SPaolo Bonzini
2313139c1837SPaolo Bonzini#ifndef use_mips32r2_instructions
2314139c1837SPaolo Bonzinibool use_mips32r2_instructions = false;
2315139c1837SPaolo Bonzini#endif
2316139c1837SPaolo Bonzini
2317139c1837SPaolo Bonzinistatic volatile sig_atomic_t got_sigill;
2318139c1837SPaolo Bonzini
2319139c1837SPaolo Bonzinistatic void sigill_handler(int signo, siginfo_t *si, void *data)
2320139c1837SPaolo Bonzini{
2321139c1837SPaolo Bonzini    /* Skip the faulty instruction */
2322139c1837SPaolo Bonzini    ucontext_t *uc = (ucontext_t *)data;
2323139c1837SPaolo Bonzini    uc->uc_mcontext.pc += 4;
2324139c1837SPaolo Bonzini
2325139c1837SPaolo Bonzini    got_sigill = 1;
2326139c1837SPaolo Bonzini}
2327139c1837SPaolo Bonzini
2328139c1837SPaolo Bonzinistatic void tcg_target_detect_isa(void)
2329139c1837SPaolo Bonzini{
2330139c1837SPaolo Bonzini    struct sigaction sa_old, sa_new;
2331139c1837SPaolo Bonzini
2332139c1837SPaolo Bonzini    memset(&sa_new, 0, sizeof(sa_new));
2333139c1837SPaolo Bonzini    sa_new.sa_flags = SA_SIGINFO;
2334139c1837SPaolo Bonzini    sa_new.sa_sigaction = sigill_handler;
2335139c1837SPaolo Bonzini    sigaction(SIGILL, &sa_new, &sa_old);
2336139c1837SPaolo Bonzini
2337139c1837SPaolo Bonzini    /* Probe for movn/movz, necessary to implement movcond. */
2338139c1837SPaolo Bonzini#ifndef use_movnz_instructions
2339139c1837SPaolo Bonzini    got_sigill = 0;
2340139c1837SPaolo Bonzini    asm volatile(".set push\n"
2341139c1837SPaolo Bonzini                 ".set mips32\n"
2342139c1837SPaolo Bonzini                 "movn $zero, $zero, $zero\n"
2343139c1837SPaolo Bonzini                 "movz $zero, $zero, $zero\n"
2344139c1837SPaolo Bonzini                 ".set pop\n"
2345139c1837SPaolo Bonzini                 : : : );
2346139c1837SPaolo Bonzini    use_movnz_instructions = !got_sigill;
2347139c1837SPaolo Bonzini#endif
2348139c1837SPaolo Bonzini
2349139c1837SPaolo Bonzini    /* Probe for MIPS32 instructions. As no subsetting is allowed
2350139c1837SPaolo Bonzini       by the specification, it is only necessary to probe for one
2351139c1837SPaolo Bonzini       of the instructions. */
2352139c1837SPaolo Bonzini#ifndef use_mips32_instructions
2353139c1837SPaolo Bonzini    got_sigill = 0;
2354139c1837SPaolo Bonzini    asm volatile(".set push\n"
2355139c1837SPaolo Bonzini                 ".set mips32\n"
2356139c1837SPaolo Bonzini                 "mul $zero, $zero\n"
2357139c1837SPaolo Bonzini                 ".set pop\n"
2358139c1837SPaolo Bonzini                 : : : );
2359139c1837SPaolo Bonzini    use_mips32_instructions = !got_sigill;
2360139c1837SPaolo Bonzini#endif
2361139c1837SPaolo Bonzini
2362139c1837SPaolo Bonzini    /* Probe for MIPS32r2 instructions if MIPS32 instructions are
2363139c1837SPaolo Bonzini       available. As no subsetting is allowed by the specification,
2364139c1837SPaolo Bonzini       it is only necessary to probe for one of the instructions. */
2365139c1837SPaolo Bonzini#ifndef use_mips32r2_instructions
2366139c1837SPaolo Bonzini    if (use_mips32_instructions) {
2367139c1837SPaolo Bonzini        got_sigill = 0;
2368139c1837SPaolo Bonzini        asm volatile(".set push\n"
2369139c1837SPaolo Bonzini                     ".set mips32r2\n"
2370139c1837SPaolo Bonzini                     "seb $zero, $zero\n"
2371139c1837SPaolo Bonzini                     ".set pop\n"
2372139c1837SPaolo Bonzini                     : : : );
2373139c1837SPaolo Bonzini        use_mips32r2_instructions = !got_sigill;
2374139c1837SPaolo Bonzini    }
2375139c1837SPaolo Bonzini#endif
2376139c1837SPaolo Bonzini
2377139c1837SPaolo Bonzini    sigaction(SIGILL, &sa_old, NULL);
2378139c1837SPaolo Bonzini}
2379139c1837SPaolo Bonzini
2380139c1837SPaolo Bonzinistatic tcg_insn_unit *align_code_ptr(TCGContext *s)
2381139c1837SPaolo Bonzini{
2382139c1837SPaolo Bonzini    uintptr_t p = (uintptr_t)s->code_ptr;
2383139c1837SPaolo Bonzini    if (p & 15) {
2384139c1837SPaolo Bonzini        p = (p + 15) & -16;
2385139c1837SPaolo Bonzini        s->code_ptr = (void *)p;
2386139c1837SPaolo Bonzini    }
2387139c1837SPaolo Bonzini    return s->code_ptr;
2388139c1837SPaolo Bonzini}
2389139c1837SPaolo Bonzini
2390139c1837SPaolo Bonzini/* Stack frame parameters.  */
2391139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2392139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2393139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2394139c1837SPaolo Bonzini
2395139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2396139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2397139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2398139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2399139c1837SPaolo Bonzini
2400139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2401139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7fff);
2402139c1837SPaolo Bonzini
2403139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2404139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2405139c1837SPaolo Bonzini{
2406139c1837SPaolo Bonzini    int i;
2407139c1837SPaolo Bonzini
2408139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2409139c1837SPaolo Bonzini
2410139c1837SPaolo Bonzini    /* TB prologue */
2411139c1837SPaolo Bonzini    tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2412139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2413139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2414139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2415139c1837SPaolo Bonzini    }
2416139c1837SPaolo Bonzini
2417e3a650cdSRichard Henderson    if (!tcg_use_softmmu && guest_base != (int16_t)guest_base) {
241848c12ba7SRichard Henderson        /*
241948c12ba7SRichard Henderson         * The function call abi for n32 and n64 will have loaded $25 (t9)
242048c12ba7SRichard Henderson         * with the address of the prologue, so we can use that instead
242148c12ba7SRichard Henderson         * of TCG_REG_TB.
242248c12ba7SRichard Henderson         */
242348c12ba7SRichard Henderson#if TCG_TARGET_REG_BITS == 64 && !defined(__mips_abicalls)
242448c12ba7SRichard Henderson# error "Unknown mips abi"
242548c12ba7SRichard Henderson#endif
242648c12ba7SRichard Henderson        tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base,
242748c12ba7SRichard Henderson                         TCG_TARGET_REG_BITS == 64 ? TCG_REG_T9 : 0);
2428139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2429139c1837SPaolo Bonzini    }
243048c12ba7SRichard Henderson
243153c4fa27SRichard Henderson    if (TCG_TARGET_REG_BITS == 64) {
243253c4fa27SRichard Henderson        tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]);
243353c4fa27SRichard Henderson    }
2434139c1837SPaolo Bonzini
2435139c1837SPaolo Bonzini    /* Call generated code */
2436139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0);
2437139c1837SPaolo Bonzini    /* delay slot */
2438139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2439139c1837SPaolo Bonzini
2440139c1837SPaolo Bonzini    /*
2441139c1837SPaolo Bonzini     * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2442139c1837SPaolo Bonzini     * and fall through to the rest of the epilogue.
2443139c1837SPaolo Bonzini     */
2444c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2445139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_V0, TCG_REG_ZERO);
2446139c1837SPaolo Bonzini
2447139c1837SPaolo Bonzini    /* TB epilogue */
2448df5af130SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2449139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2450139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2451139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2452139c1837SPaolo Bonzini    }
2453139c1837SPaolo Bonzini
2454139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2455139c1837SPaolo Bonzini    /* delay slot */
2456139c1837SPaolo Bonzini    tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2457139c1837SPaolo Bonzini
2458139c1837SPaolo Bonzini    if (use_mips32r2_instructions) {
2459139c1837SPaolo Bonzini        return;
2460139c1837SPaolo Bonzini    }
2461139c1837SPaolo Bonzini
2462139c1837SPaolo Bonzini    /* Bswap subroutines: Input in TCG_TMP0, output in TCG_TMP3;
2463139c1837SPaolo Bonzini       clobbers TCG_TMP1, TCG_TMP2.  */
2464139c1837SPaolo Bonzini
2465139c1837SPaolo Bonzini    /*
2466139c1837SPaolo Bonzini     * bswap32 -- 32-bit swap (signed result for mips64).  a0 = abcd.
2467139c1837SPaolo Bonzini     */
2468df5af130SRichard Henderson    bswap32_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2469139c1837SPaolo Bonzini    /* t3 = (ssss)d000 */
2470139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP3, TCG_TMP0, 24);
2471139c1837SPaolo Bonzini    /* t1 = 000a */
2472139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 24);
2473139c1837SPaolo Bonzini    /* t2 = 00c0 */
2474139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2475139c1837SPaolo Bonzini    /* t3 = d00a */
2476139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2477139c1837SPaolo Bonzini    /* t1 = 0abc */
2478139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2479139c1837SPaolo Bonzini    /* t2 = 0c00 */
2480139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2481139c1837SPaolo Bonzini    /* t1 = 00b0 */
2482139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2483139c1837SPaolo Bonzini    /* t3 = dc0a */
2484139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2485139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2486139c1837SPaolo Bonzini    /* t3 = dcba -- delay slot */
2487139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2488139c1837SPaolo Bonzini
2489139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32) {
2490139c1837SPaolo Bonzini        return;
2491139c1837SPaolo Bonzini    }
2492139c1837SPaolo Bonzini
2493139c1837SPaolo Bonzini    /*
2494139c1837SPaolo Bonzini     * bswap32u -- unsigned 32-bit swap.  a0 = ....abcd.
2495139c1837SPaolo Bonzini     */
2496df5af130SRichard Henderson    bswap32u_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2497139c1837SPaolo Bonzini    /* t1 = (0000)000d */
2498139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP0, 0xff);
2499139c1837SPaolo Bonzini    /* t3 = 000a */
2500139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP3, TCG_TMP0, 24);
2501139c1837SPaolo Bonzini    /* t1 = (0000)d000 */
2502139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2503139c1837SPaolo Bonzini    /* t2 = 00c0 */
2504139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2505139c1837SPaolo Bonzini    /* t3 = d00a */
2506139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2507139c1837SPaolo Bonzini    /* t1 = 0abc */
2508139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SRL, TCG_TMP1, TCG_TMP0, 8);
2509139c1837SPaolo Bonzini    /* t2 = 0c00 */
2510139c1837SPaolo Bonzini    tcg_out_opc_sa(s, OPC_SLL, TCG_TMP2, TCG_TMP2, 8);
2511139c1837SPaolo Bonzini    /* t1 = 00b0 */
2512139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2513139c1837SPaolo Bonzini    /* t3 = dc0a */
2514139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2515139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2516139c1837SPaolo Bonzini    /* t3 = dcba -- delay slot */
2517139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2518139c1837SPaolo Bonzini
2519139c1837SPaolo Bonzini    /*
2520139c1837SPaolo Bonzini     * bswap64 -- 64-bit swap.  a0 = abcdefgh
2521139c1837SPaolo Bonzini     */
2522df5af130SRichard Henderson    bswap64_addr = tcg_splitwx_to_rx(align_code_ptr(s));
2523139c1837SPaolo Bonzini    /* t3 = h0000000 */
2524139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP3, TCG_TMP0, 56);
2525139c1837SPaolo Bonzini    /* t1 = 0000000a */
2526139c1837SPaolo Bonzini    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 56);
2527139c1837SPaolo Bonzini
2528139c1837SPaolo Bonzini    /* t2 = 000000g0 */
2529139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP0, 0xff00);
2530139c1837SPaolo Bonzini    /* t3 = h000000a */
2531139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2532139c1837SPaolo Bonzini    /* t1 = 00000abc */
2533139c1837SPaolo Bonzini    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 40);
2534139c1837SPaolo Bonzini    /* t2 = 0g000000 */
2535139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2536139c1837SPaolo Bonzini    /* t1 = 000000b0 */
2537139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2538139c1837SPaolo Bonzini
2539139c1837SPaolo Bonzini    /* t3 = hg00000a */
2540139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2541139c1837SPaolo Bonzini    /* t2 = 0000abcd */
2542139c1837SPaolo Bonzini    tcg_out_dsrl(s, TCG_TMP2, TCG_TMP0, 32);
2543139c1837SPaolo Bonzini    /* t3 = hg0000ba */
2544139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2545139c1837SPaolo Bonzini
2546139c1837SPaolo Bonzini    /* t1 = 000000c0 */
2547139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP2, 0xff00);
2548139c1837SPaolo Bonzini    /* t2 = 0000000d */
2549139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP2, 0x00ff);
2550139c1837SPaolo Bonzini    /* t1 = 00000c00 */
2551139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 8);
2552139c1837SPaolo Bonzini    /* t2 = 0000d000 */
2553139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 24);
2554139c1837SPaolo Bonzini
2555139c1837SPaolo Bonzini    /* t3 = hg000cba */
2556139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2557139c1837SPaolo Bonzini    /* t1 = 00abcdef */
2558139c1837SPaolo Bonzini    tcg_out_dsrl(s, TCG_TMP1, TCG_TMP0, 16);
2559139c1837SPaolo Bonzini    /* t3 = hg00dcba */
2560139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2561139c1837SPaolo Bonzini
2562139c1837SPaolo Bonzini    /* t2 = 0000000f */
2563139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP2, TCG_TMP1, 0x00ff);
2564139c1837SPaolo Bonzini    /* t1 = 000000e0 */
2565139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, TCG_TMP1, TCG_TMP1, 0xff00);
2566139c1837SPaolo Bonzini    /* t2 = 00f00000 */
2567139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP2, TCG_TMP2, 40);
2568139c1837SPaolo Bonzini    /* t1 = 000e0000 */
2569139c1837SPaolo Bonzini    tcg_out_dsll(s, TCG_TMP1, TCG_TMP1, 24);
2570139c1837SPaolo Bonzini
2571139c1837SPaolo Bonzini    /* t3 = hgf0dcba */
2572139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP2);
2573139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
2574139c1837SPaolo Bonzini    /* t3 = hgfedcba -- delay slot */
2575139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_OR, TCG_TMP3, TCG_TMP3, TCG_TMP1);
2576139c1837SPaolo Bonzini}
2577139c1837SPaolo Bonzini
25789358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
25799358fbbfSRichard Henderson{
25809358fbbfSRichard Henderson    /* nothing to do */
25819358fbbfSRichard Henderson}
25829358fbbfSRichard Henderson
2583139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2584139c1837SPaolo Bonzini{
2585139c1837SPaolo Bonzini    tcg_target_detect_isa();
2586139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2587139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64) {
2588139c1837SPaolo Bonzini        tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2589139c1837SPaolo Bonzini    }
2590139c1837SPaolo Bonzini
2591139c1837SPaolo Bonzini    tcg_target_call_clobber_regs = 0;
2592139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V0);
2593139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_V1);
2594139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A0);
2595139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A1);
2596139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A2);
2597139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_A3);
2598139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T0);
2599139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T1);
2600139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T2);
2601139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T3);
2602139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T4);
2603139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T5);
2604139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T6);
2605139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T7);
2606139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T8);
2607139c1837SPaolo Bonzini    tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_T9);
2608139c1837SPaolo Bonzini
2609139c1837SPaolo Bonzini    s->reserved_regs = 0;
2610139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO); /* zero register */
2611139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K0);   /* kernel use only */
2612139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_K1);   /* kernel use only */
2613139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_TMP0);     /* internal use */
2614139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_TMP1);     /* internal use */
2615139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_TMP2);     /* internal use */
2616139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_TMP3);     /* internal use */
2617139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);   /* return address */
2618139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);   /* stack pointer */
2619139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);   /* global pointer */
262053c4fa27SRichard Henderson    if (TCG_TARGET_REG_BITS == 64) {
262153c4fa27SRichard Henderson        tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); /* tc->tc_ptr */
262253c4fa27SRichard Henderson    }
2623139c1837SPaolo Bonzini}
2624139c1837SPaolo Bonzini
2625139c1837SPaolo Bonzinitypedef struct {
2626139c1837SPaolo Bonzini    DebugFrameHeader h;
2627139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2628139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2629139c1837SPaolo Bonzini} DebugFrame;
2630139c1837SPaolo Bonzini
2631139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_MIPS
2632139c1837SPaolo Bonzini/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
2633139c1837SPaolo Bonzini   which is good because they're really quite complicated for MIPS.  */
2634139c1837SPaolo Bonzini
2635139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2636139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2637139c1837SPaolo Bonzini    .h.cie.id = -1,
2638139c1837SPaolo Bonzini    .h.cie.version = 1,
2639139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2640139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2641139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2642139c1837SPaolo Bonzini
2643139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2644139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2645139c1837SPaolo Bonzini
2646139c1837SPaolo Bonzini    .fde_def_cfa = {
2647139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2648139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2649139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2650139c1837SPaolo Bonzini    },
2651139c1837SPaolo Bonzini    .fde_reg_ofs = {
2652139c1837SPaolo Bonzini        0x80 + 16, 9,                   /* DW_CFA_offset, s0, -72 */
2653139c1837SPaolo Bonzini        0x80 + 17, 8,                   /* DW_CFA_offset, s2, -64 */
2654139c1837SPaolo Bonzini        0x80 + 18, 7,                   /* DW_CFA_offset, s3, -56 */
2655139c1837SPaolo Bonzini        0x80 + 19, 6,                   /* DW_CFA_offset, s4, -48 */
2656139c1837SPaolo Bonzini        0x80 + 20, 5,                   /* DW_CFA_offset, s5, -40 */
2657139c1837SPaolo Bonzini        0x80 + 21, 4,                   /* DW_CFA_offset, s6, -32 */
2658139c1837SPaolo Bonzini        0x80 + 22, 3,                   /* DW_CFA_offset, s7, -24 */
2659139c1837SPaolo Bonzini        0x80 + 30, 2,                   /* DW_CFA_offset, s8, -16 */
2660139c1837SPaolo Bonzini        0x80 + 31, 1,                   /* DW_CFA_offset, ra,  -8 */
2661139c1837SPaolo Bonzini    }
2662139c1837SPaolo Bonzini};
2663139c1837SPaolo Bonzini
2664755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2665139c1837SPaolo Bonzini{
2666139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2667139c1837SPaolo Bonzini}
2668