]> git.proxmox.com Git - mirror_qemu.git/blame - target-mips/translate.c
virtio-9p: Add P9_TREMOVE support.
[mirror_qemu.git] / target-mips / translate.c
CommitLineData
6af0bf9c
FB
1/*
2 * MIPS32 emulation for qemu: main translation routines.
5fafdf24 3 *
6af0bf9c 4 * Copyright (c) 2004-2005 Jocelyn Mayer
6ea83fed 5 * Copyright (c) 2006 Marius Groeger (FPU operations)
bb8a53ad 6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
9da53be7 7 * Copyright (c) 2009 CodeSourcery (MIPS16 support)
6af0bf9c
FB
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
8167ee88 20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
6af0bf9c
FB
21 */
22
23#include <stdarg.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <inttypes.h>
28
29#include "cpu.h"
30#include "exec-all.h"
31#include "disas.h"
57fec1fe 32#include "tcg-op.h"
ca10f867 33#include "qemu-common.h"
6af0bf9c 34
a7812ae4
PB
35#include "helper.h"
36#define GEN_HELPER 1
37#include "helper.h"
38
eeef26cd 39//#define MIPS_DEBUG_DISAS
c570fd16 40//#define MIPS_DEBUG_SIGN_EXTENSIONS
6af0bf9c 41
7a387fff
TS
42/* MIPS major opcodes */
43#define MASK_OP_MAJOR(op) (op & (0x3F << 26))
e37e863f
FB
44
45enum {
46 /* indirect opcode tables */
7a387fff
TS
47 OPC_SPECIAL = (0x00 << 26),
48 OPC_REGIMM = (0x01 << 26),
49 OPC_CP0 = (0x10 << 26),
50 OPC_CP1 = (0x11 << 26),
51 OPC_CP2 = (0x12 << 26),
52 OPC_CP3 = (0x13 << 26),
53 OPC_SPECIAL2 = (0x1C << 26),
54 OPC_SPECIAL3 = (0x1F << 26),
e37e863f 55 /* arithmetic with immediate */
7a387fff
TS
56 OPC_ADDI = (0x08 << 26),
57 OPC_ADDIU = (0x09 << 26),
58 OPC_SLTI = (0x0A << 26),
59 OPC_SLTIU = (0x0B << 26),
324d9e32 60 /* logic with immediate */
7a387fff
TS
61 OPC_ANDI = (0x0C << 26),
62 OPC_ORI = (0x0D << 26),
63 OPC_XORI = (0x0E << 26),
64 OPC_LUI = (0x0F << 26),
324d9e32 65 /* arithmetic with immediate */
7a387fff
TS
66 OPC_DADDI = (0x18 << 26),
67 OPC_DADDIU = (0x19 << 26),
e37e863f 68 /* Jump and branches */
7a387fff
TS
69 OPC_J = (0x02 << 26),
70 OPC_JAL = (0x03 << 26),
71 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
72 OPC_BEQL = (0x14 << 26),
73 OPC_BNE = (0x05 << 26),
74 OPC_BNEL = (0x15 << 26),
75 OPC_BLEZ = (0x06 << 26),
76 OPC_BLEZL = (0x16 << 26),
77 OPC_BGTZ = (0x07 << 26),
78 OPC_BGTZL = (0x17 << 26),
79 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
e37e863f 80 /* Load and stores */
7a387fff
TS
81 OPC_LDL = (0x1A << 26),
82 OPC_LDR = (0x1B << 26),
83 OPC_LB = (0x20 << 26),
84 OPC_LH = (0x21 << 26),
85 OPC_LWL = (0x22 << 26),
86 OPC_LW = (0x23 << 26),
364d4831 87 OPC_LWPC = OPC_LW | 0x5,
7a387fff
TS
88 OPC_LBU = (0x24 << 26),
89 OPC_LHU = (0x25 << 26),
90 OPC_LWR = (0x26 << 26),
91 OPC_LWU = (0x27 << 26),
92 OPC_SB = (0x28 << 26),
93 OPC_SH = (0x29 << 26),
94 OPC_SWL = (0x2A << 26),
95 OPC_SW = (0x2B << 26),
96 OPC_SDL = (0x2C << 26),
97 OPC_SDR = (0x2D << 26),
98 OPC_SWR = (0x2E << 26),
99 OPC_LL = (0x30 << 26),
100 OPC_LLD = (0x34 << 26),
101 OPC_LD = (0x37 << 26),
364d4831 102 OPC_LDPC = OPC_LD | 0x5,
7a387fff
TS
103 OPC_SC = (0x38 << 26),
104 OPC_SCD = (0x3C << 26),
105 OPC_SD = (0x3F << 26),
e37e863f 106 /* Floating point load/store */
7a387fff
TS
107 OPC_LWC1 = (0x31 << 26),
108 OPC_LWC2 = (0x32 << 26),
109 OPC_LDC1 = (0x35 << 26),
110 OPC_LDC2 = (0x36 << 26),
111 OPC_SWC1 = (0x39 << 26),
112 OPC_SWC2 = (0x3A << 26),
113 OPC_SDC1 = (0x3D << 26),
114 OPC_SDC2 = (0x3E << 26),
115 /* MDMX ASE specific */
116 OPC_MDMX = (0x1E << 26),
e37e863f 117 /* Cache and prefetch */
7a387fff
TS
118 OPC_CACHE = (0x2F << 26),
119 OPC_PREF = (0x33 << 26),
120 /* Reserved major opcode */
121 OPC_MAJOR3B_RESERVED = (0x3B << 26),
e37e863f
FB
122};
123
124/* MIPS special opcodes */
7a387fff
TS
125#define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
126
e37e863f
FB
127enum {
128 /* Shifts */
7a387fff 129 OPC_SLL = 0x00 | OPC_SPECIAL,
e37e863f
FB
130 /* NOP is SLL r0, r0, 0 */
131 /* SSNOP is SLL r0, r0, 1 */
7a387fff
TS
132 /* EHB is SLL r0, r0, 3 */
133 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
ea63e2c3 134 OPC_ROTR = OPC_SRL | (1 << 21),
7a387fff
TS
135 OPC_SRA = 0x03 | OPC_SPECIAL,
136 OPC_SLLV = 0x04 | OPC_SPECIAL,
e189e748 137 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
ea63e2c3 138 OPC_ROTRV = OPC_SRLV | (1 << 6),
7a387fff
TS
139 OPC_SRAV = 0x07 | OPC_SPECIAL,
140 OPC_DSLLV = 0x14 | OPC_SPECIAL,
141 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
ea63e2c3 142 OPC_DROTRV = OPC_DSRLV | (1 << 6),
7a387fff
TS
143 OPC_DSRAV = 0x17 | OPC_SPECIAL,
144 OPC_DSLL = 0x38 | OPC_SPECIAL,
145 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
ea63e2c3 146 OPC_DROTR = OPC_DSRL | (1 << 21),
7a387fff
TS
147 OPC_DSRA = 0x3B | OPC_SPECIAL,
148 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
149 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
ea63e2c3 150 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
7a387fff 151 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
e37e863f 152 /* Multiplication / division */
7a387fff
TS
153 OPC_MULT = 0x18 | OPC_SPECIAL,
154 OPC_MULTU = 0x19 | OPC_SPECIAL,
155 OPC_DIV = 0x1A | OPC_SPECIAL,
156 OPC_DIVU = 0x1B | OPC_SPECIAL,
157 OPC_DMULT = 0x1C | OPC_SPECIAL,
158 OPC_DMULTU = 0x1D | OPC_SPECIAL,
159 OPC_DDIV = 0x1E | OPC_SPECIAL,
160 OPC_DDIVU = 0x1F | OPC_SPECIAL,
e37e863f 161 /* 2 registers arithmetic / logic */
7a387fff
TS
162 OPC_ADD = 0x20 | OPC_SPECIAL,
163 OPC_ADDU = 0x21 | OPC_SPECIAL,
164 OPC_SUB = 0x22 | OPC_SPECIAL,
165 OPC_SUBU = 0x23 | OPC_SPECIAL,
166 OPC_AND = 0x24 | OPC_SPECIAL,
167 OPC_OR = 0x25 | OPC_SPECIAL,
168 OPC_XOR = 0x26 | OPC_SPECIAL,
169 OPC_NOR = 0x27 | OPC_SPECIAL,
170 OPC_SLT = 0x2A | OPC_SPECIAL,
171 OPC_SLTU = 0x2B | OPC_SPECIAL,
172 OPC_DADD = 0x2C | OPC_SPECIAL,
173 OPC_DADDU = 0x2D | OPC_SPECIAL,
174 OPC_DSUB = 0x2E | OPC_SPECIAL,
175 OPC_DSUBU = 0x2F | OPC_SPECIAL,
e37e863f 176 /* Jumps */
7a387fff
TS
177 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
178 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
364d4831 179 OPC_JALRC = OPC_JALR | (0x5 << 6),
e37e863f 180 /* Traps */
7a387fff
TS
181 OPC_TGE = 0x30 | OPC_SPECIAL,
182 OPC_TGEU = 0x31 | OPC_SPECIAL,
183 OPC_TLT = 0x32 | OPC_SPECIAL,
184 OPC_TLTU = 0x33 | OPC_SPECIAL,
185 OPC_TEQ = 0x34 | OPC_SPECIAL,
186 OPC_TNE = 0x36 | OPC_SPECIAL,
e37e863f 187 /* HI / LO registers load & stores */
7a387fff
TS
188 OPC_MFHI = 0x10 | OPC_SPECIAL,
189 OPC_MTHI = 0x11 | OPC_SPECIAL,
190 OPC_MFLO = 0x12 | OPC_SPECIAL,
191 OPC_MTLO = 0x13 | OPC_SPECIAL,
e37e863f 192 /* Conditional moves */
7a387fff
TS
193 OPC_MOVZ = 0x0A | OPC_SPECIAL,
194 OPC_MOVN = 0x0B | OPC_SPECIAL,
e37e863f 195
7a387fff 196 OPC_MOVCI = 0x01 | OPC_SPECIAL,
e37e863f
FB
197
198 /* Special */
a0d700e4 199 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
7a387fff
TS
200 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
201 OPC_BREAK = 0x0D | OPC_SPECIAL,
a0d700e4 202 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
7a387fff
TS
203 OPC_SYNC = 0x0F | OPC_SPECIAL,
204
205 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
206 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
207 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
208 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
209 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
210 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
211 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
212};
213
e9c71dd1
TS
214/* Multiplication variants of the vr54xx. */
215#define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
216
217enum {
218 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
219 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
220 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
221 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
222 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
223 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
224 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
225 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
226 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
227 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
228 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
229 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
230 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
231 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
232};
233
7a387fff
TS
234/* REGIMM (rt field) opcodes */
235#define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
236
237enum {
238 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
239 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
240 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
241 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
242 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
243 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
244 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
245 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
246 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
247 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
248 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
249 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
250 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
251 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
252 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
e37e863f
FB
253};
254
7a387fff
TS
255/* Special2 opcodes */
256#define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
257
e37e863f 258enum {
7a387fff
TS
259 /* Multiply & xxx operations */
260 OPC_MADD = 0x00 | OPC_SPECIAL2,
261 OPC_MADDU = 0x01 | OPC_SPECIAL2,
262 OPC_MUL = 0x02 | OPC_SPECIAL2,
263 OPC_MSUB = 0x04 | OPC_SPECIAL2,
264 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
e37e863f 265 /* Misc */
7a387fff
TS
266 OPC_CLZ = 0x20 | OPC_SPECIAL2,
267 OPC_CLO = 0x21 | OPC_SPECIAL2,
268 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
269 OPC_DCLO = 0x25 | OPC_SPECIAL2,
e37e863f 270 /* Special */
7a387fff
TS
271 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
272};
273
274/* Special3 opcodes */
275#define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
276
277enum {
278 OPC_EXT = 0x00 | OPC_SPECIAL3,
279 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
280 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
281 OPC_DEXT = 0x03 | OPC_SPECIAL3,
282 OPC_INS = 0x04 | OPC_SPECIAL3,
283 OPC_DINSM = 0x05 | OPC_SPECIAL3,
284 OPC_DINSU = 0x06 | OPC_SPECIAL3,
285 OPC_DINS = 0x07 | OPC_SPECIAL3,
ead9360e
TS
286 OPC_FORK = 0x08 | OPC_SPECIAL3,
287 OPC_YIELD = 0x09 | OPC_SPECIAL3,
7a387fff
TS
288 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
289 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
290 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
e37e863f
FB
291};
292
7a387fff
TS
293/* BSHFL opcodes */
294#define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
295
e37e863f 296enum {
7a387fff
TS
297 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
298 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
299 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
e37e863f
FB
300};
301
7a387fff
TS
302/* DBSHFL opcodes */
303#define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
304
e37e863f 305enum {
7a387fff
TS
306 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
307 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
e37e863f
FB
308};
309
7a387fff
TS
310/* Coprocessor 0 (rs field) */
311#define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
312
6ea83fed 313enum {
7a387fff
TS
314 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
315 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
316 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
317 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
ead9360e 318 OPC_MFTR = (0x08 << 21) | OPC_CP0,
7a387fff
TS
319 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
320 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
ead9360e 321 OPC_MTTR = (0x0C << 21) | OPC_CP0,
7a387fff
TS
322 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
323 OPC_C0 = (0x10 << 21) | OPC_CP0,
324 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
325 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
6ea83fed 326};
7a387fff
TS
327
328/* MFMC0 opcodes */
b48cfdff 329#define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
7a387fff
TS
330
331enum {
ead9360e
TS
332 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
333 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
334 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
335 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
7a387fff
TS
336 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
337 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
338};
339
340/* Coprocessor 0 (with rs == C0) */
341#define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
342
343enum {
344 OPC_TLBR = 0x01 | OPC_C0,
345 OPC_TLBWI = 0x02 | OPC_C0,
346 OPC_TLBWR = 0x06 | OPC_C0,
347 OPC_TLBP = 0x08 | OPC_C0,
348 OPC_RFE = 0x10 | OPC_C0,
349 OPC_ERET = 0x18 | OPC_C0,
350 OPC_DERET = 0x1F | OPC_C0,
351 OPC_WAIT = 0x20 | OPC_C0,
352};
353
354/* Coprocessor 1 (rs field) */
355#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
356
357enum {
358 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
359 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
360 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
5a5012ec 361 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
7a387fff
TS
362 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
363 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
364 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
5a5012ec 365 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
7a387fff 366 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
5a5012ec
TS
367 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
368 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
7a387fff
TS
369 OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
370 OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
371 OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
372 OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
373 OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
374 OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
5a5012ec 375 OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
7a387fff
TS
376};
377
5a5012ec
TS
378#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
379#define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
380
7a387fff
TS
381enum {
382 OPC_BC1F = (0x00 << 16) | OPC_BC1,
383 OPC_BC1T = (0x01 << 16) | OPC_BC1,
384 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
385 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
386};
387
5a5012ec
TS
388enum {
389 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
390 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
391};
392
393enum {
394 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
395 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
396};
7a387fff
TS
397
398#define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
e0c84da7
TS
399
400enum {
401 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
402 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
403 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
404 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
405 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
406 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
407 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
408 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
409 OPC_BC2 = (0x08 << 21) | OPC_CP2,
410};
411
412#define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
413
414enum {
415 OPC_LWXC1 = 0x00 | OPC_CP3,
416 OPC_LDXC1 = 0x01 | OPC_CP3,
417 OPC_LUXC1 = 0x05 | OPC_CP3,
418 OPC_SWXC1 = 0x08 | OPC_CP3,
419 OPC_SDXC1 = 0x09 | OPC_CP3,
420 OPC_SUXC1 = 0x0D | OPC_CP3,
421 OPC_PREFX = 0x0F | OPC_CP3,
422 OPC_ALNV_PS = 0x1E | OPC_CP3,
423 OPC_MADD_S = 0x20 | OPC_CP3,
424 OPC_MADD_D = 0x21 | OPC_CP3,
425 OPC_MADD_PS = 0x26 | OPC_CP3,
426 OPC_MSUB_S = 0x28 | OPC_CP3,
427 OPC_MSUB_D = 0x29 | OPC_CP3,
428 OPC_MSUB_PS = 0x2E | OPC_CP3,
429 OPC_NMADD_S = 0x30 | OPC_CP3,
fbcc6828 430 OPC_NMADD_D = 0x31 | OPC_CP3,
e0c84da7
TS
431 OPC_NMADD_PS= 0x36 | OPC_CP3,
432 OPC_NMSUB_S = 0x38 | OPC_CP3,
433 OPC_NMSUB_D = 0x39 | OPC_CP3,
434 OPC_NMSUB_PS= 0x3E | OPC_CP3,
435};
436
39454628 437/* global register indices */
a7812ae4
PB
438static TCGv_ptr cpu_env;
439static TCGv cpu_gpr[32], cpu_PC;
4b2eb8d2 440static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
41db4607
AJ
441static TCGv cpu_dspctrl, btarget, bcond;
442static TCGv_i32 hflags;
a7812ae4 443static TCGv_i32 fpu_fcr0, fpu_fcr31;
aa0bf00b 444
1a7ff922
PB
445static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
446
2e70f6ef
PB
447#include "gen-icount.h"
448
a7812ae4
PB
449#define gen_helper_0i(name, arg) do { \
450 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
451 gen_helper_##name(helper_tmp); \
452 tcg_temp_free_i32(helper_tmp); \
453 } while(0)
be24bb4f 454
a7812ae4
PB
455#define gen_helper_1i(name, arg1, arg2) do { \
456 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
457 gen_helper_##name(arg1, helper_tmp); \
458 tcg_temp_free_i32(helper_tmp); \
459 } while(0)
be24bb4f 460
a7812ae4
PB
461#define gen_helper_2i(name, arg1, arg2, arg3) do { \
462 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
463 gen_helper_##name(arg1, arg2, helper_tmp); \
464 tcg_temp_free_i32(helper_tmp); \
465 } while(0)
be24bb4f 466
a7812ae4
PB
467#define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
468 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
469 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
470 tcg_temp_free_i32(helper_tmp); \
471 } while(0)
c239529e 472
8e9ade68
TS
473typedef struct DisasContext {
474 struct TranslationBlock *tb;
475 target_ulong pc, saved_pc;
476 uint32_t opcode;
7b270ef2 477 int singlestep_enabled;
8e9ade68
TS
478 /* Routine used to access memory */
479 int mem_idx;
480 uint32_t hflags, saved_hflags;
481 int bstate;
482 target_ulong btarget;
483} DisasContext;
484
485enum {
486 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
d077b6f7 487 * exception condition */
8e9ade68
TS
488 BS_STOP = 1, /* We want to stop translation for any reason */
489 BS_BRANCH = 2, /* We reached a branch condition */
490 BS_EXCP = 3, /* We reached an exception condition */
491};
492
493static const char *regnames[] =
6af0bf9c
FB
494 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
495 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
496 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
497 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
498
4b2eb8d2
TS
499static const char *regnames_HI[] =
500 { "HI0", "HI1", "HI2", "HI3", };
501
502static const char *regnames_LO[] =
503 { "LO0", "LO1", "LO2", "LO3", };
504
505static const char *regnames_ACX[] =
506 { "ACX0", "ACX1", "ACX2", "ACX3", };
507
8e9ade68
TS
508static const char *fregnames[] =
509 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
510 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
511 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
512 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
958fb4a9 513
8e9ade68 514#ifdef MIPS_DEBUG_DISAS
001faf32 515#define MIPS_DEBUG(fmt, ...) \
93fcfe39
AL
516 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
517 TARGET_FMT_lx ": %08x " fmt "\n", \
001faf32 518 ctx->pc, ctx->opcode , ## __VA_ARGS__)
93fcfe39 519#define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
8e9ade68 520#else
001faf32 521#define MIPS_DEBUG(fmt, ...) do { } while(0)
d12d51d5 522#define LOG_DISAS(...) do { } while (0)
8e9ade68 523#endif
958fb4a9 524
8e9ade68
TS
525#define MIPS_INVAL(op) \
526do { \
527 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
528 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
529} while (0)
ead9360e 530
8e9ade68
TS
531/* General purpose registers moves. */
532static inline void gen_load_gpr (TCGv t, int reg)
aaa9128a 533{
8e9ade68
TS
534 if (reg == 0)
535 tcg_gen_movi_tl(t, 0);
536 else
4b2eb8d2 537 tcg_gen_mov_tl(t, cpu_gpr[reg]);
aaa9128a
TS
538}
539
8e9ade68 540static inline void gen_store_gpr (TCGv t, int reg)
aaa9128a 541{
8e9ade68 542 if (reg != 0)
4b2eb8d2 543 tcg_gen_mov_tl(cpu_gpr[reg], t);
aaa9128a
TS
544}
545
b10fa3c9 546/* Moves to/from ACX register. */
4b2eb8d2 547static inline void gen_load_ACX (TCGv t, int reg)
893f9865 548{
4b2eb8d2 549 tcg_gen_mov_tl(t, cpu_ACX[reg]);
893f9865
TS
550}
551
4b2eb8d2 552static inline void gen_store_ACX (TCGv t, int reg)
893f9865 553{
4b2eb8d2 554 tcg_gen_mov_tl(cpu_ACX[reg], t);
893f9865
TS
555}
556
8e9ade68 557/* Moves to/from shadow registers. */
be24bb4f 558static inline void gen_load_srsgpr (int from, int to)
aaa9128a 559{
d9bea114 560 TCGv t0 = tcg_temp_new();
be24bb4f
TS
561
562 if (from == 0)
d9bea114 563 tcg_gen_movi_tl(t0, 0);
8e9ade68 564 else {
d9bea114 565 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 566 TCGv_ptr addr = tcg_temp_new_ptr();
aaa9128a 567
d9bea114
AJ
568 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
569 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
570 tcg_gen_andi_i32(t2, t2, 0xf);
571 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
572 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 573 tcg_gen_add_ptr(addr, cpu_env, addr);
aaa9128a 574
d9bea114 575 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
a7812ae4 576 tcg_temp_free_ptr(addr);
d9bea114 577 tcg_temp_free_i32(t2);
8e9ade68 578 }
d9bea114
AJ
579 gen_store_gpr(t0, to);
580 tcg_temp_free(t0);
aaa9128a
TS
581}
582
be24bb4f 583static inline void gen_store_srsgpr (int from, int to)
aaa9128a 584{
be24bb4f 585 if (to != 0) {
d9bea114
AJ
586 TCGv t0 = tcg_temp_new();
587 TCGv_i32 t2 = tcg_temp_new_i32();
a7812ae4 588 TCGv_ptr addr = tcg_temp_new_ptr();
be24bb4f 589
d9bea114
AJ
590 gen_load_gpr(t0, from);
591 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUState, CP0_SRSCtl));
592 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
593 tcg_gen_andi_i32(t2, t2, 0xf);
594 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
595 tcg_gen_ext_i32_ptr(addr, t2);
a7812ae4 596 tcg_gen_add_ptr(addr, cpu_env, addr);
be24bb4f 597
d9bea114 598 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
a7812ae4 599 tcg_temp_free_ptr(addr);
d9bea114
AJ
600 tcg_temp_free_i32(t2);
601 tcg_temp_free(t0);
8e9ade68 602 }
aaa9128a
TS
603}
604
aaa9128a 605/* Floating point register moves. */
a7812ae4 606static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 607{
6d066274 608 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
6ea83fed
FB
609}
610
a7812ae4 611static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
aa0bf00b 612{
6d066274
AJ
613 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
614}
615
616static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
617{
618 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
619}
620
621static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
622{
623 tcg_gen_st_i32(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
aa0bf00b 624}
6ea83fed 625
a7812ae4 626static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 627{
f364515c 628 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 629 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 630 } else {
6d066274
AJ
631 TCGv_i32 t0 = tcg_temp_new_i32();
632 TCGv_i32 t1 = tcg_temp_new_i32();
633 gen_load_fpr32(t0, reg & ~1);
634 gen_load_fpr32(t1, reg | 1);
635 tcg_gen_concat_i32_i64(t, t0, t1);
636 tcg_temp_free_i32(t0);
637 tcg_temp_free_i32(t1);
aa0bf00b
TS
638 }
639}
6ea83fed 640
a7812ae4 641static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
aa0bf00b 642{
f364515c 643 if (ctx->hflags & MIPS_HFLAG_F64) {
6d066274 644 tcg_gen_st_i64(t, cpu_env, offsetof(CPUState, active_fpu.fpr[reg].d));
f364515c 645 } else {
6d066274
AJ
646 TCGv_i64 t0 = tcg_temp_new_i64();
647 TCGv_i32 t1 = tcg_temp_new_i32();
648 tcg_gen_trunc_i64_i32(t1, t);
649 gen_store_fpr32(t1, reg & ~1);
650 tcg_gen_shri_i64(t0, t, 32);
651 tcg_gen_trunc_i64_i32(t1, t0);
652 gen_store_fpr32(t1, reg | 1);
653 tcg_temp_free_i32(t1);
654 tcg_temp_free_i64(t0);
aa0bf00b
TS
655 }
656}
6ea83fed 657
d94536f4 658static inline int get_fp_bit (int cc)
a16336e4 659{
d94536f4
AJ
660 if (cc)
661 return 24 + cc;
662 else
663 return 23;
a16336e4
TS
664}
665
a7812ae4
PB
666#define FOP_CONDS(type, fmt, bits) \
667static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
668 TCGv_i##bits b, int cc) \
b6d96bed 669{ \
a7812ae4
PB
670 switch (n) { \
671 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
672 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
673 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
674 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
675 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
676 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
677 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
678 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
679 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
680 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
681 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
682 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
683 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
684 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
685 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
686 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
687 default: abort(); \
688 } \
6ea83fed
FB
689}
690
a7812ae4
PB
691FOP_CONDS(, d, 64)
692FOP_CONDS(abs, d, 64)
693FOP_CONDS(, s, 32)
694FOP_CONDS(abs, s, 32)
695FOP_CONDS(, ps, 64)
696FOP_CONDS(abs, ps, 64)
5d0fc900 697#undef FOP_CONDS
6ea83fed 698
30898801 699/* Tests */
8e9ade68
TS
700static inline void gen_save_pc(target_ulong pc)
701{
1eb75d4a 702 tcg_gen_movi_tl(cpu_PC, pc);
8e9ade68 703}
30898801 704
356265ae 705static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
6af0bf9c 706{
d12d51d5 707 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
6af0bf9c 708 if (do_save_pc && ctx->pc != ctx->saved_pc) {
9b9e4393 709 gen_save_pc(ctx->pc);
6af0bf9c
FB
710 ctx->saved_pc = ctx->pc;
711 }
712 if (ctx->hflags != ctx->saved_hflags) {
41db4607 713 tcg_gen_movi_i32(hflags, ctx->hflags);
6af0bf9c 714 ctx->saved_hflags = ctx->hflags;
364d4831 715 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
5a5012ec 716 case MIPS_HFLAG_BR:
5a5012ec
TS
717 break;
718 case MIPS_HFLAG_BC:
5a5012ec 719 case MIPS_HFLAG_BL:
5a5012ec 720 case MIPS_HFLAG_B:
d077b6f7 721 tcg_gen_movi_tl(btarget, ctx->btarget);
5a5012ec 722 break;
6af0bf9c
FB
723 }
724 }
725}
726
356265ae 727static inline void restore_cpu_state (CPUState *env, DisasContext *ctx)
5a5012ec 728{
fd4a04eb 729 ctx->saved_hflags = ctx->hflags;
364d4831 730 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
fd4a04eb 731 case MIPS_HFLAG_BR:
fd4a04eb
TS
732 break;
733 case MIPS_HFLAG_BC:
734 case MIPS_HFLAG_BL:
39454628 735 case MIPS_HFLAG_B:
fd4a04eb 736 ctx->btarget = env->btarget;
fd4a04eb 737 break;
5a5012ec
TS
738 }
739}
740
356265ae 741static inline void
48d38ca5 742generate_exception_err (DisasContext *ctx, int excp, int err)
aaa9128a 743{
a7812ae4
PB
744 TCGv_i32 texcp = tcg_const_i32(excp);
745 TCGv_i32 terr = tcg_const_i32(err);
aaa9128a 746 save_cpu_state(ctx, 1);
a7812ae4
PB
747 gen_helper_raise_exception_err(texcp, terr);
748 tcg_temp_free_i32(terr);
749 tcg_temp_free_i32(texcp);
aaa9128a
TS
750}
751
356265ae 752static inline void
48d38ca5 753generate_exception (DisasContext *ctx, int excp)
aaa9128a 754{
6af0bf9c 755 save_cpu_state(ctx, 1);
a7812ae4 756 gen_helper_0i(raise_exception, excp);
6af0bf9c
FB
757}
758
48d38ca5 759/* Addresses computation */
941694d0 760static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
4ad40f36 761{
941694d0 762 tcg_gen_add_tl(ret, arg0, arg1);
48d38ca5
TS
763
764#if defined(TARGET_MIPS64)
765 /* For compatibility with 32-bit code, data reference in user mode
766 with Status_UX = 0 should be casted to 32-bit and sign extended.
767 See the MIPS64 PRA manual, section 4.10. */
2623c1ec
AJ
768 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
769 !(ctx->hflags & MIPS_HFLAG_UX)) {
941694d0 770 tcg_gen_ext32s_i64(ret, ret);
48d38ca5
TS
771 }
772#endif
4ad40f36
FB
773}
774
356265ae 775static inline void check_cp0_enabled(DisasContext *ctx)
387a8fe5 776{
fe253235 777 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
c2c65dab 778 generate_exception_err(ctx, EXCP_CpU, 0);
387a8fe5
TS
779}
780
356265ae 781static inline void check_cp1_enabled(DisasContext *ctx)
5e755519 782{
fe253235 783 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
5e755519
TS
784 generate_exception_err(ctx, EXCP_CpU, 1);
785}
786
b8aa4598
TS
787/* Verify that the processor is running with COP1X instructions enabled.
788 This is associated with the nabla symbol in the MIPS32 and MIPS64
789 opcode tables. */
790
356265ae 791static inline void check_cop1x(DisasContext *ctx)
b8aa4598
TS
792{
793 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
794 generate_exception(ctx, EXCP_RI);
795}
796
797/* Verify that the processor is running with 64-bit floating-point
798 operations enabled. */
799
356265ae 800static inline void check_cp1_64bitmode(DisasContext *ctx)
5e755519 801{
b8aa4598 802 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
5e755519
TS
803 generate_exception(ctx, EXCP_RI);
804}
805
806/*
807 * Verify if floating point register is valid; an operation is not defined
808 * if bit 0 of any register specification is set and the FR bit in the
809 * Status register equals zero, since the register numbers specify an
810 * even-odd pair of adjacent coprocessor general registers. When the FR bit
811 * in the Status register equals one, both even and odd register numbers
812 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
813 *
814 * Multiple 64 bit wide registers can be checked by calling
815 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
816 */
356265ae 817static inline void check_cp1_registers(DisasContext *ctx, int regs)
5e755519 818{
fe253235 819 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
5e755519
TS
820 generate_exception(ctx, EXCP_RI);
821}
822
3a95e3a7 823/* This code generates a "reserved instruction" exception if the
e189e748 824 CPU does not support the instruction set corresponding to flags. */
356265ae 825static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
3a95e3a7 826{
e189e748 827 if (unlikely(!(env->insn_flags & flags)))
3a95e3a7
TS
828 generate_exception(ctx, EXCP_RI);
829}
830
e189e748
TS
831/* This code generates a "reserved instruction" exception if 64-bit
832 instructions are not enabled. */
356265ae 833static inline void check_mips_64(DisasContext *ctx)
e189e748 834{
fe253235 835 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
e189e748
TS
836 generate_exception(ctx, EXCP_RI);
837}
838
958fb4a9 839/* load/store instructions. */
d9bea114
AJ
840#define OP_LD(insn,fname) \
841static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
842{ \
843 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
aaa9128a
TS
844}
845OP_LD(lb,ld8s);
846OP_LD(lbu,ld8u);
847OP_LD(lh,ld16s);
848OP_LD(lhu,ld16u);
849OP_LD(lw,ld32s);
850#if defined(TARGET_MIPS64)
851OP_LD(lwu,ld32u);
852OP_LD(ld,ld64);
853#endif
854#undef OP_LD
855
d9bea114
AJ
856#define OP_ST(insn,fname) \
857static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
858{ \
859 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
aaa9128a
TS
860}
861OP_ST(sb,st8);
862OP_ST(sh,st16);
863OP_ST(sw,st32);
864#if defined(TARGET_MIPS64)
865OP_ST(sd,st64);
866#endif
867#undef OP_ST
868
e7139c44 869#ifdef CONFIG_USER_ONLY
d9bea114
AJ
870#define OP_LD_ATOMIC(insn,fname) \
871static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
872{ \
873 TCGv t0 = tcg_temp_new(); \
874 tcg_gen_mov_tl(t0, arg1); \
875 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
e7139c44 876 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
590bc601 877 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUState, llval)); \
d9bea114 878 tcg_temp_free(t0); \
aaa9128a 879}
e7139c44
AJ
880#else
881#define OP_LD_ATOMIC(insn,fname) \
882static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
883{ \
884 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
885}
886#endif
aaa9128a
TS
887OP_LD_ATOMIC(ll,ld32s);
888#if defined(TARGET_MIPS64)
889OP_LD_ATOMIC(lld,ld64);
890#endif
891#undef OP_LD_ATOMIC
892
590bc601
PB
893#ifdef CONFIG_USER_ONLY
894#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
895static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
896{ \
897 TCGv t0 = tcg_temp_new(); \
898 int l1 = gen_new_label(); \
899 int l2 = gen_new_label(); \
900 \
901 tcg_gen_andi_tl(t0, arg2, almask); \
902 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
903 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUState, CP0_BadVAddr)); \
904 generate_exception(ctx, EXCP_AdES); \
905 gen_set_label(l1); \
e7139c44 906 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, lladdr)); \
590bc601
PB
907 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
908 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
909 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUState, llreg)); \
910 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUState, llnewval)); \
911 gen_helper_0i(raise_exception, EXCP_SC); \
912 gen_set_label(l2); \
913 tcg_gen_movi_tl(t0, 0); \
914 gen_store_gpr(t0, rt); \
915 tcg_temp_free(t0); \
916}
917#else
918#define OP_ST_ATOMIC(insn,fname,ldname,almask) \
919static inline void op_ldst_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
920{ \
921 TCGv t0 = tcg_temp_new(); \
e7139c44 922 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
590bc601 923 gen_store_gpr(t0, rt); \
590bc601
PB
924 tcg_temp_free(t0); \
925}
926#endif
590bc601 927OP_ST_ATOMIC(sc,st32,ld32s,0x3);
aaa9128a 928#if defined(TARGET_MIPS64)
590bc601 929OP_ST_ATOMIC(scd,st64,ld64,0x7);
aaa9128a
TS
930#endif
931#undef OP_ST_ATOMIC
932
662d7485
NF
933static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
934 int base, int16_t offset)
935{
936 if (base == 0) {
937 tcg_gen_movi_tl(addr, offset);
938 } else if (offset == 0) {
939 gen_load_gpr(addr, base);
940 } else {
941 tcg_gen_movi_tl(addr, offset);
942 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
943 }
944}
945
364d4831
NF
946static target_ulong pc_relative_pc (DisasContext *ctx)
947{
948 target_ulong pc = ctx->pc;
949
950 if (ctx->hflags & MIPS_HFLAG_BMASK) {
951 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
952
953 pc -= branch_bytes;
954 }
955
956 pc &= ~(target_ulong)3;
957 return pc;
958}
959
6af0bf9c 960/* Load and store */
7a387fff 961static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
6af0bf9c
FB
962 int base, int16_t offset)
963{
923617a3 964 const char *opn = "ldst";
d66c7132
AJ
965 TCGv t0 = tcg_temp_new();
966 TCGv t1 = tcg_temp_new();
6af0bf9c 967
662d7485 968 gen_base_offset_addr(ctx, t0, base, offset);
6af0bf9c 969 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 970 memory access. */
6af0bf9c 971 switch (opc) {
d26bc211 972#if defined(TARGET_MIPS64)
6e473128 973 case OPC_LWU:
d66c7132 974 save_cpu_state(ctx, 0);
d9bea114 975 op_ldst_lwu(t0, t0, ctx);
78723684 976 gen_store_gpr(t0, rt);
6e473128
TS
977 opn = "lwu";
978 break;
6af0bf9c 979 case OPC_LD:
d66c7132 980 save_cpu_state(ctx, 0);
d9bea114 981 op_ldst_ld(t0, t0, ctx);
78723684 982 gen_store_gpr(t0, rt);
6af0bf9c
FB
983 opn = "ld";
984 break;
7a387fff 985 case OPC_LLD:
d66c7132 986 save_cpu_state(ctx, 0);
d9bea114 987 op_ldst_lld(t0, t0, ctx);
78723684 988 gen_store_gpr(t0, rt);
7a387fff
TS
989 opn = "lld";
990 break;
6af0bf9c 991 case OPC_SD:
d66c7132 992 save_cpu_state(ctx, 0);
78723684 993 gen_load_gpr(t1, rt);
d9bea114 994 op_ldst_sd(t1, t0, ctx);
6af0bf9c
FB
995 opn = "sd";
996 break;
997 case OPC_LDL:
c8c2227e 998 save_cpu_state(ctx, 1);
78723684 999 gen_load_gpr(t1, rt);
d9bea114 1000 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
78723684 1001 gen_store_gpr(t1, rt);
6af0bf9c
FB
1002 opn = "ldl";
1003 break;
1004 case OPC_SDL:
c8c2227e 1005 save_cpu_state(ctx, 1);
78723684 1006 gen_load_gpr(t1, rt);
d9bea114 1007 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
6af0bf9c
FB
1008 opn = "sdl";
1009 break;
1010 case OPC_LDR:
c8c2227e 1011 save_cpu_state(ctx, 1);
78723684 1012 gen_load_gpr(t1, rt);
d9bea114 1013 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
78723684 1014 gen_store_gpr(t1, rt);
6af0bf9c
FB
1015 opn = "ldr";
1016 break;
1017 case OPC_SDR:
c8c2227e 1018 save_cpu_state(ctx, 1);
78723684 1019 gen_load_gpr(t1, rt);
d9bea114 1020 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
6af0bf9c
FB
1021 opn = "sdr";
1022 break;
364d4831
NF
1023 case OPC_LDPC:
1024 save_cpu_state(ctx, 1);
1025 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1026 gen_op_addr_add(ctx, t0, t0, t1);
1027 op_ldst_ld(t0, t0, ctx);
1028 gen_store_gpr(t0, rt);
1029 break;
6af0bf9c 1030#endif
364d4831
NF
1031 case OPC_LWPC:
1032 save_cpu_state(ctx, 1);
1033 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1034 gen_op_addr_add(ctx, t0, t0, t1);
1035 op_ldst_lw(t0, t0, ctx);
1036 gen_store_gpr(t0, rt);
1037 break;
6af0bf9c 1038 case OPC_LW:
d66c7132 1039 save_cpu_state(ctx, 0);
d9bea114 1040 op_ldst_lw(t0, t0, ctx);
78723684 1041 gen_store_gpr(t0, rt);
6af0bf9c
FB
1042 opn = "lw";
1043 break;
1044 case OPC_SW:
d66c7132 1045 save_cpu_state(ctx, 0);
78723684 1046 gen_load_gpr(t1, rt);
d9bea114 1047 op_ldst_sw(t1, t0, ctx);
6af0bf9c
FB
1048 opn = "sw";
1049 break;
1050 case OPC_LH:
d66c7132 1051 save_cpu_state(ctx, 0);
d9bea114 1052 op_ldst_lh(t0, t0, ctx);
78723684 1053 gen_store_gpr(t0, rt);
6af0bf9c
FB
1054 opn = "lh";
1055 break;
1056 case OPC_SH:
d66c7132 1057 save_cpu_state(ctx, 0);
78723684 1058 gen_load_gpr(t1, rt);
d9bea114 1059 op_ldst_sh(t1, t0, ctx);
6af0bf9c
FB
1060 opn = "sh";
1061 break;
1062 case OPC_LHU:
d66c7132 1063 save_cpu_state(ctx, 0);
d9bea114 1064 op_ldst_lhu(t0, t0, ctx);
78723684 1065 gen_store_gpr(t0, rt);
6af0bf9c
FB
1066 opn = "lhu";
1067 break;
1068 case OPC_LB:
d66c7132 1069 save_cpu_state(ctx, 0);
d9bea114 1070 op_ldst_lb(t0, t0, ctx);
78723684 1071 gen_store_gpr(t0, rt);
6af0bf9c
FB
1072 opn = "lb";
1073 break;
1074 case OPC_SB:
d66c7132 1075 save_cpu_state(ctx, 0);
78723684 1076 gen_load_gpr(t1, rt);
d9bea114 1077 op_ldst_sb(t1, t0, ctx);
6af0bf9c
FB
1078 opn = "sb";
1079 break;
1080 case OPC_LBU:
d66c7132 1081 save_cpu_state(ctx, 0);
d9bea114 1082 op_ldst_lbu(t0, t0, ctx);
78723684 1083 gen_store_gpr(t0, rt);
6af0bf9c
FB
1084 opn = "lbu";
1085 break;
1086 case OPC_LWL:
c8c2227e 1087 save_cpu_state(ctx, 1);
6958549d 1088 gen_load_gpr(t1, rt);
d9bea114 1089 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
78723684 1090 gen_store_gpr(t1, rt);
6af0bf9c
FB
1091 opn = "lwl";
1092 break;
1093 case OPC_SWL:
c8c2227e 1094 save_cpu_state(ctx, 1);
78723684 1095 gen_load_gpr(t1, rt);
d9bea114 1096 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
6af0bf9c
FB
1097 opn = "swr";
1098 break;
1099 case OPC_LWR:
c8c2227e 1100 save_cpu_state(ctx, 1);
6958549d 1101 gen_load_gpr(t1, rt);
d9bea114 1102 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
78723684 1103 gen_store_gpr(t1, rt);
6af0bf9c
FB
1104 opn = "lwr";
1105 break;
1106 case OPC_SWR:
c8c2227e 1107 save_cpu_state(ctx, 1);
78723684 1108 gen_load_gpr(t1, rt);
d9bea114 1109 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
6af0bf9c
FB
1110 opn = "swr";
1111 break;
1112 case OPC_LL:
e7139c44 1113 save_cpu_state(ctx, 1);
d9bea114 1114 op_ldst_ll(t0, t0, ctx);
78723684 1115 gen_store_gpr(t0, rt);
6af0bf9c
FB
1116 opn = "ll";
1117 break;
d66c7132
AJ
1118 }
1119 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1120 tcg_temp_free(t0);
1121 tcg_temp_free(t1);
1122}
1123
1124/* Store conditional */
1125static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1126 int base, int16_t offset)
1127{
1128 const char *opn = "st_cond";
1129 TCGv t0, t1;
1130
1131 t0 = tcg_temp_local_new();
1132
662d7485 1133 gen_base_offset_addr(ctx, t0, base, offset);
d66c7132
AJ
1134 /* Don't do NOP if destination is zero: we must perform the actual
1135 memory access. */
1136
1137 t1 = tcg_temp_local_new();
1138 gen_load_gpr(t1, rt);
1139 switch (opc) {
1140#if defined(TARGET_MIPS64)
1141 case OPC_SCD:
1142 save_cpu_state(ctx, 0);
feeb3b6a 1143 op_ldst_scd(t1, t0, rt, ctx);
d66c7132
AJ
1144 opn = "scd";
1145 break;
1146#endif
6af0bf9c 1147 case OPC_SC:
e7139c44 1148 save_cpu_state(ctx, 1);
feeb3b6a 1149 op_ldst_sc(t1, t0, rt, ctx);
6af0bf9c
FB
1150 opn = "sc";
1151 break;
6af0bf9c
FB
1152 }
1153 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
78723684 1154 tcg_temp_free(t1);
d66c7132 1155 tcg_temp_free(t0);
6af0bf9c
FB
1156}
1157
6ea83fed 1158/* Load and store */
7a387fff 1159static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
356265ae 1160 int base, int16_t offset)
6ea83fed 1161{
923617a3 1162 const char *opn = "flt_ldst";
4e2474d6 1163 TCGv t0 = tcg_temp_new();
6ea83fed 1164
662d7485 1165 gen_base_offset_addr(ctx, t0, base, offset);
6ea83fed 1166 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 1167 memory access. */
6ea83fed
FB
1168 switch (opc) {
1169 case OPC_LWC1:
b6d96bed 1170 {
a7812ae4 1171 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 1172
c407df81
AJ
1173 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1174 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 1175 gen_store_fpr32(fp0, ft);
a7812ae4 1176 tcg_temp_free_i32(fp0);
b6d96bed 1177 }
6ea83fed
FB
1178 opn = "lwc1";
1179 break;
1180 case OPC_SWC1:
b6d96bed 1181 {
a7812ae4
PB
1182 TCGv_i32 fp0 = tcg_temp_new_i32();
1183 TCGv t1 = tcg_temp_new();
b6d96bed
TS
1184
1185 gen_load_fpr32(fp0, ft);
a7812ae4
PB
1186 tcg_gen_extu_i32_tl(t1, fp0);
1187 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1188 tcg_temp_free(t1);
1189 tcg_temp_free_i32(fp0);
b6d96bed 1190 }
6ea83fed
FB
1191 opn = "swc1";
1192 break;
1193 case OPC_LDC1:
b6d96bed 1194 {
a7812ae4 1195 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1196
1197 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1198 gen_store_fpr64(ctx, fp0, ft);
a7812ae4 1199 tcg_temp_free_i64(fp0);
b6d96bed 1200 }
6ea83fed
FB
1201 opn = "ldc1";
1202 break;
1203 case OPC_SDC1:
b6d96bed 1204 {
a7812ae4 1205 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
1206
1207 gen_load_fpr64(ctx, fp0, ft);
1208 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 1209 tcg_temp_free_i64(fp0);
b6d96bed 1210 }
6ea83fed
FB
1211 opn = "sdc1";
1212 break;
1213 default:
923617a3 1214 MIPS_INVAL(opn);
e397ee33 1215 generate_exception(ctx, EXCP_RI);
78723684 1216 goto out;
6ea83fed
FB
1217 }
1218 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
78723684
TS
1219 out:
1220 tcg_temp_free(t0);
6ea83fed 1221}
6ea83fed 1222
6af0bf9c 1223/* Arithmetic with immediate operand */
e189e748
TS
1224static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
1225 int rt, int rs, int16_t imm)
6af0bf9c 1226{
324d9e32 1227 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
923617a3 1228 const char *opn = "imm arith";
6af0bf9c 1229
7a387fff 1230 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
ead9360e
TS
1231 /* If no destination, treat it as a NOP.
1232 For addi, we must generate the overflow exception when needed. */
6af0bf9c 1233 MIPS_DEBUG("NOP");
324d9e32 1234 return;
6af0bf9c
FB
1235 }
1236 switch (opc) {
1237 case OPC_ADDI:
48d38ca5 1238 {
324d9e32
AJ
1239 TCGv t0 = tcg_temp_local_new();
1240 TCGv t1 = tcg_temp_new();
1241 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1242 int l1 = gen_new_label();
1243
324d9e32
AJ
1244 gen_load_gpr(t1, rs);
1245 tcg_gen_addi_tl(t0, t1, uimm);
1246 tcg_gen_ext32s_tl(t0, t0);
48d38ca5 1247
324d9e32
AJ
1248 tcg_gen_xori_tl(t1, t1, ~uimm);
1249 tcg_gen_xori_tl(t2, t0, uimm);
1250 tcg_gen_and_tl(t1, t1, t2);
1251 tcg_temp_free(t2);
1252 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1253 tcg_temp_free(t1);
48d38ca5
TS
1254 /* operands of same sign, result different sign */
1255 generate_exception(ctx, EXCP_OVERFLOW);
1256 gen_set_label(l1);
78723684 1257 tcg_gen_ext32s_tl(t0, t0);
324d9e32
AJ
1258 gen_store_gpr(t0, rt);
1259 tcg_temp_free(t0);
48d38ca5 1260 }
6af0bf9c
FB
1261 opn = "addi";
1262 break;
1263 case OPC_ADDIU:
324d9e32
AJ
1264 if (rs != 0) {
1265 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1266 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1267 } else {
1268 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1269 }
6af0bf9c
FB
1270 opn = "addiu";
1271 break;
d26bc211 1272#if defined(TARGET_MIPS64)
7a387fff 1273 case OPC_DADDI:
48d38ca5 1274 {
324d9e32
AJ
1275 TCGv t0 = tcg_temp_local_new();
1276 TCGv t1 = tcg_temp_new();
1277 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1278 int l1 = gen_new_label();
1279
324d9e32
AJ
1280 gen_load_gpr(t1, rs);
1281 tcg_gen_addi_tl(t0, t1, uimm);
48d38ca5 1282
324d9e32
AJ
1283 tcg_gen_xori_tl(t1, t1, ~uimm);
1284 tcg_gen_xori_tl(t2, t0, uimm);
1285 tcg_gen_and_tl(t1, t1, t2);
1286 tcg_temp_free(t2);
1287 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1288 tcg_temp_free(t1);
48d38ca5
TS
1289 /* operands of same sign, result different sign */
1290 generate_exception(ctx, EXCP_OVERFLOW);
1291 gen_set_label(l1);
324d9e32
AJ
1292 gen_store_gpr(t0, rt);
1293 tcg_temp_free(t0);
48d38ca5 1294 }
7a387fff
TS
1295 opn = "daddi";
1296 break;
1297 case OPC_DADDIU:
324d9e32
AJ
1298 if (rs != 0) {
1299 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1300 } else {
1301 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1302 }
7a387fff
TS
1303 opn = "daddiu";
1304 break;
1305#endif
324d9e32
AJ
1306 }
1307 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1308}
1309
1310/* Logic with immediate operand */
1311static void gen_logic_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1312{
1313 target_ulong uimm;
1314 const char *opn = "imm logic";
1315
1316 if (rt == 0) {
1317 /* If no destination, treat it as a NOP. */
1318 MIPS_DEBUG("NOP");
1319 return;
1320 }
1321 uimm = (uint16_t)imm;
1322 switch (opc) {
6af0bf9c 1323 case OPC_ANDI:
324d9e32
AJ
1324 if (likely(rs != 0))
1325 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1326 else
1327 tcg_gen_movi_tl(cpu_gpr[rt], 0);
6af0bf9c
FB
1328 opn = "andi";
1329 break;
1330 case OPC_ORI:
324d9e32
AJ
1331 if (rs != 0)
1332 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1333 else
1334 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1335 opn = "ori";
1336 break;
1337 case OPC_XORI:
324d9e32
AJ
1338 if (likely(rs != 0))
1339 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1340 else
1341 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
6af0bf9c
FB
1342 opn = "xori";
1343 break;
1344 case OPC_LUI:
324d9e32 1345 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
6af0bf9c
FB
1346 opn = "lui";
1347 break;
324d9e32
AJ
1348 }
1349 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1350}
1351
1352/* Set on less than with immediate operand */
1353static void gen_slt_imm (CPUState *env, uint32_t opc, int rt, int rs, int16_t imm)
1354{
1355 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1356 const char *opn = "imm arith";
1357 TCGv t0;
1358
1359 if (rt == 0) {
1360 /* If no destination, treat it as a NOP. */
1361 MIPS_DEBUG("NOP");
1362 return;
1363 }
1364 t0 = tcg_temp_new();
1365 gen_load_gpr(t0, rs);
1366 switch (opc) {
1367 case OPC_SLTI:
e68dd28f 1368 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1369 opn = "slti";
1370 break;
1371 case OPC_SLTIU:
e68dd28f 1372 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
324d9e32
AJ
1373 opn = "sltiu";
1374 break;
1375 }
1376 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1377 tcg_temp_free(t0);
1378}
1379
1380/* Shifts with immediate operand */
1381static void gen_shift_imm(CPUState *env, DisasContext *ctx, uint32_t opc,
1382 int rt, int rs, int16_t imm)
1383{
1384 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1385 const char *opn = "imm shift";
1386 TCGv t0;
1387
1388 if (rt == 0) {
1389 /* If no destination, treat it as a NOP. */
1390 MIPS_DEBUG("NOP");
1391 return;
1392 }
1393
1394 t0 = tcg_temp_new();
1395 gen_load_gpr(t0, rs);
1396 switch (opc) {
6af0bf9c 1397 case OPC_SLL:
78723684 1398 tcg_gen_shli_tl(t0, t0, uimm);
324d9e32 1399 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
6af0bf9c
FB
1400 opn = "sll";
1401 break;
1402 case OPC_SRA:
324d9e32 1403 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
6af0bf9c
FB
1404 opn = "sra";
1405 break;
1406 case OPC_SRL:
ea63e2c3
NF
1407 if (uimm != 0) {
1408 tcg_gen_ext32u_tl(t0, t0);
1409 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1410 } else {
1411 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
5a63bcb2 1412 }
ea63e2c3
NF
1413 opn = "srl";
1414 break;
1415 case OPC_ROTR:
1416 if (uimm != 0) {
1417 TCGv_i32 t1 = tcg_temp_new_i32();
1418
1419 tcg_gen_trunc_tl_i32(t1, t0);
1420 tcg_gen_rotri_i32(t1, t1, uimm);
1421 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1422 tcg_temp_free_i32(t1);
3399e30f
NF
1423 } else {
1424 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
ea63e2c3
NF
1425 }
1426 opn = "rotr";
7a387fff 1427 break;
d26bc211 1428#if defined(TARGET_MIPS64)
7a387fff 1429 case OPC_DSLL:
324d9e32 1430 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1431 opn = "dsll";
1432 break;
1433 case OPC_DSRA:
324d9e32 1434 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
7a387fff
TS
1435 opn = "dsra";
1436 break;
1437 case OPC_DSRL:
ea63e2c3
NF
1438 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1439 opn = "dsrl";
1440 break;
1441 case OPC_DROTR:
1442 if (uimm != 0) {
1443 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
3399e30f
NF
1444 } else {
1445 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5a63bcb2 1446 }
ea63e2c3 1447 opn = "drotr";
7a387fff
TS
1448 break;
1449 case OPC_DSLL32:
324d9e32 1450 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1451 opn = "dsll32";
1452 break;
1453 case OPC_DSRA32:
324d9e32 1454 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
7a387fff
TS
1455 opn = "dsra32";
1456 break;
1457 case OPC_DSRL32:
ea63e2c3
NF
1458 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1459 opn = "dsrl32";
1460 break;
1461 case OPC_DROTR32:
1462 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1463 opn = "drotr32";
6af0bf9c 1464 break;
7a387fff 1465#endif
6af0bf9c 1466 }
93b12ccc 1467 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
78723684 1468 tcg_temp_free(t0);
6af0bf9c
FB
1469}
1470
1471/* Arithmetic */
e189e748 1472static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1473 int rd, int rs, int rt)
1474{
923617a3 1475 const char *opn = "arith";
6af0bf9c 1476
7a387fff
TS
1477 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1478 && opc != OPC_DADD && opc != OPC_DSUB) {
ead9360e
TS
1479 /* If no destination, treat it as a NOP.
1480 For add & sub, we must generate the overflow exception when needed. */
6af0bf9c 1481 MIPS_DEBUG("NOP");
460f00c4 1482 return;
185f0762 1483 }
460f00c4 1484
6af0bf9c
FB
1485 switch (opc) {
1486 case OPC_ADD:
48d38ca5 1487 {
460f00c4
AJ
1488 TCGv t0 = tcg_temp_local_new();
1489 TCGv t1 = tcg_temp_new();
1490 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1491 int l1 = gen_new_label();
1492
460f00c4
AJ
1493 gen_load_gpr(t1, rs);
1494 gen_load_gpr(t2, rt);
1495 tcg_gen_add_tl(t0, t1, t2);
1496 tcg_gen_ext32s_tl(t0, t0);
1497 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1498 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1499 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1500 tcg_temp_free(t2);
1501 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1502 tcg_temp_free(t1);
48d38ca5
TS
1503 /* operands of same sign, result different sign */
1504 generate_exception(ctx, EXCP_OVERFLOW);
1505 gen_set_label(l1);
460f00c4
AJ
1506 gen_store_gpr(t0, rd);
1507 tcg_temp_free(t0);
48d38ca5 1508 }
6af0bf9c
FB
1509 opn = "add";
1510 break;
1511 case OPC_ADDU:
460f00c4
AJ
1512 if (rs != 0 && rt != 0) {
1513 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1514 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1515 } else if (rs == 0 && rt != 0) {
1516 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1517 } else if (rs != 0 && rt == 0) {
1518 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1519 } else {
1520 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1521 }
6af0bf9c
FB
1522 opn = "addu";
1523 break;
1524 case OPC_SUB:
48d38ca5 1525 {
460f00c4
AJ
1526 TCGv t0 = tcg_temp_local_new();
1527 TCGv t1 = tcg_temp_new();
1528 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1529 int l1 = gen_new_label();
1530
460f00c4
AJ
1531 gen_load_gpr(t1, rs);
1532 gen_load_gpr(t2, rt);
1533 tcg_gen_sub_tl(t0, t1, t2);
1534 tcg_gen_ext32s_tl(t0, t0);
1535 tcg_gen_xor_tl(t2, t1, t2);
1536 tcg_gen_xor_tl(t1, t0, t1);
1537 tcg_gen_and_tl(t1, t1, t2);
1538 tcg_temp_free(t2);
1539 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1540 tcg_temp_free(t1);
31e3104f 1541 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1542 generate_exception(ctx, EXCP_OVERFLOW);
1543 gen_set_label(l1);
460f00c4
AJ
1544 gen_store_gpr(t0, rd);
1545 tcg_temp_free(t0);
48d38ca5 1546 }
6af0bf9c
FB
1547 opn = "sub";
1548 break;
1549 case OPC_SUBU:
460f00c4
AJ
1550 if (rs != 0 && rt != 0) {
1551 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1552 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1553 } else if (rs == 0 && rt != 0) {
1554 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
6bb72b18 1555 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
460f00c4
AJ
1556 } else if (rs != 0 && rt == 0) {
1557 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1558 } else {
1559 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1560 }
6af0bf9c
FB
1561 opn = "subu";
1562 break;
d26bc211 1563#if defined(TARGET_MIPS64)
7a387fff 1564 case OPC_DADD:
48d38ca5 1565 {
460f00c4
AJ
1566 TCGv t0 = tcg_temp_local_new();
1567 TCGv t1 = tcg_temp_new();
1568 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1569 int l1 = gen_new_label();
1570
460f00c4
AJ
1571 gen_load_gpr(t1, rs);
1572 gen_load_gpr(t2, rt);
1573 tcg_gen_add_tl(t0, t1, t2);
1574 tcg_gen_xor_tl(t1, t1, t2);
460f00c4 1575 tcg_gen_xor_tl(t2, t0, t2);
deb4203d 1576 tcg_gen_andc_tl(t1, t2, t1);
460f00c4
AJ
1577 tcg_temp_free(t2);
1578 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1579 tcg_temp_free(t1);
48d38ca5
TS
1580 /* operands of same sign, result different sign */
1581 generate_exception(ctx, EXCP_OVERFLOW);
1582 gen_set_label(l1);
460f00c4
AJ
1583 gen_store_gpr(t0, rd);
1584 tcg_temp_free(t0);
48d38ca5 1585 }
7a387fff
TS
1586 opn = "dadd";
1587 break;
1588 case OPC_DADDU:
460f00c4
AJ
1589 if (rs != 0 && rt != 0) {
1590 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1591 } else if (rs == 0 && rt != 0) {
1592 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1593 } else if (rs != 0 && rt == 0) {
1594 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1595 } else {
1596 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1597 }
7a387fff
TS
1598 opn = "daddu";
1599 break;
1600 case OPC_DSUB:
48d38ca5 1601 {
460f00c4
AJ
1602 TCGv t0 = tcg_temp_local_new();
1603 TCGv t1 = tcg_temp_new();
1604 TCGv t2 = tcg_temp_new();
48d38ca5
TS
1605 int l1 = gen_new_label();
1606
460f00c4
AJ
1607 gen_load_gpr(t1, rs);
1608 gen_load_gpr(t2, rt);
1609 tcg_gen_sub_tl(t0, t1, t2);
1610 tcg_gen_xor_tl(t2, t1, t2);
1611 tcg_gen_xor_tl(t1, t0, t1);
1612 tcg_gen_and_tl(t1, t1, t2);
1613 tcg_temp_free(t2);
1614 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1615 tcg_temp_free(t1);
31e3104f 1616 /* operands of different sign, first operand and result different sign */
48d38ca5
TS
1617 generate_exception(ctx, EXCP_OVERFLOW);
1618 gen_set_label(l1);
460f00c4
AJ
1619 gen_store_gpr(t0, rd);
1620 tcg_temp_free(t0);
48d38ca5 1621 }
7a387fff
TS
1622 opn = "dsub";
1623 break;
1624 case OPC_DSUBU:
460f00c4
AJ
1625 if (rs != 0 && rt != 0) {
1626 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1627 } else if (rs == 0 && rt != 0) {
1628 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1629 } else if (rs != 0 && rt == 0) {
1630 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1631 } else {
1632 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1633 }
7a387fff
TS
1634 opn = "dsubu";
1635 break;
1636#endif
460f00c4
AJ
1637 case OPC_MUL:
1638 if (likely(rs != 0 && rt != 0)) {
1639 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1640 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1641 } else {
1642 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1643 }
1644 opn = "mul";
6af0bf9c 1645 break;
460f00c4
AJ
1646 }
1647 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1648}
1649
1650/* Conditional move */
1651static void gen_cond_move (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1652{
1653 const char *opn = "cond move";
1654 int l1;
1655
1656 if (rd == 0) {
1657 /* If no destination, treat it as a NOP.
1658 For add & sub, we must generate the overflow exception when needed. */
1659 MIPS_DEBUG("NOP");
1660 return;
1661 }
1662
1663 l1 = gen_new_label();
1664 switch (opc) {
1665 case OPC_MOVN:
1666 if (likely(rt != 0))
1667 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1668 else
1669 tcg_gen_br(l1);
1670 opn = "movn";
6af0bf9c 1671 break;
460f00c4
AJ
1672 case OPC_MOVZ:
1673 if (likely(rt != 0))
1674 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1675 opn = "movz";
1676 break;
1677 }
1678 if (rs != 0)
1679 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1680 else
1681 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1682 gen_set_label(l1);
1683
1684 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1685}
1686
1687/* Logic */
1688static void gen_logic (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1689{
1690 const char *opn = "logic";
1691
1692 if (rd == 0) {
1693 /* If no destination, treat it as a NOP. */
1694 MIPS_DEBUG("NOP");
1695 return;
1696 }
1697
1698 switch (opc) {
6af0bf9c 1699 case OPC_AND:
460f00c4
AJ
1700 if (likely(rs != 0 && rt != 0)) {
1701 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1702 } else {
1703 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1704 }
6af0bf9c
FB
1705 opn = "and";
1706 break;
1707 case OPC_NOR:
460f00c4
AJ
1708 if (rs != 0 && rt != 0) {
1709 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1710 } else if (rs == 0 && rt != 0) {
1711 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1712 } else if (rs != 0 && rt == 0) {
1713 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1714 } else {
1715 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1716 }
6af0bf9c
FB
1717 opn = "nor";
1718 break;
1719 case OPC_OR:
460f00c4
AJ
1720 if (likely(rs != 0 && rt != 0)) {
1721 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1722 } else if (rs == 0 && rt != 0) {
1723 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1724 } else if (rs != 0 && rt == 0) {
1725 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1726 } else {
1727 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1728 }
6af0bf9c
FB
1729 opn = "or";
1730 break;
1731 case OPC_XOR:
460f00c4
AJ
1732 if (likely(rs != 0 && rt != 0)) {
1733 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1734 } else if (rs == 0 && rt != 0) {
1735 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1736 } else if (rs != 0 && rt == 0) {
1737 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1738 } else {
1739 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1740 }
6af0bf9c
FB
1741 opn = "xor";
1742 break;
460f00c4
AJ
1743 }
1744 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1745}
1746
1747/* Set on lower than */
1748static void gen_slt (CPUState *env, uint32_t opc, int rd, int rs, int rt)
1749{
1750 const char *opn = "slt";
1751 TCGv t0, t1;
1752
1753 if (rd == 0) {
1754 /* If no destination, treat it as a NOP. */
1755 MIPS_DEBUG("NOP");
1756 return;
1757 }
1758
1759 t0 = tcg_temp_new();
1760 t1 = tcg_temp_new();
1761 gen_load_gpr(t0, rs);
1762 gen_load_gpr(t1, rt);
1763 switch (opc) {
1764 case OPC_SLT:
e68dd28f 1765 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
460f00c4 1766 opn = "slt";
6af0bf9c 1767 break;
460f00c4 1768 case OPC_SLTU:
e68dd28f 1769 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
460f00c4
AJ
1770 opn = "sltu";
1771 break;
1772 }
1773 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1774 tcg_temp_free(t0);
1775 tcg_temp_free(t1);
1776}
20c4c97c 1777
460f00c4
AJ
1778/* Shifts */
1779static void gen_shift (CPUState *env, DisasContext *ctx, uint32_t opc,
1780 int rd, int rs, int rt)
1781{
1782 const char *opn = "shifts";
1783 TCGv t0, t1;
20c4c97c 1784
460f00c4
AJ
1785 if (rd == 0) {
1786 /* If no destination, treat it as a NOP.
1787 For add & sub, we must generate the overflow exception when needed. */
1788 MIPS_DEBUG("NOP");
1789 return;
1790 }
1791
1792 t0 = tcg_temp_new();
1793 t1 = tcg_temp_new();
1794 gen_load_gpr(t0, rs);
1795 gen_load_gpr(t1, rt);
1796 switch (opc) {
6af0bf9c 1797 case OPC_SLLV:
78723684
TS
1798 tcg_gen_andi_tl(t0, t0, 0x1f);
1799 tcg_gen_shl_tl(t0, t1, t0);
460f00c4 1800 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
6af0bf9c
FB
1801 opn = "sllv";
1802 break;
1803 case OPC_SRAV:
78723684 1804 tcg_gen_andi_tl(t0, t0, 0x1f);
460f00c4 1805 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
6af0bf9c
FB
1806 opn = "srav";
1807 break;
1808 case OPC_SRLV:
ea63e2c3
NF
1809 tcg_gen_ext32u_tl(t1, t1);
1810 tcg_gen_andi_tl(t0, t0, 0x1f);
1811 tcg_gen_shr_tl(t0, t1, t0);
1812 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1813 opn = "srlv";
1814 break;
1815 case OPC_ROTRV:
1816 {
1817 TCGv_i32 t2 = tcg_temp_new_i32();
1818 TCGv_i32 t3 = tcg_temp_new_i32();
1819
1820 tcg_gen_trunc_tl_i32(t2, t0);
1821 tcg_gen_trunc_tl_i32(t3, t1);
1822 tcg_gen_andi_i32(t2, t2, 0x1f);
1823 tcg_gen_rotr_i32(t2, t3, t2);
1824 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1825 tcg_temp_free_i32(t2);
1826 tcg_temp_free_i32(t3);
1827 opn = "rotrv";
5a63bcb2 1828 }
7a387fff 1829 break;
d26bc211 1830#if defined(TARGET_MIPS64)
7a387fff 1831 case OPC_DSLLV:
78723684 1832 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1833 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1834 opn = "dsllv";
1835 break;
1836 case OPC_DSRAV:
78723684 1837 tcg_gen_andi_tl(t0, t0, 0x3f);
460f00c4 1838 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
7a387fff
TS
1839 opn = "dsrav";
1840 break;
1841 case OPC_DSRLV:
ea63e2c3
NF
1842 tcg_gen_andi_tl(t0, t0, 0x3f);
1843 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1844 opn = "dsrlv";
1845 break;
1846 case OPC_DROTRV:
1847 tcg_gen_andi_tl(t0, t0, 0x3f);
1848 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1849 opn = "drotrv";
6af0bf9c 1850 break;
7a387fff 1851#endif
6af0bf9c 1852 }
6af0bf9c 1853 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
78723684
TS
1854 tcg_temp_free(t0);
1855 tcg_temp_free(t1);
6af0bf9c
FB
1856}
1857
1858/* Arithmetic on HI/LO registers */
7a387fff 1859static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
6af0bf9c 1860{
923617a3 1861 const char *opn = "hilo";
6af0bf9c
FB
1862
1863 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
ead9360e 1864 /* Treat as NOP. */
6af0bf9c 1865 MIPS_DEBUG("NOP");
a1f6684d 1866 return;
6af0bf9c
FB
1867 }
1868 switch (opc) {
1869 case OPC_MFHI:
a1f6684d 1870 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
6af0bf9c
FB
1871 opn = "mfhi";
1872 break;
1873 case OPC_MFLO:
a1f6684d 1874 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
6af0bf9c
FB
1875 opn = "mflo";
1876 break;
1877 case OPC_MTHI:
a1f6684d
AJ
1878 if (reg != 0)
1879 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1880 else
1881 tcg_gen_movi_tl(cpu_HI[0], 0);
6af0bf9c
FB
1882 opn = "mthi";
1883 break;
1884 case OPC_MTLO:
a1f6684d
AJ
1885 if (reg != 0)
1886 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
1887 else
1888 tcg_gen_movi_tl(cpu_LO[0], 0);
6af0bf9c
FB
1889 opn = "mtlo";
1890 break;
6af0bf9c
FB
1891 }
1892 MIPS_DEBUG("%s %s", opn, regnames[reg]);
1893}
1894
7a387fff 1895static void gen_muldiv (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
1896 int rs, int rt)
1897{
923617a3 1898 const char *opn = "mul/div";
d45f89f4
AJ
1899 TCGv t0, t1;
1900
1901 switch (opc) {
1902 case OPC_DIV:
1903 case OPC_DIVU:
1904#if defined(TARGET_MIPS64)
1905 case OPC_DDIV:
1906 case OPC_DDIVU:
1907#endif
1908 t0 = tcg_temp_local_new();
1909 t1 = tcg_temp_local_new();
1910 break;
1911 default:
1912 t0 = tcg_temp_new();
1913 t1 = tcg_temp_new();
1914 break;
1915 }
6af0bf9c 1916
78723684
TS
1917 gen_load_gpr(t0, rs);
1918 gen_load_gpr(t1, rt);
6af0bf9c
FB
1919 switch (opc) {
1920 case OPC_DIV:
48d38ca5
TS
1921 {
1922 int l1 = gen_new_label();
d45f89f4 1923 int l2 = gen_new_label();
48d38ca5 1924
d45f89f4
AJ
1925 tcg_gen_ext32s_tl(t0, t0);
1926 tcg_gen_ext32s_tl(t1, t1);
78723684 1927 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1928 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
1929 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
1930
1931 tcg_gen_mov_tl(cpu_LO[0], t0);
1932 tcg_gen_movi_tl(cpu_HI[0], 0);
1933 tcg_gen_br(l1);
1934 gen_set_label(l2);
1935 tcg_gen_div_tl(cpu_LO[0], t0, t1);
1936 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
1937 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1938 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1939 gen_set_label(l1);
1940 }
6af0bf9c
FB
1941 opn = "div";
1942 break;
1943 case OPC_DIVU:
48d38ca5
TS
1944 {
1945 int l1 = gen_new_label();
1946
0c0ed03b
AJ
1947 tcg_gen_ext32u_tl(t0, t0);
1948 tcg_gen_ext32u_tl(t1, t1);
78723684 1949 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
1950 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
1951 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
1952 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
1953 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
48d38ca5
TS
1954 gen_set_label(l1);
1955 }
6af0bf9c
FB
1956 opn = "divu";
1957 break;
1958 case OPC_MULT:
214c465f 1959 {
d45f89f4
AJ
1960 TCGv_i64 t2 = tcg_temp_new_i64();
1961 TCGv_i64 t3 = tcg_temp_new_i64();
1962
1963 tcg_gen_ext_tl_i64(t2, t0);
1964 tcg_gen_ext_tl_i64(t3, t1);
1965 tcg_gen_mul_i64(t2, t2, t3);
1966 tcg_temp_free_i64(t3);
1967 tcg_gen_trunc_i64_tl(t0, t2);
1968 tcg_gen_shri_i64(t2, t2, 32);
1969 tcg_gen_trunc_i64_tl(t1, t2);
1970 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1971 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1972 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1973 }
6af0bf9c
FB
1974 opn = "mult";
1975 break;
1976 case OPC_MULTU:
214c465f 1977 {
d45f89f4
AJ
1978 TCGv_i64 t2 = tcg_temp_new_i64();
1979 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 1980
78723684
TS
1981 tcg_gen_ext32u_tl(t0, t0);
1982 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
1983 tcg_gen_extu_tl_i64(t2, t0);
1984 tcg_gen_extu_tl_i64(t3, t1);
1985 tcg_gen_mul_i64(t2, t2, t3);
1986 tcg_temp_free_i64(t3);
1987 tcg_gen_trunc_i64_tl(t0, t2);
1988 tcg_gen_shri_i64(t2, t2, 32);
1989 tcg_gen_trunc_i64_tl(t1, t2);
1990 tcg_temp_free_i64(t2);
b10fa3c9
AJ
1991 tcg_gen_ext32s_tl(cpu_LO[0], t0);
1992 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 1993 }
6af0bf9c
FB
1994 opn = "multu";
1995 break;
d26bc211 1996#if defined(TARGET_MIPS64)
7a387fff 1997 case OPC_DDIV:
48d38ca5
TS
1998 {
1999 int l1 = gen_new_label();
d45f89f4 2000 int l2 = gen_new_label();
48d38ca5 2001
78723684 2002 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
d45f89f4
AJ
2003 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2004 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2005 tcg_gen_mov_tl(cpu_LO[0], t0);
2006 tcg_gen_movi_tl(cpu_HI[0], 0);
2007 tcg_gen_br(l1);
2008 gen_set_label(l2);
2009 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2010 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2011 gen_set_label(l1);
2012 }
7a387fff
TS
2013 opn = "ddiv";
2014 break;
2015 case OPC_DDIVU:
48d38ca5
TS
2016 {
2017 int l1 = gen_new_label();
2018
78723684 2019 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
b10fa3c9
AJ
2020 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2021 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
48d38ca5
TS
2022 gen_set_label(l1);
2023 }
7a387fff
TS
2024 opn = "ddivu";
2025 break;
2026 case OPC_DMULT:
a7812ae4 2027 gen_helper_dmult(t0, t1);
7a387fff
TS
2028 opn = "dmult";
2029 break;
2030 case OPC_DMULTU:
a7812ae4 2031 gen_helper_dmultu(t0, t1);
7a387fff
TS
2032 opn = "dmultu";
2033 break;
2034#endif
6af0bf9c 2035 case OPC_MADD:
214c465f 2036 {
d45f89f4
AJ
2037 TCGv_i64 t2 = tcg_temp_new_i64();
2038 TCGv_i64 t3 = tcg_temp_new_i64();
2039
2040 tcg_gen_ext_tl_i64(t2, t0);
2041 tcg_gen_ext_tl_i64(t3, t1);
2042 tcg_gen_mul_i64(t2, t2, t3);
2043 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2044 tcg_gen_add_i64(t2, t2, t3);
2045 tcg_temp_free_i64(t3);
2046 tcg_gen_trunc_i64_tl(t0, t2);
2047 tcg_gen_shri_i64(t2, t2, 32);
2048 tcg_gen_trunc_i64_tl(t1, t2);
2049 tcg_temp_free_i64(t2);
b10fa3c9 2050 tcg_gen_ext32s_tl(cpu_LO[0], t0);
98070ce0 2051 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2052 }
6af0bf9c
FB
2053 opn = "madd";
2054 break;
2055 case OPC_MADDU:
214c465f 2056 {
d45f89f4
AJ
2057 TCGv_i64 t2 = tcg_temp_new_i64();
2058 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2059
78723684
TS
2060 tcg_gen_ext32u_tl(t0, t0);
2061 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2062 tcg_gen_extu_tl_i64(t2, t0);
2063 tcg_gen_extu_tl_i64(t3, t1);
2064 tcg_gen_mul_i64(t2, t2, t3);
2065 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2066 tcg_gen_add_i64(t2, t2, t3);
2067 tcg_temp_free_i64(t3);
2068 tcg_gen_trunc_i64_tl(t0, t2);
2069 tcg_gen_shri_i64(t2, t2, 32);
2070 tcg_gen_trunc_i64_tl(t1, t2);
2071 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2072 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2073 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2074 }
6af0bf9c
FB
2075 opn = "maddu";
2076 break;
2077 case OPC_MSUB:
214c465f 2078 {
d45f89f4
AJ
2079 TCGv_i64 t2 = tcg_temp_new_i64();
2080 TCGv_i64 t3 = tcg_temp_new_i64();
2081
2082 tcg_gen_ext_tl_i64(t2, t0);
2083 tcg_gen_ext_tl_i64(t3, t1);
2084 tcg_gen_mul_i64(t2, t2, t3);
2085 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2086 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2087 tcg_temp_free_i64(t3);
2088 tcg_gen_trunc_i64_tl(t0, t2);
2089 tcg_gen_shri_i64(t2, t2, 32);
2090 tcg_gen_trunc_i64_tl(t1, t2);
2091 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2092 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2093 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2094 }
6af0bf9c
FB
2095 opn = "msub";
2096 break;
2097 case OPC_MSUBU:
214c465f 2098 {
d45f89f4
AJ
2099 TCGv_i64 t2 = tcg_temp_new_i64();
2100 TCGv_i64 t3 = tcg_temp_new_i64();
214c465f 2101
78723684
TS
2102 tcg_gen_ext32u_tl(t0, t0);
2103 tcg_gen_ext32u_tl(t1, t1);
d45f89f4
AJ
2104 tcg_gen_extu_tl_i64(t2, t0);
2105 tcg_gen_extu_tl_i64(t3, t1);
2106 tcg_gen_mul_i64(t2, t2, t3);
2107 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
98070ce0 2108 tcg_gen_sub_i64(t2, t3, t2);
d45f89f4
AJ
2109 tcg_temp_free_i64(t3);
2110 tcg_gen_trunc_i64_tl(t0, t2);
2111 tcg_gen_shri_i64(t2, t2, 32);
2112 tcg_gen_trunc_i64_tl(t1, t2);
2113 tcg_temp_free_i64(t2);
b10fa3c9
AJ
2114 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2115 tcg_gen_ext32s_tl(cpu_HI[0], t1);
214c465f 2116 }
6af0bf9c
FB
2117 opn = "msubu";
2118 break;
2119 default:
923617a3 2120 MIPS_INVAL(opn);
6af0bf9c 2121 generate_exception(ctx, EXCP_RI);
78723684 2122 goto out;
6af0bf9c
FB
2123 }
2124 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
78723684
TS
2125 out:
2126 tcg_temp_free(t0);
2127 tcg_temp_free(t1);
6af0bf9c
FB
2128}
2129
e9c71dd1
TS
2130static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2131 int rd, int rs, int rt)
2132{
2133 const char *opn = "mul vr54xx";
f157bfe1
AJ
2134 TCGv t0 = tcg_temp_new();
2135 TCGv t1 = tcg_temp_new();
e9c71dd1 2136
6c5c1e20
TS
2137 gen_load_gpr(t0, rs);
2138 gen_load_gpr(t1, rt);
e9c71dd1
TS
2139
2140 switch (opc) {
2141 case OPC_VR54XX_MULS:
a7812ae4 2142 gen_helper_muls(t0, t0, t1);
e9c71dd1 2143 opn = "muls";
6958549d 2144 break;
e9c71dd1 2145 case OPC_VR54XX_MULSU:
a7812ae4 2146 gen_helper_mulsu(t0, t0, t1);
e9c71dd1 2147 opn = "mulsu";
6958549d 2148 break;
e9c71dd1 2149 case OPC_VR54XX_MACC:
a7812ae4 2150 gen_helper_macc(t0, t0, t1);
e9c71dd1 2151 opn = "macc";
6958549d 2152 break;
e9c71dd1 2153 case OPC_VR54XX_MACCU:
a7812ae4 2154 gen_helper_maccu(t0, t0, t1);
e9c71dd1 2155 opn = "maccu";
6958549d 2156 break;
e9c71dd1 2157 case OPC_VR54XX_MSAC:
a7812ae4 2158 gen_helper_msac(t0, t0, t1);
e9c71dd1 2159 opn = "msac";
6958549d 2160 break;
e9c71dd1 2161 case OPC_VR54XX_MSACU:
a7812ae4 2162 gen_helper_msacu(t0, t0, t1);
e9c71dd1 2163 opn = "msacu";
6958549d 2164 break;
e9c71dd1 2165 case OPC_VR54XX_MULHI:
a7812ae4 2166 gen_helper_mulhi(t0, t0, t1);
e9c71dd1 2167 opn = "mulhi";
6958549d 2168 break;
e9c71dd1 2169 case OPC_VR54XX_MULHIU:
a7812ae4 2170 gen_helper_mulhiu(t0, t0, t1);
e9c71dd1 2171 opn = "mulhiu";
6958549d 2172 break;
e9c71dd1 2173 case OPC_VR54XX_MULSHI:
a7812ae4 2174 gen_helper_mulshi(t0, t0, t1);
e9c71dd1 2175 opn = "mulshi";
6958549d 2176 break;
e9c71dd1 2177 case OPC_VR54XX_MULSHIU:
a7812ae4 2178 gen_helper_mulshiu(t0, t0, t1);
e9c71dd1 2179 opn = "mulshiu";
6958549d 2180 break;
e9c71dd1 2181 case OPC_VR54XX_MACCHI:
a7812ae4 2182 gen_helper_macchi(t0, t0, t1);
e9c71dd1 2183 opn = "macchi";
6958549d 2184 break;
e9c71dd1 2185 case OPC_VR54XX_MACCHIU:
a7812ae4 2186 gen_helper_macchiu(t0, t0, t1);
e9c71dd1 2187 opn = "macchiu";
6958549d 2188 break;
e9c71dd1 2189 case OPC_VR54XX_MSACHI:
a7812ae4 2190 gen_helper_msachi(t0, t0, t1);
e9c71dd1 2191 opn = "msachi";
6958549d 2192 break;
e9c71dd1 2193 case OPC_VR54XX_MSACHIU:
a7812ae4 2194 gen_helper_msachiu(t0, t0, t1);
e9c71dd1 2195 opn = "msachiu";
6958549d 2196 break;
e9c71dd1
TS
2197 default:
2198 MIPS_INVAL("mul vr54xx");
2199 generate_exception(ctx, EXCP_RI);
6c5c1e20 2200 goto out;
e9c71dd1 2201 }
6c5c1e20 2202 gen_store_gpr(t0, rd);
e9c71dd1 2203 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
6c5c1e20
TS
2204
2205 out:
2206 tcg_temp_free(t0);
2207 tcg_temp_free(t1);
e9c71dd1
TS
2208}
2209
7a387fff 2210static void gen_cl (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2211 int rd, int rs)
2212{
923617a3 2213 const char *opn = "CLx";
20e1fb52 2214 TCGv t0;
6c5c1e20 2215
6af0bf9c 2216 if (rd == 0) {
ead9360e 2217 /* Treat as NOP. */
6af0bf9c 2218 MIPS_DEBUG("NOP");
20e1fb52 2219 return;
6af0bf9c 2220 }
20e1fb52 2221 t0 = tcg_temp_new();
6c5c1e20 2222 gen_load_gpr(t0, rs);
6af0bf9c
FB
2223 switch (opc) {
2224 case OPC_CLO:
20e1fb52 2225 gen_helper_clo(cpu_gpr[rd], t0);
6af0bf9c
FB
2226 opn = "clo";
2227 break;
2228 case OPC_CLZ:
20e1fb52 2229 gen_helper_clz(cpu_gpr[rd], t0);
6af0bf9c
FB
2230 opn = "clz";
2231 break;
d26bc211 2232#if defined(TARGET_MIPS64)
7a387fff 2233 case OPC_DCLO:
20e1fb52 2234 gen_helper_dclo(cpu_gpr[rd], t0);
7a387fff
TS
2235 opn = "dclo";
2236 break;
2237 case OPC_DCLZ:
20e1fb52 2238 gen_helper_dclz(cpu_gpr[rd], t0);
7a387fff
TS
2239 opn = "dclz";
2240 break;
2241#endif
6af0bf9c 2242 }
6af0bf9c 2243 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
6c5c1e20 2244 tcg_temp_free(t0);
6af0bf9c
FB
2245}
2246
2247/* Traps */
7a387fff 2248static void gen_trap (DisasContext *ctx, uint32_t opc,
6af0bf9c
FB
2249 int rs, int rt, int16_t imm)
2250{
2251 int cond;
cdc0faa6 2252 TCGv t0 = tcg_temp_new();
1ba74fb8 2253 TCGv t1 = tcg_temp_new();
6af0bf9c
FB
2254
2255 cond = 0;
2256 /* Load needed operands */
2257 switch (opc) {
2258 case OPC_TEQ:
2259 case OPC_TGE:
2260 case OPC_TGEU:
2261 case OPC_TLT:
2262 case OPC_TLTU:
2263 case OPC_TNE:
2264 /* Compare two registers */
2265 if (rs != rt) {
be24bb4f
TS
2266 gen_load_gpr(t0, rs);
2267 gen_load_gpr(t1, rt);
6af0bf9c
FB
2268 cond = 1;
2269 }
179e32bb 2270 break;
6af0bf9c
FB
2271 case OPC_TEQI:
2272 case OPC_TGEI:
2273 case OPC_TGEIU:
2274 case OPC_TLTI:
2275 case OPC_TLTIU:
2276 case OPC_TNEI:
2277 /* Compare register to immediate */
2278 if (rs != 0 || imm != 0) {
be24bb4f
TS
2279 gen_load_gpr(t0, rs);
2280 tcg_gen_movi_tl(t1, (int32_t)imm);
6af0bf9c
FB
2281 cond = 1;
2282 }
2283 break;
2284 }
2285 if (cond == 0) {
2286 switch (opc) {
2287 case OPC_TEQ: /* rs == rs */
2288 case OPC_TEQI: /* r0 == 0 */
2289 case OPC_TGE: /* rs >= rs */
2290 case OPC_TGEI: /* r0 >= 0 */
2291 case OPC_TGEU: /* rs >= rs unsigned */
2292 case OPC_TGEIU: /* r0 >= 0 unsigned */
2293 /* Always trap */
cdc0faa6 2294 generate_exception(ctx, EXCP_TRAP);
6af0bf9c
FB
2295 break;
2296 case OPC_TLT: /* rs < rs */
2297 case OPC_TLTI: /* r0 < 0 */
2298 case OPC_TLTU: /* rs < rs unsigned */
2299 case OPC_TLTIU: /* r0 < 0 unsigned */
2300 case OPC_TNE: /* rs != rs */
2301 case OPC_TNEI: /* r0 != 0 */
ead9360e 2302 /* Never trap: treat as NOP. */
cdc0faa6 2303 break;
6af0bf9c
FB
2304 }
2305 } else {
cdc0faa6
AJ
2306 int l1 = gen_new_label();
2307
6af0bf9c
FB
2308 switch (opc) {
2309 case OPC_TEQ:
2310 case OPC_TEQI:
cdc0faa6 2311 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
6af0bf9c
FB
2312 break;
2313 case OPC_TGE:
2314 case OPC_TGEI:
cdc0faa6 2315 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
6af0bf9c
FB
2316 break;
2317 case OPC_TGEU:
2318 case OPC_TGEIU:
cdc0faa6 2319 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
6af0bf9c
FB
2320 break;
2321 case OPC_TLT:
2322 case OPC_TLTI:
cdc0faa6 2323 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
6af0bf9c
FB
2324 break;
2325 case OPC_TLTU:
2326 case OPC_TLTIU:
cdc0faa6 2327 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
6af0bf9c
FB
2328 break;
2329 case OPC_TNE:
2330 case OPC_TNEI:
cdc0faa6 2331 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
6af0bf9c 2332 break;
6af0bf9c 2333 }
cdc0faa6 2334 generate_exception(ctx, EXCP_TRAP);
08ba7963
TS
2335 gen_set_label(l1);
2336 }
be24bb4f
TS
2337 tcg_temp_free(t0);
2338 tcg_temp_free(t1);
6af0bf9c
FB
2339}
2340
356265ae 2341static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
c53be334 2342{
6e256c93
FB
2343 TranslationBlock *tb;
2344 tb = ctx->tb;
7b270ef2
NF
2345 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2346 likely(!ctx->singlestep_enabled)) {
57fec1fe 2347 tcg_gen_goto_tb(n);
9b9e4393 2348 gen_save_pc(dest);
57fec1fe 2349 tcg_gen_exit_tb((long)tb + n);
6e256c93 2350 } else {
9b9e4393 2351 gen_save_pc(dest);
7b270ef2
NF
2352 if (ctx->singlestep_enabled) {
2353 save_cpu_state(ctx, 0);
2354 gen_helper_0i(raise_exception, EXCP_DEBUG);
2355 }
57fec1fe 2356 tcg_gen_exit_tb(0);
6e256c93 2357 }
c53be334
FB
2358}
2359
6af0bf9c 2360/* Branches (before delay slot) */
7a387fff 2361static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
7dca4ad0 2362 int insn_bytes,
6af0bf9c
FB
2363 int rs, int rt, int32_t offset)
2364{
d077b6f7 2365 target_ulong btgt = -1;
3ad4bb2d 2366 int blink = 0;
2fdbad25 2367 int bcond_compute = 0;
1ba74fb8
AJ
2368 TCGv t0 = tcg_temp_new();
2369 TCGv t1 = tcg_temp_new();
3ad4bb2d
TS
2370
2371 if (ctx->hflags & MIPS_HFLAG_BMASK) {
923617a3 2372#ifdef MIPS_DEBUG_DISAS
d12d51d5 2373 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
923617a3 2374#endif
3ad4bb2d 2375 generate_exception(ctx, EXCP_RI);
6c5c1e20 2376 goto out;
3ad4bb2d 2377 }
6af0bf9c 2378
6af0bf9c
FB
2379 /* Load needed operands */
2380 switch (opc) {
2381 case OPC_BEQ:
2382 case OPC_BEQL:
2383 case OPC_BNE:
2384 case OPC_BNEL:
2385 /* Compare two registers */
2386 if (rs != rt) {
6c5c1e20
TS
2387 gen_load_gpr(t0, rs);
2388 gen_load_gpr(t1, rt);
2fdbad25 2389 bcond_compute = 1;
6af0bf9c 2390 }
7dca4ad0 2391 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2392 break;
2393 case OPC_BGEZ:
2394 case OPC_BGEZAL:
2395 case OPC_BGEZALL:
2396 case OPC_BGEZL:
2397 case OPC_BGTZ:
2398 case OPC_BGTZL:
2399 case OPC_BLEZ:
2400 case OPC_BLEZL:
2401 case OPC_BLTZ:
2402 case OPC_BLTZAL:
2403 case OPC_BLTZALL:
2404 case OPC_BLTZL:
2405 /* Compare to zero */
2406 if (rs != 0) {
6c5c1e20 2407 gen_load_gpr(t0, rs);
2fdbad25 2408 bcond_compute = 1;
6af0bf9c 2409 }
7dca4ad0 2410 btgt = ctx->pc + insn_bytes + offset;
6af0bf9c
FB
2411 break;
2412 case OPC_J:
2413 case OPC_JAL:
364d4831 2414 case OPC_JALX:
6af0bf9c 2415 /* Jump to immediate */
7dca4ad0 2416 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
6af0bf9c
FB
2417 break;
2418 case OPC_JR:
2419 case OPC_JALR:
364d4831 2420 case OPC_JALRC:
6af0bf9c 2421 /* Jump to register */
7a387fff
TS
2422 if (offset != 0 && offset != 16) {
2423 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
cbeb0857 2424 others are reserved. */
923617a3 2425 MIPS_INVAL("jump hint");
6af0bf9c 2426 generate_exception(ctx, EXCP_RI);
6c5c1e20 2427 goto out;
6af0bf9c 2428 }
d077b6f7 2429 gen_load_gpr(btarget, rs);
6af0bf9c
FB
2430 break;
2431 default:
2432 MIPS_INVAL("branch/jump");
2433 generate_exception(ctx, EXCP_RI);
6c5c1e20 2434 goto out;
6af0bf9c 2435 }
2fdbad25 2436 if (bcond_compute == 0) {
6af0bf9c
FB
2437 /* No condition to be computed */
2438 switch (opc) {
2439 case OPC_BEQ: /* rx == rx */
2440 case OPC_BEQL: /* rx == rx likely */
2441 case OPC_BGEZ: /* 0 >= 0 */
2442 case OPC_BGEZL: /* 0 >= 0 likely */
2443 case OPC_BLEZ: /* 0 <= 0 */
2444 case OPC_BLEZL: /* 0 <= 0 likely */
2445 /* Always take */
4ad40f36 2446 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2447 MIPS_DEBUG("balways");
2448 break;
2449 case OPC_BGEZAL: /* 0 >= 0 */
2450 case OPC_BGEZALL: /* 0 >= 0 likely */
2451 /* Always take and link */
2452 blink = 31;
4ad40f36 2453 ctx->hflags |= MIPS_HFLAG_B;
6af0bf9c
FB
2454 MIPS_DEBUG("balways and link");
2455 break;
2456 case OPC_BNE: /* rx != rx */
2457 case OPC_BGTZ: /* 0 > 0 */
2458 case OPC_BLTZ: /* 0 < 0 */
ead9360e 2459 /* Treat as NOP. */
6af0bf9c 2460 MIPS_DEBUG("bnever (NOP)");
6c5c1e20 2461 goto out;
eeef26cd 2462 case OPC_BLTZAL: /* 0 < 0 */
1ba74fb8 2463 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f 2464 MIPS_DEBUG("bnever and link");
6c5c1e20 2465 goto out;
eeef26cd 2466 case OPC_BLTZALL: /* 0 < 0 likely */
1ba74fb8 2467 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
9898128f
TS
2468 /* Skip the instruction in the delay slot */
2469 MIPS_DEBUG("bnever, link and skip");
2470 ctx->pc += 4;
6c5c1e20 2471 goto out;
6af0bf9c
FB
2472 case OPC_BNEL: /* rx != rx likely */
2473 case OPC_BGTZL: /* 0 > 0 likely */
6af0bf9c
FB
2474 case OPC_BLTZL: /* 0 < 0 likely */
2475 /* Skip the instruction in the delay slot */
2476 MIPS_DEBUG("bnever and skip");
9898128f 2477 ctx->pc += 4;
6c5c1e20 2478 goto out;
6af0bf9c 2479 case OPC_J:
4ad40f36 2480 ctx->hflags |= MIPS_HFLAG_B;
d077b6f7 2481 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
6af0bf9c 2482 break;
364d4831
NF
2483 case OPC_JALX:
2484 ctx->hflags |= MIPS_HFLAG_BX;
2485 /* Fallthrough */
6af0bf9c
FB
2486 case OPC_JAL:
2487 blink = 31;
4ad40f36 2488 ctx->hflags |= MIPS_HFLAG_B;
364d4831
NF
2489 ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
2490 ? MIPS_HFLAG_BDS16
2491 : MIPS_HFLAG_BDS32);
d077b6f7 2492 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
6af0bf9c
FB
2493 break;
2494 case OPC_JR:
4ad40f36 2495 ctx->hflags |= MIPS_HFLAG_BR;
364d4831
NF
2496 if (ctx->hflags & MIPS_HFLAG_M16)
2497 ctx->hflags |= MIPS_HFLAG_BDS16;
6af0bf9c
FB
2498 MIPS_DEBUG("jr %s", regnames[rs]);
2499 break;
2500 case OPC_JALR:
364d4831 2501 case OPC_JALRC:
6af0bf9c 2502 blink = rt;
4ad40f36 2503 ctx->hflags |= MIPS_HFLAG_BR;
364d4831
NF
2504 if (ctx->hflags & MIPS_HFLAG_M16)
2505 ctx->hflags |= MIPS_HFLAG_BDS16;
6af0bf9c
FB
2506 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2507 break;
2508 default:
2509 MIPS_INVAL("branch/jump");
2510 generate_exception(ctx, EXCP_RI);
6c5c1e20 2511 goto out;
6af0bf9c
FB
2512 }
2513 } else {
2514 switch (opc) {
2515 case OPC_BEQ:
e68dd28f 2516 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2517 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
d077b6f7 2518 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2519 goto not_likely;
2520 case OPC_BEQL:
e68dd28f 2521 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
923617a3 2522 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
d077b6f7 2523 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2524 goto likely;
2525 case OPC_BNE:
e68dd28f 2526 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2527 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
d077b6f7 2528 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2529 goto not_likely;
2530 case OPC_BNEL:
e68dd28f 2531 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
923617a3 2532 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
d077b6f7 2533 regnames[rs], regnames[rt], btgt);
6af0bf9c
FB
2534 goto likely;
2535 case OPC_BGEZ:
e68dd28f 2536 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2537 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2538 goto not_likely;
2539 case OPC_BGEZL:
e68dd28f 2540 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2541 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2542 goto likely;
2543 case OPC_BGEZAL:
e68dd28f 2544 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
d077b6f7 2545 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2546 blink = 31;
2547 goto not_likely;
2548 case OPC_BGEZALL:
e68dd28f 2549 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
6af0bf9c 2550 blink = 31;
d077b6f7 2551 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2552 goto likely;
2553 case OPC_BGTZ:
e68dd28f 2554 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2555 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2556 goto not_likely;
2557 case OPC_BGTZL:
e68dd28f 2558 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
d077b6f7 2559 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2560 goto likely;
2561 case OPC_BLEZ:
e68dd28f 2562 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2563 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2564 goto not_likely;
2565 case OPC_BLEZL:
e68dd28f 2566 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
d077b6f7 2567 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2568 goto likely;
2569 case OPC_BLTZ:
e68dd28f 2570 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2571 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2572 goto not_likely;
2573 case OPC_BLTZL:
e68dd28f 2574 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
d077b6f7 2575 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c
FB
2576 goto likely;
2577 case OPC_BLTZAL:
e68dd28f 2578 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2579 blink = 31;
d077b6f7 2580 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2581 not_likely:
4ad40f36 2582 ctx->hflags |= MIPS_HFLAG_BC;
6af0bf9c
FB
2583 break;
2584 case OPC_BLTZALL:
e68dd28f 2585 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
6af0bf9c 2586 blink = 31;
d077b6f7 2587 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
6af0bf9c 2588 likely:
4ad40f36 2589 ctx->hflags |= MIPS_HFLAG_BL;
6af0bf9c 2590 break;
c53f4a62
TS
2591 default:
2592 MIPS_INVAL("conditional branch/jump");
2593 generate_exception(ctx, EXCP_RI);
6c5c1e20 2594 goto out;
6af0bf9c 2595 }
6af0bf9c 2596 }
923617a3 2597 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
d077b6f7 2598 blink, ctx->hflags, btgt);
9b9e4393 2599
d077b6f7 2600 ctx->btarget = btgt;
6af0bf9c 2601 if (blink > 0) {
364d4831
NF
2602 int post_delay = insn_bytes;
2603 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2604
2605 if (opc != OPC_JALRC)
2606 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2607
2608 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
6af0bf9c 2609 }
6c5c1e20
TS
2610
2611 out:
364d4831
NF
2612 if (insn_bytes == 2)
2613 ctx->hflags |= MIPS_HFLAG_B16;
6c5c1e20
TS
2614 tcg_temp_free(t0);
2615 tcg_temp_free(t1);
6af0bf9c
FB
2616}
2617
7a387fff
TS
2618/* special3 bitfield operations */
2619static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
356265ae 2620 int rs, int lsb, int msb)
7a387fff 2621{
a7812ae4
PB
2622 TCGv t0 = tcg_temp_new();
2623 TCGv t1 = tcg_temp_new();
505ad7c2 2624 target_ulong mask;
6c5c1e20
TS
2625
2626 gen_load_gpr(t1, rs);
7a387fff
TS
2627 switch (opc) {
2628 case OPC_EXT:
2629 if (lsb + msb > 31)
2630 goto fail;
505ad7c2
AJ
2631 tcg_gen_shri_tl(t0, t1, lsb);
2632 if (msb != 31) {
2633 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2634 } else {
2635 tcg_gen_ext32s_tl(t0, t0);
2636 }
7a387fff 2637 break;
c6d6dd7c 2638#if defined(TARGET_MIPS64)
7a387fff 2639 case OPC_DEXTM:
505ad7c2
AJ
2640 tcg_gen_shri_tl(t0, t1, lsb);
2641 if (msb != 31) {
2642 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
2643 }
7a387fff
TS
2644 break;
2645 case OPC_DEXTU:
505ad7c2
AJ
2646 tcg_gen_shri_tl(t0, t1, lsb + 32);
2647 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff
TS
2648 break;
2649 case OPC_DEXT:
505ad7c2
AJ
2650 tcg_gen_shri_tl(t0, t1, lsb);
2651 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
7a387fff 2652 break;
c6d6dd7c 2653#endif
7a387fff
TS
2654 case OPC_INS:
2655 if (lsb > msb)
2656 goto fail;
505ad7c2 2657 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
6c5c1e20 2658 gen_load_gpr(t0, rt);
505ad7c2
AJ
2659 tcg_gen_andi_tl(t0, t0, ~mask);
2660 tcg_gen_shli_tl(t1, t1, lsb);
2661 tcg_gen_andi_tl(t1, t1, mask);
2662 tcg_gen_or_tl(t0, t0, t1);
2663 tcg_gen_ext32s_tl(t0, t0);
7a387fff 2664 break;
c6d6dd7c 2665#if defined(TARGET_MIPS64)
7a387fff
TS
2666 case OPC_DINSM:
2667 if (lsb > msb)
2668 goto fail;
505ad7c2 2669 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
6c5c1e20 2670 gen_load_gpr(t0, rt);
505ad7c2
AJ
2671 tcg_gen_andi_tl(t0, t0, ~mask);
2672 tcg_gen_shli_tl(t1, t1, lsb);
2673 tcg_gen_andi_tl(t1, t1, mask);
2674 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2675 break;
2676 case OPC_DINSU:
2677 if (lsb > msb)
2678 goto fail;
505ad7c2 2679 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
6c5c1e20 2680 gen_load_gpr(t0, rt);
505ad7c2
AJ
2681 tcg_gen_andi_tl(t0, t0, ~mask);
2682 tcg_gen_shli_tl(t1, t1, lsb + 32);
2683 tcg_gen_andi_tl(t1, t1, mask);
2684 tcg_gen_or_tl(t0, t0, t1);
7a387fff
TS
2685 break;
2686 case OPC_DINS:
2687 if (lsb > msb)
2688 goto fail;
6c5c1e20 2689 gen_load_gpr(t0, rt);
505ad7c2
AJ
2690 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
2691 gen_load_gpr(t0, rt);
2692 tcg_gen_andi_tl(t0, t0, ~mask);
2693 tcg_gen_shli_tl(t1, t1, lsb);
2694 tcg_gen_andi_tl(t1, t1, mask);
2695 tcg_gen_or_tl(t0, t0, t1);
7a387fff 2696 break;
c6d6dd7c 2697#endif
7a387fff
TS
2698 default:
2699fail:
2700 MIPS_INVAL("bitops");
2701 generate_exception(ctx, EXCP_RI);
6c5c1e20
TS
2702 tcg_temp_free(t0);
2703 tcg_temp_free(t1);
7a387fff
TS
2704 return;
2705 }
6c5c1e20
TS
2706 gen_store_gpr(t0, rt);
2707 tcg_temp_free(t0);
2708 tcg_temp_free(t1);
7a387fff
TS
2709}
2710
49bcf33c
AJ
2711static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
2712{
3a55fa47 2713 TCGv t0;
49bcf33c 2714
3a55fa47
AJ
2715 if (rd == 0) {
2716 /* If no destination, treat it as a NOP. */
2717 MIPS_DEBUG("NOP");
2718 return;
2719 }
2720
2721 t0 = tcg_temp_new();
2722 gen_load_gpr(t0, rt);
49bcf33c
AJ
2723 switch (op2) {
2724 case OPC_WSBH:
3a55fa47
AJ
2725 {
2726 TCGv t1 = tcg_temp_new();
2727
2728 tcg_gen_shri_tl(t1, t0, 8);
2729 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
2730 tcg_gen_shli_tl(t0, t0, 8);
2731 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
2732 tcg_gen_or_tl(t0, t0, t1);
2733 tcg_temp_free(t1);
2734 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2735 }
49bcf33c
AJ
2736 break;
2737 case OPC_SEB:
3a55fa47 2738 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2739 break;
2740 case OPC_SEH:
3a55fa47 2741 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
49bcf33c
AJ
2742 break;
2743#if defined(TARGET_MIPS64)
2744 case OPC_DSBH:
3a55fa47
AJ
2745 {
2746 TCGv t1 = tcg_temp_new();
2747
2748 tcg_gen_shri_tl(t1, t0, 8);
2749 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
2750 tcg_gen_shli_tl(t0, t0, 8);
2751 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
2752 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2753 tcg_temp_free(t1);
2754 }
49bcf33c
AJ
2755 break;
2756 case OPC_DSHD:
3a55fa47
AJ
2757 {
2758 TCGv t1 = tcg_temp_new();
2759
2760 tcg_gen_shri_tl(t1, t0, 16);
2761 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
2762 tcg_gen_shli_tl(t0, t0, 16);
2763 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
2764 tcg_gen_or_tl(t0, t0, t1);
2765 tcg_gen_shri_tl(t1, t0, 32);
2766 tcg_gen_shli_tl(t0, t0, 32);
2767 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
2768 tcg_temp_free(t1);
2769 }
49bcf33c
AJ
2770 break;
2771#endif
2772 default:
2773 MIPS_INVAL("bsfhl");
2774 generate_exception(ctx, EXCP_RI);
2775 tcg_temp_free(t0);
49bcf33c
AJ
2776 return;
2777 }
49bcf33c 2778 tcg_temp_free(t0);
49bcf33c
AJ
2779}
2780
f1aa6320 2781#ifndef CONFIG_USER_ONLY
0eaef5aa 2782/* CP0 (MMU and control) */
d9bea114 2783static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4f57689a 2784{
d9bea114 2785 TCGv_i32 t0 = tcg_temp_new_i32();
4f57689a 2786
d9bea114
AJ
2787 tcg_gen_ld_i32(t0, cpu_env, off);
2788 tcg_gen_ext_i32_tl(arg, t0);
2789 tcg_temp_free_i32(t0);
4f57689a
TS
2790}
2791
d9bea114 2792static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4f57689a 2793{
d9bea114
AJ
2794 tcg_gen_ld_tl(arg, cpu_env, off);
2795 tcg_gen_ext32s_tl(arg, arg);
4f57689a
TS
2796}
2797
d9bea114 2798static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
f1aa6320 2799{
d9bea114 2800 TCGv_i32 t0 = tcg_temp_new_i32();
f1aa6320 2801
d9bea114
AJ
2802 tcg_gen_trunc_tl_i32(t0, arg);
2803 tcg_gen_st_i32(t0, cpu_env, off);
2804 tcg_temp_free_i32(t0);
f1aa6320
TS
2805}
2806
d9bea114 2807static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
f1aa6320 2808{
d9bea114
AJ
2809 tcg_gen_ext32s_tl(arg, arg);
2810 tcg_gen_st_tl(arg, cpu_env, off);
f1aa6320
TS
2811}
2812
d9bea114 2813static void gen_mfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
873eb012 2814{
7a387fff 2815 const char *rn = "invalid";
873eb012 2816
e189e748
TS
2817 if (sel != 0)
2818 check_insn(env, ctx, ISA_MIPS32);
2819
873eb012
TS
2820 switch (reg) {
2821 case 0:
7a387fff
TS
2822 switch (sel) {
2823 case 0:
d9bea114 2824 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
7a387fff
TS
2825 rn = "Index";
2826 break;
2827 case 1:
7385ac0b 2828 check_insn(env, ctx, ASE_MT);
d9bea114 2829 gen_helper_mfc0_mvpcontrol(arg);
7a387fff 2830 rn = "MVPControl";
ead9360e 2831 break;
7a387fff 2832 case 2:
7385ac0b 2833 check_insn(env, ctx, ASE_MT);
d9bea114 2834 gen_helper_mfc0_mvpconf0(arg);
7a387fff 2835 rn = "MVPConf0";
ead9360e 2836 break;
7a387fff 2837 case 3:
7385ac0b 2838 check_insn(env, ctx, ASE_MT);
d9bea114 2839 gen_helper_mfc0_mvpconf1(arg);
7a387fff 2840 rn = "MVPConf1";
ead9360e 2841 break;
7a387fff
TS
2842 default:
2843 goto die;
2844 }
873eb012
TS
2845 break;
2846 case 1:
7a387fff
TS
2847 switch (sel) {
2848 case 0:
d9bea114 2849 gen_helper_mfc0_random(arg);
7a387fff 2850 rn = "Random";
2423f660 2851 break;
7a387fff 2852 case 1:
7385ac0b 2853 check_insn(env, ctx, ASE_MT);
d9bea114 2854 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
7a387fff 2855 rn = "VPEControl";
ead9360e 2856 break;
7a387fff 2857 case 2:
7385ac0b 2858 check_insn(env, ctx, ASE_MT);
d9bea114 2859 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
7a387fff 2860 rn = "VPEConf0";
ead9360e 2861 break;
7a387fff 2862 case 3:
7385ac0b 2863 check_insn(env, ctx, ASE_MT);
d9bea114 2864 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
7a387fff 2865 rn = "VPEConf1";
ead9360e 2866 break;
7a387fff 2867 case 4:
7385ac0b 2868 check_insn(env, ctx, ASE_MT);
d9bea114 2869 gen_mfc0_load64(arg, offsetof(CPUState, CP0_YQMask));
7a387fff 2870 rn = "YQMask";
ead9360e 2871 break;
7a387fff 2872 case 5:
7385ac0b 2873 check_insn(env, ctx, ASE_MT);
d9bea114 2874 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPESchedule));
7a387fff 2875 rn = "VPESchedule";
ead9360e 2876 break;
7a387fff 2877 case 6:
7385ac0b 2878 check_insn(env, ctx, ASE_MT);
d9bea114 2879 gen_mfc0_load64(arg, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 2880 rn = "VPEScheFBack";
ead9360e 2881 break;
7a387fff 2882 case 7:
7385ac0b 2883 check_insn(env, ctx, ASE_MT);
d9bea114 2884 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
7a387fff 2885 rn = "VPEOpt";
ead9360e 2886 break;
7a387fff
TS
2887 default:
2888 goto die;
2889 }
873eb012
TS
2890 break;
2891 case 2:
7a387fff
TS
2892 switch (sel) {
2893 case 0:
d9bea114
AJ
2894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2895 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
2896 rn = "EntryLo0";
2897 break;
7a387fff 2898 case 1:
7385ac0b 2899 check_insn(env, ctx, ASE_MT);
d9bea114 2900 gen_helper_mfc0_tcstatus(arg);
2423f660 2901 rn = "TCStatus";
ead9360e 2902 break;
7a387fff 2903 case 2:
7385ac0b 2904 check_insn(env, ctx, ASE_MT);
d9bea114 2905 gen_helper_mfc0_tcbind(arg);
2423f660 2906 rn = "TCBind";
ead9360e 2907 break;
7a387fff 2908 case 3:
7385ac0b 2909 check_insn(env, ctx, ASE_MT);
d9bea114 2910 gen_helper_mfc0_tcrestart(arg);
2423f660 2911 rn = "TCRestart";
ead9360e 2912 break;
7a387fff 2913 case 4:
7385ac0b 2914 check_insn(env, ctx, ASE_MT);
d9bea114 2915 gen_helper_mfc0_tchalt(arg);
2423f660 2916 rn = "TCHalt";
ead9360e 2917 break;
7a387fff 2918 case 5:
7385ac0b 2919 check_insn(env, ctx, ASE_MT);
d9bea114 2920 gen_helper_mfc0_tccontext(arg);
2423f660 2921 rn = "TCContext";
ead9360e 2922 break;
7a387fff 2923 case 6:
7385ac0b 2924 check_insn(env, ctx, ASE_MT);
d9bea114 2925 gen_helper_mfc0_tcschedule(arg);
2423f660 2926 rn = "TCSchedule";
ead9360e 2927 break;
7a387fff 2928 case 7:
7385ac0b 2929 check_insn(env, ctx, ASE_MT);
d9bea114 2930 gen_helper_mfc0_tcschefback(arg);
2423f660 2931 rn = "TCScheFBack";
ead9360e 2932 break;
7a387fff
TS
2933 default:
2934 goto die;
2935 }
873eb012
TS
2936 break;
2937 case 3:
7a387fff
TS
2938 switch (sel) {
2939 case 0:
d9bea114
AJ
2940 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2941 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
2942 rn = "EntryLo1";
2943 break;
7a387fff
TS
2944 default:
2945 goto die;
1579a72e 2946 }
873eb012
TS
2947 break;
2948 case 4:
7a387fff
TS
2949 switch (sel) {
2950 case 0:
d9bea114
AJ
2951 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2952 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
2953 rn = "Context";
2954 break;
7a387fff 2955 case 1:
d9bea114 2956// gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
2957 rn = "ContextConfig";
2958// break;
7a387fff
TS
2959 default:
2960 goto die;
1579a72e 2961 }
873eb012
TS
2962 break;
2963 case 5:
7a387fff
TS
2964 switch (sel) {
2965 case 0:
d9bea114 2966 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2423f660
TS
2967 rn = "PageMask";
2968 break;
7a387fff 2969 case 1:
e189e748 2970 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 2971 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
2972 rn = "PageGrain";
2973 break;
7a387fff
TS
2974 default:
2975 goto die;
1579a72e 2976 }
873eb012
TS
2977 break;
2978 case 6:
7a387fff
TS
2979 switch (sel) {
2980 case 0:
d9bea114 2981 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2423f660
TS
2982 rn = "Wired";
2983 break;
7a387fff 2984 case 1:
e189e748 2985 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 2986 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2423f660 2987 rn = "SRSConf0";
ead9360e 2988 break;
7a387fff 2989 case 2:
e189e748 2990 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 2991 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2423f660 2992 rn = "SRSConf1";
ead9360e 2993 break;
7a387fff 2994 case 3:
e189e748 2995 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 2996 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2423f660 2997 rn = "SRSConf2";
ead9360e 2998 break;
7a387fff 2999 case 4:
e189e748 3000 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3001 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
2423f660 3002 rn = "SRSConf3";
ead9360e 3003 break;
7a387fff 3004 case 5:
e189e748 3005 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3006 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
2423f660 3007 rn = "SRSConf4";
ead9360e 3008 break;
7a387fff
TS
3009 default:
3010 goto die;
1579a72e 3011 }
873eb012 3012 break;
8c0fdd85 3013 case 7:
7a387fff
TS
3014 switch (sel) {
3015 case 0:
e189e748 3016 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3017 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
2423f660
TS
3018 rn = "HWREna";
3019 break;
7a387fff
TS
3020 default:
3021 goto die;
1579a72e 3022 }
8c0fdd85 3023 break;
873eb012 3024 case 8:
7a387fff
TS
3025 switch (sel) {
3026 case 0:
d9bea114
AJ
3027 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
3028 tcg_gen_ext32s_tl(arg, arg);
f0b3f3ae 3029 rn = "BadVAddr";
2423f660 3030 break;
7a387fff
TS
3031 default:
3032 goto die;
3033 }
873eb012
TS
3034 break;
3035 case 9:
7a387fff
TS
3036 switch (sel) {
3037 case 0:
2e70f6ef
PB
3038 /* Mark as an IO operation because we read the time. */
3039 if (use_icount)
3040 gen_io_start();
d9bea114 3041 gen_helper_mfc0_count(arg);
2e70f6ef
PB
3042 if (use_icount) {
3043 gen_io_end();
3044 ctx->bstate = BS_STOP;
3045 }
2423f660
TS
3046 rn = "Count";
3047 break;
3048 /* 6,7 are implementation dependent */
7a387fff
TS
3049 default:
3050 goto die;
2423f660 3051 }
873eb012
TS
3052 break;
3053 case 10:
7a387fff
TS
3054 switch (sel) {
3055 case 0:
d9bea114
AJ
3056 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
3057 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3058 rn = "EntryHi";
3059 break;
7a387fff
TS
3060 default:
3061 goto die;
1579a72e 3062 }
873eb012
TS
3063 break;
3064 case 11:
7a387fff
TS
3065 switch (sel) {
3066 case 0:
d9bea114 3067 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
2423f660
TS
3068 rn = "Compare";
3069 break;
3070 /* 6,7 are implementation dependent */
7a387fff
TS
3071 default:
3072 goto die;
2423f660 3073 }
873eb012
TS
3074 break;
3075 case 12:
7a387fff
TS
3076 switch (sel) {
3077 case 0:
d9bea114 3078 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
2423f660
TS
3079 rn = "Status";
3080 break;
7a387fff 3081 case 1:
e189e748 3082 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3083 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
3084 rn = "IntCtl";
3085 break;
7a387fff 3086 case 2:
e189e748 3087 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3088 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
3089 rn = "SRSCtl";
3090 break;
7a387fff 3091 case 3:
e189e748 3092 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3093 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
2423f660 3094 rn = "SRSMap";
fd88b6ab 3095 break;
7a387fff
TS
3096 default:
3097 goto die;
3098 }
873eb012
TS
3099 break;
3100 case 13:
7a387fff
TS
3101 switch (sel) {
3102 case 0:
d9bea114 3103 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
2423f660
TS
3104 rn = "Cause";
3105 break;
7a387fff
TS
3106 default:
3107 goto die;
3108 }
873eb012
TS
3109 break;
3110 case 14:
7a387fff
TS
3111 switch (sel) {
3112 case 0:
d9bea114
AJ
3113 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
3114 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3115 rn = "EPC";
3116 break;
7a387fff
TS
3117 default:
3118 goto die;
1579a72e 3119 }
873eb012
TS
3120 break;
3121 case 15:
7a387fff
TS
3122 switch (sel) {
3123 case 0:
d9bea114 3124 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
2423f660
TS
3125 rn = "PRid";
3126 break;
7a387fff 3127 case 1:
e189e748 3128 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3129 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
2423f660
TS
3130 rn = "EBase";
3131 break;
7a387fff
TS
3132 default:
3133 goto die;
3134 }
873eb012
TS
3135 break;
3136 case 16:
3137 switch (sel) {
3138 case 0:
d9bea114 3139 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
873eb012
TS
3140 rn = "Config";
3141 break;
3142 case 1:
d9bea114 3143 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
873eb012
TS
3144 rn = "Config1";
3145 break;
7a387fff 3146 case 2:
d9bea114 3147 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
7a387fff
TS
3148 rn = "Config2";
3149 break;
3150 case 3:
d9bea114 3151 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
7a387fff
TS
3152 rn = "Config3";
3153 break;
e397ee33
TS
3154 /* 4,5 are reserved */
3155 /* 6,7 are implementation dependent */
3156 case 6:
d9bea114 3157 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
e397ee33
TS
3158 rn = "Config6";
3159 break;
3160 case 7:
d9bea114 3161 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
e397ee33
TS
3162 rn = "Config7";
3163 break;
873eb012 3164 default:
873eb012
TS
3165 goto die;
3166 }
3167 break;
3168 case 17:
7a387fff
TS
3169 switch (sel) {
3170 case 0:
d9bea114 3171 gen_helper_mfc0_lladdr(arg);
2423f660
TS
3172 rn = "LLAddr";
3173 break;
7a387fff
TS
3174 default:
3175 goto die;
3176 }
873eb012
TS
3177 break;
3178 case 18:
7a387fff 3179 switch (sel) {
fd88b6ab 3180 case 0 ... 7:
d9bea114 3181 gen_helper_1i(mfc0_watchlo, arg, sel);
2423f660
TS
3182 rn = "WatchLo";
3183 break;
7a387fff
TS
3184 default:
3185 goto die;
3186 }
873eb012
TS
3187 break;
3188 case 19:
7a387fff 3189 switch (sel) {
fd88b6ab 3190 case 0 ...7:
d9bea114 3191 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
3192 rn = "WatchHi";
3193 break;
7a387fff
TS
3194 default:
3195 goto die;
3196 }
873eb012 3197 break;
8c0fdd85 3198 case 20:
7a387fff
TS
3199 switch (sel) {
3200 case 0:
d26bc211 3201#if defined(TARGET_MIPS64)
e189e748 3202 check_insn(env, ctx, ISA_MIPS3);
d9bea114
AJ
3203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
3204 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3205 rn = "XContext";
3206 break;
703eaf37 3207#endif
7a387fff
TS
3208 default:
3209 goto die;
3210 }
8c0fdd85
TS
3211 break;
3212 case 21:
7a387fff
TS
3213 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3214 switch (sel) {
3215 case 0:
d9bea114 3216 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
2423f660
TS
3217 rn = "Framemask";
3218 break;
7a387fff
TS
3219 default:
3220 goto die;
3221 }
8c0fdd85
TS
3222 break;
3223 case 22:
d9bea114 3224 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3225 rn = "'Diagnostic"; /* implementation dependent */
3226 break;
873eb012 3227 case 23:
7a387fff
TS
3228 switch (sel) {
3229 case 0:
d9bea114 3230 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
3231 rn = "Debug";
3232 break;
7a387fff 3233 case 1:
d9bea114 3234// gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
3235 rn = "TraceControl";
3236// break;
7a387fff 3237 case 2:
d9bea114 3238// gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
3239 rn = "TraceControl2";
3240// break;
7a387fff 3241 case 3:
d9bea114 3242// gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
3243 rn = "UserTraceData";
3244// break;
7a387fff 3245 case 4:
d9bea114 3246// gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
3247 rn = "TraceBPC";
3248// break;
7a387fff
TS
3249 default:
3250 goto die;
3251 }
873eb012
TS
3252 break;
3253 case 24:
7a387fff
TS
3254 switch (sel) {
3255 case 0:
f0b3f3ae 3256 /* EJTAG support */
d9bea114
AJ
3257 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
3258 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3259 rn = "DEPC";
3260 break;
7a387fff
TS
3261 default:
3262 goto die;
3263 }
873eb012 3264 break;
8c0fdd85 3265 case 25:
7a387fff
TS
3266 switch (sel) {
3267 case 0:
d9bea114 3268 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
2423f660 3269 rn = "Performance0";
7a387fff
TS
3270 break;
3271 case 1:
d9bea114 3272// gen_helper_mfc0_performance1(arg);
2423f660
TS
3273 rn = "Performance1";
3274// break;
7a387fff 3275 case 2:
d9bea114 3276// gen_helper_mfc0_performance2(arg);
2423f660
TS
3277 rn = "Performance2";
3278// break;
7a387fff 3279 case 3:
d9bea114 3280// gen_helper_mfc0_performance3(arg);
2423f660
TS
3281 rn = "Performance3";
3282// break;
7a387fff 3283 case 4:
d9bea114 3284// gen_helper_mfc0_performance4(arg);
2423f660
TS
3285 rn = "Performance4";
3286// break;
7a387fff 3287 case 5:
d9bea114 3288// gen_helper_mfc0_performance5(arg);
2423f660
TS
3289 rn = "Performance5";
3290// break;
7a387fff 3291 case 6:
d9bea114 3292// gen_helper_mfc0_performance6(arg);
2423f660
TS
3293 rn = "Performance6";
3294// break;
7a387fff 3295 case 7:
d9bea114 3296// gen_helper_mfc0_performance7(arg);
2423f660
TS
3297 rn = "Performance7";
3298// break;
7a387fff
TS
3299 default:
3300 goto die;
3301 }
8c0fdd85
TS
3302 break;
3303 case 26:
d9bea114 3304 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
3305 rn = "ECC";
3306 break;
8c0fdd85 3307 case 27:
7a387fff 3308 switch (sel) {
7a387fff 3309 case 0 ... 3:
d9bea114 3310 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
3311 rn = "CacheErr";
3312 break;
7a387fff
TS
3313 default:
3314 goto die;
3315 }
8c0fdd85 3316 break;
873eb012
TS
3317 case 28:
3318 switch (sel) {
3319 case 0:
7a387fff
TS
3320 case 2:
3321 case 4:
3322 case 6:
d9bea114 3323 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
873eb012
TS
3324 rn = "TagLo";
3325 break;
3326 case 1:
7a387fff
TS
3327 case 3:
3328 case 5:
3329 case 7:
d9bea114 3330 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
873eb012
TS
3331 rn = "DataLo";
3332 break;
3333 default:
873eb012
TS
3334 goto die;
3335 }
3336 break;
8c0fdd85 3337 case 29:
7a387fff
TS
3338 switch (sel) {
3339 case 0:
3340 case 2:
3341 case 4:
3342 case 6:
d9bea114 3343 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
7a387fff
TS
3344 rn = "TagHi";
3345 break;
3346 case 1:
3347 case 3:
3348 case 5:
3349 case 7:
d9bea114 3350 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
7a387fff
TS
3351 rn = "DataHi";
3352 break;
3353 default:
3354 goto die;
3355 }
8c0fdd85 3356 break;
873eb012 3357 case 30:
7a387fff
TS
3358 switch (sel) {
3359 case 0:
d9bea114
AJ
3360 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
3361 tcg_gen_ext32s_tl(arg, arg);
2423f660
TS
3362 rn = "ErrorEPC";
3363 break;
7a387fff
TS
3364 default:
3365 goto die;
3366 }
873eb012
TS
3367 break;
3368 case 31:
7a387fff
TS
3369 switch (sel) {
3370 case 0:
f0b3f3ae 3371 /* EJTAG support */
d9bea114 3372 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3373 rn = "DESAVE";
3374 break;
7a387fff
TS
3375 default:
3376 goto die;
3377 }
873eb012
TS
3378 break;
3379 default:
873eb012
TS
3380 goto die;
3381 }
d12d51d5 3382 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3383 return;
3384
3385die:
d12d51d5 3386 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
873eb012
TS
3387 generate_exception(ctx, EXCP_RI);
3388}
3389
d9bea114 3390static void gen_mtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
8c0fdd85 3391{
7a387fff
TS
3392 const char *rn = "invalid";
3393
e189e748
TS
3394 if (sel != 0)
3395 check_insn(env, ctx, ISA_MIPS32);
3396
2e70f6ef
PB
3397 if (use_icount)
3398 gen_io_start();
3399
8c0fdd85
TS
3400 switch (reg) {
3401 case 0:
7a387fff
TS
3402 switch (sel) {
3403 case 0:
d9bea114 3404 gen_helper_mtc0_index(arg);
7a387fff
TS
3405 rn = "Index";
3406 break;
3407 case 1:
7385ac0b 3408 check_insn(env, ctx, ASE_MT);
d9bea114 3409 gen_helper_mtc0_mvpcontrol(arg);
7a387fff 3410 rn = "MVPControl";
ead9360e 3411 break;
7a387fff 3412 case 2:
7385ac0b 3413 check_insn(env, ctx, ASE_MT);
ead9360e 3414 /* ignored */
7a387fff 3415 rn = "MVPConf0";
ead9360e 3416 break;
7a387fff 3417 case 3:
7385ac0b 3418 check_insn(env, ctx, ASE_MT);
ead9360e 3419 /* ignored */
7a387fff 3420 rn = "MVPConf1";
ead9360e 3421 break;
7a387fff
TS
3422 default:
3423 goto die;
3424 }
8c0fdd85
TS
3425 break;
3426 case 1:
7a387fff
TS
3427 switch (sel) {
3428 case 0:
2423f660 3429 /* ignored */
7a387fff 3430 rn = "Random";
2423f660 3431 break;
7a387fff 3432 case 1:
7385ac0b 3433 check_insn(env, ctx, ASE_MT);
d9bea114 3434 gen_helper_mtc0_vpecontrol(arg);
7a387fff 3435 rn = "VPEControl";
ead9360e 3436 break;
7a387fff 3437 case 2:
7385ac0b 3438 check_insn(env, ctx, ASE_MT);
d9bea114 3439 gen_helper_mtc0_vpeconf0(arg);
7a387fff 3440 rn = "VPEConf0";
ead9360e 3441 break;
7a387fff 3442 case 3:
7385ac0b 3443 check_insn(env, ctx, ASE_MT);
d9bea114 3444 gen_helper_mtc0_vpeconf1(arg);
7a387fff 3445 rn = "VPEConf1";
ead9360e 3446 break;
7a387fff 3447 case 4:
7385ac0b 3448 check_insn(env, ctx, ASE_MT);
d9bea114 3449 gen_helper_mtc0_yqmask(arg);
7a387fff 3450 rn = "YQMask";
ead9360e 3451 break;
7a387fff 3452 case 5:
7385ac0b 3453 check_insn(env, ctx, ASE_MT);
d9bea114 3454 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPESchedule));
7a387fff 3455 rn = "VPESchedule";
ead9360e 3456 break;
7a387fff 3457 case 6:
7385ac0b 3458 check_insn(env, ctx, ASE_MT);
d9bea114 3459 gen_mtc0_store64(arg, offsetof(CPUState, CP0_VPEScheFBack));
7a387fff 3460 rn = "VPEScheFBack";
ead9360e 3461 break;
7a387fff 3462 case 7:
7385ac0b 3463 check_insn(env, ctx, ASE_MT);
d9bea114 3464 gen_helper_mtc0_vpeopt(arg);
7a387fff 3465 rn = "VPEOpt";
ead9360e 3466 break;
7a387fff
TS
3467 default:
3468 goto die;
3469 }
8c0fdd85
TS
3470 break;
3471 case 2:
7a387fff
TS
3472 switch (sel) {
3473 case 0:
d9bea114 3474 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
3475 rn = "EntryLo0";
3476 break;
7a387fff 3477 case 1:
7385ac0b 3478 check_insn(env, ctx, ASE_MT);
d9bea114 3479 gen_helper_mtc0_tcstatus(arg);
2423f660 3480 rn = "TCStatus";
ead9360e 3481 break;
7a387fff 3482 case 2:
7385ac0b 3483 check_insn(env, ctx, ASE_MT);
d9bea114 3484 gen_helper_mtc0_tcbind(arg);
2423f660 3485 rn = "TCBind";
ead9360e 3486 break;
7a387fff 3487 case 3:
7385ac0b 3488 check_insn(env, ctx, ASE_MT);
d9bea114 3489 gen_helper_mtc0_tcrestart(arg);
2423f660 3490 rn = "TCRestart";
ead9360e 3491 break;
7a387fff 3492 case 4:
7385ac0b 3493 check_insn(env, ctx, ASE_MT);
d9bea114 3494 gen_helper_mtc0_tchalt(arg);
2423f660 3495 rn = "TCHalt";
ead9360e 3496 break;
7a387fff 3497 case 5:
7385ac0b 3498 check_insn(env, ctx, ASE_MT);
d9bea114 3499 gen_helper_mtc0_tccontext(arg);
2423f660 3500 rn = "TCContext";
ead9360e 3501 break;
7a387fff 3502 case 6:
7385ac0b 3503 check_insn(env, ctx, ASE_MT);
d9bea114 3504 gen_helper_mtc0_tcschedule(arg);
2423f660 3505 rn = "TCSchedule";
ead9360e 3506 break;
7a387fff 3507 case 7:
7385ac0b 3508 check_insn(env, ctx, ASE_MT);
d9bea114 3509 gen_helper_mtc0_tcschefback(arg);
2423f660 3510 rn = "TCScheFBack";
ead9360e 3511 break;
7a387fff
TS
3512 default:
3513 goto die;
3514 }
8c0fdd85
TS
3515 break;
3516 case 3:
7a387fff
TS
3517 switch (sel) {
3518 case 0:
d9bea114 3519 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
3520 rn = "EntryLo1";
3521 break;
7a387fff
TS
3522 default:
3523 goto die;
876d4b07 3524 }
8c0fdd85
TS
3525 break;
3526 case 4:
7a387fff
TS
3527 switch (sel) {
3528 case 0:
d9bea114 3529 gen_helper_mtc0_context(arg);
2423f660
TS
3530 rn = "Context";
3531 break;
7a387fff 3532 case 1:
d9bea114 3533// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
3534 rn = "ContextConfig";
3535// break;
7a387fff
TS
3536 default:
3537 goto die;
876d4b07 3538 }
8c0fdd85
TS
3539 break;
3540 case 5:
7a387fff
TS
3541 switch (sel) {
3542 case 0:
d9bea114 3543 gen_helper_mtc0_pagemask(arg);
2423f660
TS
3544 rn = "PageMask";
3545 break;
7a387fff 3546 case 1:
e189e748 3547 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3548 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
3549 rn = "PageGrain";
3550 break;
7a387fff
TS
3551 default:
3552 goto die;
876d4b07 3553 }
8c0fdd85
TS
3554 break;
3555 case 6:
7a387fff
TS
3556 switch (sel) {
3557 case 0:
d9bea114 3558 gen_helper_mtc0_wired(arg);
2423f660
TS
3559 rn = "Wired";
3560 break;
7a387fff 3561 case 1:
e189e748 3562 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3563 gen_helper_mtc0_srsconf0(arg);
2423f660 3564 rn = "SRSConf0";
ead9360e 3565 break;
7a387fff 3566 case 2:
e189e748 3567 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3568 gen_helper_mtc0_srsconf1(arg);
2423f660 3569 rn = "SRSConf1";
ead9360e 3570 break;
7a387fff 3571 case 3:
e189e748 3572 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3573 gen_helper_mtc0_srsconf2(arg);
2423f660 3574 rn = "SRSConf2";
ead9360e 3575 break;
7a387fff 3576 case 4:
e189e748 3577 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3578 gen_helper_mtc0_srsconf3(arg);
2423f660 3579 rn = "SRSConf3";
ead9360e 3580 break;
7a387fff 3581 case 5:
e189e748 3582 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3583 gen_helper_mtc0_srsconf4(arg);
2423f660 3584 rn = "SRSConf4";
ead9360e 3585 break;
7a387fff
TS
3586 default:
3587 goto die;
876d4b07 3588 }
8c0fdd85
TS
3589 break;
3590 case 7:
7a387fff
TS
3591 switch (sel) {
3592 case 0:
e189e748 3593 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3594 gen_helper_mtc0_hwrena(arg);
2423f660
TS
3595 rn = "HWREna";
3596 break;
7a387fff
TS
3597 default:
3598 goto die;
876d4b07 3599 }
8c0fdd85
TS
3600 break;
3601 case 8:
7a387fff 3602 /* ignored */
f0b3f3ae 3603 rn = "BadVAddr";
8c0fdd85
TS
3604 break;
3605 case 9:
7a387fff
TS
3606 switch (sel) {
3607 case 0:
d9bea114 3608 gen_helper_mtc0_count(arg);
2423f660
TS
3609 rn = "Count";
3610 break;
876d4b07 3611 /* 6,7 are implementation dependent */
7a387fff
TS
3612 default:
3613 goto die;
876d4b07 3614 }
8c0fdd85
TS
3615 break;
3616 case 10:
7a387fff
TS
3617 switch (sel) {
3618 case 0:
d9bea114 3619 gen_helper_mtc0_entryhi(arg);
2423f660
TS
3620 rn = "EntryHi";
3621 break;
7a387fff
TS
3622 default:
3623 goto die;
876d4b07 3624 }
8c0fdd85
TS
3625 break;
3626 case 11:
7a387fff
TS
3627 switch (sel) {
3628 case 0:
d9bea114 3629 gen_helper_mtc0_compare(arg);
2423f660
TS
3630 rn = "Compare";
3631 break;
3632 /* 6,7 are implementation dependent */
7a387fff
TS
3633 default:
3634 goto die;
876d4b07 3635 }
8c0fdd85
TS
3636 break;
3637 case 12:
7a387fff
TS
3638 switch (sel) {
3639 case 0:
867abc7e 3640 save_cpu_state(ctx, 1);
d9bea114 3641 gen_helper_mtc0_status(arg);
8487327a
TS
3642 /* BS_STOP isn't good enough here, hflags may have changed. */
3643 gen_save_pc(ctx->pc + 4);
3644 ctx->bstate = BS_EXCP;
2423f660
TS
3645 rn = "Status";
3646 break;
7a387fff 3647 case 1:
e189e748 3648 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3649 gen_helper_mtc0_intctl(arg);
8487327a
TS
3650 /* Stop translation as we may have switched the execution mode */
3651 ctx->bstate = BS_STOP;
2423f660
TS
3652 rn = "IntCtl";
3653 break;
7a387fff 3654 case 2:
e189e748 3655 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3656 gen_helper_mtc0_srsctl(arg);
8487327a
TS
3657 /* Stop translation as we may have switched the execution mode */
3658 ctx->bstate = BS_STOP;
2423f660
TS
3659 rn = "SRSCtl";
3660 break;
7a387fff 3661 case 3:
e189e748 3662 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3663 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
3664 /* Stop translation as we may have switched the execution mode */
3665 ctx->bstate = BS_STOP;
2423f660 3666 rn = "SRSMap";
fd88b6ab 3667 break;
7a387fff
TS
3668 default:
3669 goto die;
876d4b07 3670 }
8c0fdd85
TS
3671 break;
3672 case 13:
7a387fff
TS
3673 switch (sel) {
3674 case 0:
867abc7e 3675 save_cpu_state(ctx, 1);
d9bea114 3676 gen_helper_mtc0_cause(arg);
2423f660
TS
3677 rn = "Cause";
3678 break;
7a387fff
TS
3679 default:
3680 goto die;
876d4b07 3681 }
8c0fdd85
TS
3682 break;
3683 case 14:
7a387fff
TS
3684 switch (sel) {
3685 case 0:
d9bea114 3686 gen_mtc0_store64(arg, offsetof(CPUState, CP0_EPC));
2423f660
TS
3687 rn = "EPC";
3688 break;
7a387fff
TS
3689 default:
3690 goto die;
876d4b07 3691 }
8c0fdd85
TS
3692 break;
3693 case 15:
7a387fff
TS
3694 switch (sel) {
3695 case 0:
2423f660
TS
3696 /* ignored */
3697 rn = "PRid";
3698 break;
7a387fff 3699 case 1:
e189e748 3700 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 3701 gen_helper_mtc0_ebase(arg);
2423f660
TS
3702 rn = "EBase";
3703 break;
7a387fff
TS
3704 default:
3705 goto die;
1579a72e 3706 }
8c0fdd85
TS
3707 break;
3708 case 16:
3709 switch (sel) {
3710 case 0:
d9bea114 3711 gen_helper_mtc0_config0(arg);
7a387fff 3712 rn = "Config";
2423f660
TS
3713 /* Stop translation as we may have switched the execution mode */
3714 ctx->bstate = BS_STOP;
7a387fff
TS
3715 break;
3716 case 1:
e397ee33 3717 /* ignored, read only */
7a387fff
TS
3718 rn = "Config1";
3719 break;
3720 case 2:
d9bea114 3721 gen_helper_mtc0_config2(arg);
7a387fff 3722 rn = "Config2";
2423f660
TS
3723 /* Stop translation as we may have switched the execution mode */
3724 ctx->bstate = BS_STOP;
8c0fdd85 3725 break;
7a387fff 3726 case 3:
e397ee33 3727 /* ignored, read only */
7a387fff
TS
3728 rn = "Config3";
3729 break;
e397ee33
TS
3730 /* 4,5 are reserved */
3731 /* 6,7 are implementation dependent */
3732 case 6:
3733 /* ignored */
3734 rn = "Config6";
3735 break;
3736 case 7:
3737 /* ignored */
3738 rn = "Config7";
3739 break;
8c0fdd85
TS
3740 default:
3741 rn = "Invalid config selector";
3742 goto die;
3743 }
3744 break;
3745 case 17:
7a387fff
TS
3746 switch (sel) {
3747 case 0:
2a6e32dd 3748 gen_helper_mtc0_lladdr(arg);
2423f660
TS
3749 rn = "LLAddr";
3750 break;
7a387fff
TS
3751 default:
3752 goto die;
3753 }
8c0fdd85
TS
3754 break;
3755 case 18:
7a387fff 3756 switch (sel) {
fd88b6ab 3757 case 0 ... 7:
d9bea114 3758 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
3759 rn = "WatchLo";
3760 break;
7a387fff
TS
3761 default:
3762 goto die;
3763 }
8c0fdd85
TS
3764 break;
3765 case 19:
7a387fff 3766 switch (sel) {
fd88b6ab 3767 case 0 ... 7:
d9bea114 3768 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
3769 rn = "WatchHi";
3770 break;
7a387fff
TS
3771 default:
3772 goto die;
3773 }
8c0fdd85
TS
3774 break;
3775 case 20:
7a387fff
TS
3776 switch (sel) {
3777 case 0:
d26bc211 3778#if defined(TARGET_MIPS64)
e189e748 3779 check_insn(env, ctx, ISA_MIPS3);
d9bea114 3780 gen_helper_mtc0_xcontext(arg);
2423f660
TS
3781 rn = "XContext";
3782 break;
703eaf37 3783#endif
7a387fff
TS
3784 default:
3785 goto die;
3786 }
8c0fdd85
TS
3787 break;
3788 case 21:
7a387fff
TS
3789 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3790 switch (sel) {
3791 case 0:
d9bea114 3792 gen_helper_mtc0_framemask(arg);
2423f660
TS
3793 rn = "Framemask";
3794 break;
7a387fff
TS
3795 default:
3796 goto die;
3797 }
3798 break;
8c0fdd85 3799 case 22:
7a387fff
TS
3800 /* ignored */
3801 rn = "Diagnostic"; /* implementation dependent */
2423f660 3802 break;
8c0fdd85 3803 case 23:
7a387fff
TS
3804 switch (sel) {
3805 case 0:
d9bea114 3806 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
3807 /* BS_STOP isn't good enough here, hflags may have changed. */
3808 gen_save_pc(ctx->pc + 4);
3809 ctx->bstate = BS_EXCP;
2423f660
TS
3810 rn = "Debug";
3811 break;
7a387fff 3812 case 1:
d9bea114 3813// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
2423f660 3814 rn = "TraceControl";
8487327a
TS
3815 /* Stop translation as we may have switched the execution mode */
3816 ctx->bstate = BS_STOP;
2423f660 3817// break;
7a387fff 3818 case 2:
d9bea114 3819// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
2423f660 3820 rn = "TraceControl2";
8487327a
TS
3821 /* Stop translation as we may have switched the execution mode */
3822 ctx->bstate = BS_STOP;
2423f660 3823// break;
7a387fff 3824 case 3:
8487327a
TS
3825 /* Stop translation as we may have switched the execution mode */
3826 ctx->bstate = BS_STOP;
d9bea114 3827// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
2423f660 3828 rn = "UserTraceData";
8487327a
TS
3829 /* Stop translation as we may have switched the execution mode */
3830 ctx->bstate = BS_STOP;
2423f660 3831// break;
7a387fff 3832 case 4:
d9bea114 3833// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
3834 /* Stop translation as we may have switched the execution mode */
3835 ctx->bstate = BS_STOP;
2423f660
TS
3836 rn = "TraceBPC";
3837// break;
7a387fff
TS
3838 default:
3839 goto die;
3840 }
8c0fdd85
TS
3841 break;
3842 case 24:
7a387fff
TS
3843 switch (sel) {
3844 case 0:
f1aa6320 3845 /* EJTAG support */
d9bea114 3846 gen_mtc0_store64(arg, offsetof(CPUState, CP0_DEPC));
2423f660
TS
3847 rn = "DEPC";
3848 break;
7a387fff
TS
3849 default:
3850 goto die;
3851 }
8c0fdd85
TS
3852 break;
3853 case 25:
7a387fff
TS
3854 switch (sel) {
3855 case 0:
d9bea114 3856 gen_helper_mtc0_performance0(arg);
2423f660
TS
3857 rn = "Performance0";
3858 break;
7a387fff 3859 case 1:
d9bea114 3860// gen_helper_mtc0_performance1(arg);
2423f660
TS
3861 rn = "Performance1";
3862// break;
7a387fff 3863 case 2:
d9bea114 3864// gen_helper_mtc0_performance2(arg);
2423f660
TS
3865 rn = "Performance2";
3866// break;
7a387fff 3867 case 3:
d9bea114 3868// gen_helper_mtc0_performance3(arg);
2423f660
TS
3869 rn = "Performance3";
3870// break;
7a387fff 3871 case 4:
d9bea114 3872// gen_helper_mtc0_performance4(arg);
2423f660
TS
3873 rn = "Performance4";
3874// break;
7a387fff 3875 case 5:
d9bea114 3876// gen_helper_mtc0_performance5(arg);
2423f660
TS
3877 rn = "Performance5";
3878// break;
7a387fff 3879 case 6:
d9bea114 3880// gen_helper_mtc0_performance6(arg);
2423f660
TS
3881 rn = "Performance6";
3882// break;
7a387fff 3883 case 7:
d9bea114 3884// gen_helper_mtc0_performance7(arg);
2423f660
TS
3885 rn = "Performance7";
3886// break;
7a387fff
TS
3887 default:
3888 goto die;
3889 }
8c0fdd85
TS
3890 break;
3891 case 26:
2423f660 3892 /* ignored */
8c0fdd85 3893 rn = "ECC";
2423f660 3894 break;
8c0fdd85 3895 case 27:
7a387fff
TS
3896 switch (sel) {
3897 case 0 ... 3:
2423f660
TS
3898 /* ignored */
3899 rn = "CacheErr";
3900 break;
7a387fff
TS
3901 default:
3902 goto die;
3903 }
8c0fdd85
TS
3904 break;
3905 case 28:
3906 switch (sel) {
3907 case 0:
7a387fff
TS
3908 case 2:
3909 case 4:
3910 case 6:
d9bea114 3911 gen_helper_mtc0_taglo(arg);
8c0fdd85
TS
3912 rn = "TagLo";
3913 break;
7a387fff
TS
3914 case 1:
3915 case 3:
3916 case 5:
3917 case 7:
d9bea114 3918 gen_helper_mtc0_datalo(arg);
7a387fff
TS
3919 rn = "DataLo";
3920 break;
8c0fdd85 3921 default:
8c0fdd85
TS
3922 goto die;
3923 }
3924 break;
3925 case 29:
7a387fff
TS
3926 switch (sel) {
3927 case 0:
3928 case 2:
3929 case 4:
3930 case 6:
d9bea114 3931 gen_helper_mtc0_taghi(arg);
7a387fff
TS
3932 rn = "TagHi";
3933 break;
3934 case 1:
3935 case 3:
3936 case 5:
3937 case 7:
d9bea114 3938 gen_helper_mtc0_datahi(arg);
7a387fff
TS
3939 rn = "DataHi";
3940 break;
3941 default:
3942 rn = "invalid sel";
3943 goto die;
3944 }
8c0fdd85
TS
3945 break;
3946 case 30:
7a387fff
TS
3947 switch (sel) {
3948 case 0:
d9bea114 3949 gen_mtc0_store64(arg, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
3950 rn = "ErrorEPC";
3951 break;
7a387fff
TS
3952 default:
3953 goto die;
3954 }
8c0fdd85
TS
3955 break;
3956 case 31:
7a387fff
TS
3957 switch (sel) {
3958 case 0:
f1aa6320 3959 /* EJTAG support */
d9bea114 3960 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
3961 rn = "DESAVE";
3962 break;
7a387fff
TS
3963 default:
3964 goto die;
3965 }
2423f660
TS
3966 /* Stop translation as we may have switched the execution mode */
3967 ctx->bstate = BS_STOP;
8c0fdd85
TS
3968 break;
3969 default:
8c0fdd85
TS
3970 goto die;
3971 }
d12d51d5 3972 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 3973 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
3974 if (use_icount) {
3975 gen_io_end();
3976 ctx->bstate = BS_STOP;
3977 }
8c0fdd85
TS
3978 return;
3979
3980die:
d12d51d5 3981 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
8c0fdd85
TS
3982 generate_exception(ctx, EXCP_RI);
3983}
3984
d26bc211 3985#if defined(TARGET_MIPS64)
d9bea114 3986static void gen_dmfc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
3987{
3988 const char *rn = "invalid";
3989
e189e748
TS
3990 if (sel != 0)
3991 check_insn(env, ctx, ISA_MIPS64);
3992
9c2149c8
TS
3993 switch (reg) {
3994 case 0:
3995 switch (sel) {
3996 case 0:
d9bea114 3997 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Index));
9c2149c8
TS
3998 rn = "Index";
3999 break;
4000 case 1:
7385ac0b 4001 check_insn(env, ctx, ASE_MT);
d9bea114 4002 gen_helper_mfc0_mvpcontrol(arg);
9c2149c8 4003 rn = "MVPControl";
ead9360e 4004 break;
9c2149c8 4005 case 2:
7385ac0b 4006 check_insn(env, ctx, ASE_MT);
d9bea114 4007 gen_helper_mfc0_mvpconf0(arg);
9c2149c8 4008 rn = "MVPConf0";
ead9360e 4009 break;
9c2149c8 4010 case 3:
7385ac0b 4011 check_insn(env, ctx, ASE_MT);
d9bea114 4012 gen_helper_mfc0_mvpconf1(arg);
9c2149c8 4013 rn = "MVPConf1";
ead9360e 4014 break;
9c2149c8
TS
4015 default:
4016 goto die;
4017 }
4018 break;
4019 case 1:
4020 switch (sel) {
4021 case 0:
d9bea114 4022 gen_helper_mfc0_random(arg);
9c2149c8 4023 rn = "Random";
2423f660 4024 break;
9c2149c8 4025 case 1:
7385ac0b 4026 check_insn(env, ctx, ASE_MT);
d9bea114 4027 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEControl));
9c2149c8 4028 rn = "VPEControl";
ead9360e 4029 break;
9c2149c8 4030 case 2:
7385ac0b 4031 check_insn(env, ctx, ASE_MT);
d9bea114 4032 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf0));
9c2149c8 4033 rn = "VPEConf0";
ead9360e 4034 break;
9c2149c8 4035 case 3:
7385ac0b 4036 check_insn(env, ctx, ASE_MT);
d9bea114 4037 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEConf1));
9c2149c8 4038 rn = "VPEConf1";
ead9360e 4039 break;
9c2149c8 4040 case 4:
7385ac0b 4041 check_insn(env, ctx, ASE_MT);
d9bea114 4042 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_YQMask));
9c2149c8 4043 rn = "YQMask";
ead9360e 4044 break;
9c2149c8 4045 case 5:
7385ac0b 4046 check_insn(env, ctx, ASE_MT);
d9bea114 4047 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4048 rn = "VPESchedule";
ead9360e 4049 break;
9c2149c8 4050 case 6:
7385ac0b 4051 check_insn(env, ctx, ASE_MT);
d9bea114 4052 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4053 rn = "VPEScheFBack";
ead9360e 4054 break;
9c2149c8 4055 case 7:
7385ac0b 4056 check_insn(env, ctx, ASE_MT);
d9bea114 4057 gen_mfc0_load32(arg, offsetof(CPUState, CP0_VPEOpt));
9c2149c8 4058 rn = "VPEOpt";
ead9360e 4059 break;
9c2149c8
TS
4060 default:
4061 goto die;
4062 }
4063 break;
4064 case 2:
4065 switch (sel) {
4066 case 0:
d9bea114 4067 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo0));
2423f660
TS
4068 rn = "EntryLo0";
4069 break;
9c2149c8 4070 case 1:
7385ac0b 4071 check_insn(env, ctx, ASE_MT);
d9bea114 4072 gen_helper_mfc0_tcstatus(arg);
2423f660 4073 rn = "TCStatus";
ead9360e 4074 break;
9c2149c8 4075 case 2:
7385ac0b 4076 check_insn(env, ctx, ASE_MT);
d9bea114 4077 gen_helper_mfc0_tcbind(arg);
2423f660 4078 rn = "TCBind";
ead9360e 4079 break;
9c2149c8 4080 case 3:
7385ac0b 4081 check_insn(env, ctx, ASE_MT);
d9bea114 4082 gen_helper_dmfc0_tcrestart(arg);
2423f660 4083 rn = "TCRestart";
ead9360e 4084 break;
9c2149c8 4085 case 4:
7385ac0b 4086 check_insn(env, ctx, ASE_MT);
d9bea114 4087 gen_helper_dmfc0_tchalt(arg);
2423f660 4088 rn = "TCHalt";
ead9360e 4089 break;
9c2149c8 4090 case 5:
7385ac0b 4091 check_insn(env, ctx, ASE_MT);
d9bea114 4092 gen_helper_dmfc0_tccontext(arg);
2423f660 4093 rn = "TCContext";
ead9360e 4094 break;
9c2149c8 4095 case 6:
7385ac0b 4096 check_insn(env, ctx, ASE_MT);
d9bea114 4097 gen_helper_dmfc0_tcschedule(arg);
2423f660 4098 rn = "TCSchedule";
ead9360e 4099 break;
9c2149c8 4100 case 7:
7385ac0b 4101 check_insn(env, ctx, ASE_MT);
d9bea114 4102 gen_helper_dmfc0_tcschefback(arg);
2423f660 4103 rn = "TCScheFBack";
ead9360e 4104 break;
9c2149c8
TS
4105 default:
4106 goto die;
4107 }
4108 break;
4109 case 3:
4110 switch (sel) {
4111 case 0:
d9bea114 4112 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryLo1));
2423f660
TS
4113 rn = "EntryLo1";
4114 break;
9c2149c8
TS
4115 default:
4116 goto die;
1579a72e 4117 }
9c2149c8
TS
4118 break;
4119 case 4:
4120 switch (sel) {
4121 case 0:
d9bea114 4122 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_Context));
2423f660
TS
4123 rn = "Context";
4124 break;
9c2149c8 4125 case 1:
d9bea114 4126// gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4127 rn = "ContextConfig";
4128// break;
9c2149c8
TS
4129 default:
4130 goto die;
876d4b07 4131 }
9c2149c8
TS
4132 break;
4133 case 5:
4134 switch (sel) {
4135 case 0:
d9bea114 4136 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageMask));
2423f660
TS
4137 rn = "PageMask";
4138 break;
9c2149c8 4139 case 1:
e189e748 4140 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4141 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PageGrain));
2423f660
TS
4142 rn = "PageGrain";
4143 break;
9c2149c8
TS
4144 default:
4145 goto die;
876d4b07 4146 }
9c2149c8
TS
4147 break;
4148 case 6:
4149 switch (sel) {
4150 case 0:
d9bea114 4151 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Wired));
2423f660
TS
4152 rn = "Wired";
4153 break;
9c2149c8 4154 case 1:
e189e748 4155 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4156 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf0));
2423f660 4157 rn = "SRSConf0";
ead9360e 4158 break;
9c2149c8 4159 case 2:
e189e748 4160 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4161 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf1));
2423f660 4162 rn = "SRSConf1";
ead9360e 4163 break;
9c2149c8 4164 case 3:
e189e748 4165 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4166 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf2));
2423f660 4167 rn = "SRSConf2";
ead9360e 4168 break;
9c2149c8 4169 case 4:
e189e748 4170 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4171 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf3));
2423f660 4172 rn = "SRSConf3";
ead9360e 4173 break;
9c2149c8 4174 case 5:
e189e748 4175 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4176 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSConf4));
2423f660 4177 rn = "SRSConf4";
ead9360e 4178 break;
9c2149c8
TS
4179 default:
4180 goto die;
876d4b07 4181 }
9c2149c8
TS
4182 break;
4183 case 7:
4184 switch (sel) {
4185 case 0:
e189e748 4186 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4187 gen_mfc0_load32(arg, offsetof(CPUState, CP0_HWREna));
2423f660
TS
4188 rn = "HWREna";
4189 break;
9c2149c8
TS
4190 default:
4191 goto die;
876d4b07 4192 }
9c2149c8
TS
4193 break;
4194 case 8:
4195 switch (sel) {
4196 case 0:
d9bea114 4197 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_BadVAddr));
f0b3f3ae 4198 rn = "BadVAddr";
2423f660 4199 break;
9c2149c8
TS
4200 default:
4201 goto die;
876d4b07 4202 }
9c2149c8
TS
4203 break;
4204 case 9:
4205 switch (sel) {
4206 case 0:
2e70f6ef
PB
4207 /* Mark as an IO operation because we read the time. */
4208 if (use_icount)
4209 gen_io_start();
d9bea114 4210 gen_helper_mfc0_count(arg);
2e70f6ef
PB
4211 if (use_icount) {
4212 gen_io_end();
4213 ctx->bstate = BS_STOP;
4214 }
2423f660
TS
4215 rn = "Count";
4216 break;
4217 /* 6,7 are implementation dependent */
9c2149c8
TS
4218 default:
4219 goto die;
876d4b07 4220 }
9c2149c8
TS
4221 break;
4222 case 10:
4223 switch (sel) {
4224 case 0:
d9bea114 4225 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EntryHi));
2423f660
TS
4226 rn = "EntryHi";
4227 break;
9c2149c8
TS
4228 default:
4229 goto die;
876d4b07 4230 }
9c2149c8
TS
4231 break;
4232 case 11:
4233 switch (sel) {
4234 case 0:
d9bea114 4235 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Compare));
2423f660
TS
4236 rn = "Compare";
4237 break;
876d4b07 4238 /* 6,7 are implementation dependent */
9c2149c8
TS
4239 default:
4240 goto die;
876d4b07 4241 }
9c2149c8
TS
4242 break;
4243 case 12:
4244 switch (sel) {
4245 case 0:
d9bea114 4246 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Status));
2423f660
TS
4247 rn = "Status";
4248 break;
9c2149c8 4249 case 1:
e189e748 4250 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4251 gen_mfc0_load32(arg, offsetof(CPUState, CP0_IntCtl));
2423f660
TS
4252 rn = "IntCtl";
4253 break;
9c2149c8 4254 case 2:
e189e748 4255 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4256 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSCtl));
2423f660
TS
4257 rn = "SRSCtl";
4258 break;
9c2149c8 4259 case 3:
e189e748 4260 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4261 gen_mfc0_load32(arg, offsetof(CPUState, CP0_SRSMap));
2423f660
TS
4262 rn = "SRSMap";
4263 break;
9c2149c8
TS
4264 default:
4265 goto die;
876d4b07 4266 }
9c2149c8
TS
4267 break;
4268 case 13:
4269 switch (sel) {
4270 case 0:
d9bea114 4271 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Cause));
2423f660
TS
4272 rn = "Cause";
4273 break;
9c2149c8
TS
4274 default:
4275 goto die;
876d4b07 4276 }
9c2149c8
TS
4277 break;
4278 case 14:
4279 switch (sel) {
4280 case 0:
d9bea114 4281 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4282 rn = "EPC";
4283 break;
9c2149c8
TS
4284 default:
4285 goto die;
876d4b07 4286 }
9c2149c8
TS
4287 break;
4288 case 15:
4289 switch (sel) {
4290 case 0:
d9bea114 4291 gen_mfc0_load32(arg, offsetof(CPUState, CP0_PRid));
2423f660
TS
4292 rn = "PRid";
4293 break;
9c2149c8 4294 case 1:
e189e748 4295 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4296 gen_mfc0_load32(arg, offsetof(CPUState, CP0_EBase));
2423f660
TS
4297 rn = "EBase";
4298 break;
9c2149c8
TS
4299 default:
4300 goto die;
876d4b07 4301 }
9c2149c8
TS
4302 break;
4303 case 16:
4304 switch (sel) {
4305 case 0:
d9bea114 4306 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config0));
9c2149c8
TS
4307 rn = "Config";
4308 break;
4309 case 1:
d9bea114 4310 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config1));
9c2149c8
TS
4311 rn = "Config1";
4312 break;
4313 case 2:
d9bea114 4314 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config2));
9c2149c8
TS
4315 rn = "Config2";
4316 break;
4317 case 3:
d9bea114 4318 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config3));
9c2149c8
TS
4319 rn = "Config3";
4320 break;
4321 /* 6,7 are implementation dependent */
f0b3f3ae 4322 case 6:
d9bea114 4323 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config6));
f0b3f3ae
TS
4324 rn = "Config6";
4325 break;
4326 case 7:
d9bea114 4327 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Config7));
f0b3f3ae
TS
4328 rn = "Config7";
4329 break;
9c2149c8
TS
4330 default:
4331 goto die;
4332 }
4333 break;
4334 case 17:
4335 switch (sel) {
4336 case 0:
d9bea114 4337 gen_helper_dmfc0_lladdr(arg);
2423f660
TS
4338 rn = "LLAddr";
4339 break;
9c2149c8
TS
4340 default:
4341 goto die;
4342 }
4343 break;
4344 case 18:
4345 switch (sel) {
fd88b6ab 4346 case 0 ... 7:
d9bea114 4347 gen_helper_1i(dmfc0_watchlo, arg, sel);
2423f660
TS
4348 rn = "WatchLo";
4349 break;
9c2149c8
TS
4350 default:
4351 goto die;
4352 }
4353 break;
4354 case 19:
4355 switch (sel) {
fd88b6ab 4356 case 0 ... 7:
d9bea114 4357 gen_helper_1i(mfc0_watchhi, arg, sel);
2423f660
TS
4358 rn = "WatchHi";
4359 break;
9c2149c8
TS
4360 default:
4361 goto die;
4362 }
4363 break;
4364 case 20:
4365 switch (sel) {
4366 case 0:
e189e748 4367 check_insn(env, ctx, ISA_MIPS3);
d9bea114 4368 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_XContext));
2423f660
TS
4369 rn = "XContext";
4370 break;
9c2149c8
TS
4371 default:
4372 goto die;
4373 }
4374 break;
4375 case 21:
4376 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4377 switch (sel) {
4378 case 0:
d9bea114 4379 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Framemask));
2423f660
TS
4380 rn = "Framemask";
4381 break;
9c2149c8
TS
4382 default:
4383 goto die;
4384 }
4385 break;
4386 case 22:
d9bea114 4387 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4388 rn = "'Diagnostic"; /* implementation dependent */
4389 break;
9c2149c8
TS
4390 case 23:
4391 switch (sel) {
4392 case 0:
d9bea114 4393 gen_helper_mfc0_debug(arg); /* EJTAG support */
2423f660
TS
4394 rn = "Debug";
4395 break;
9c2149c8 4396 case 1:
d9bea114 4397// gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
2423f660
TS
4398 rn = "TraceControl";
4399// break;
9c2149c8 4400 case 2:
d9bea114 4401// gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
2423f660
TS
4402 rn = "TraceControl2";
4403// break;
9c2149c8 4404 case 3:
d9bea114 4405// gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
2423f660
TS
4406 rn = "UserTraceData";
4407// break;
9c2149c8 4408 case 4:
d9bea114 4409// gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
2423f660
TS
4410 rn = "TraceBPC";
4411// break;
9c2149c8
TS
4412 default:
4413 goto die;
4414 }
4415 break;
4416 case 24:
4417 switch (sel) {
4418 case 0:
f0b3f3ae 4419 /* EJTAG support */
d9bea114 4420 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
4421 rn = "DEPC";
4422 break;
9c2149c8
TS
4423 default:
4424 goto die;
4425 }
4426 break;
4427 case 25:
4428 switch (sel) {
4429 case 0:
d9bea114 4430 gen_mfc0_load32(arg, offsetof(CPUState, CP0_Performance0));
2423f660 4431 rn = "Performance0";
9c2149c8
TS
4432 break;
4433 case 1:
d9bea114 4434// gen_helper_dmfc0_performance1(arg);
2423f660
TS
4435 rn = "Performance1";
4436// break;
9c2149c8 4437 case 2:
d9bea114 4438// gen_helper_dmfc0_performance2(arg);
2423f660
TS
4439 rn = "Performance2";
4440// break;
9c2149c8 4441 case 3:
d9bea114 4442// gen_helper_dmfc0_performance3(arg);
2423f660
TS
4443 rn = "Performance3";
4444// break;
9c2149c8 4445 case 4:
d9bea114 4446// gen_helper_dmfc0_performance4(arg);
2423f660
TS
4447 rn = "Performance4";
4448// break;
9c2149c8 4449 case 5:
d9bea114 4450// gen_helper_dmfc0_performance5(arg);
2423f660
TS
4451 rn = "Performance5";
4452// break;
9c2149c8 4453 case 6:
d9bea114 4454// gen_helper_dmfc0_performance6(arg);
2423f660
TS
4455 rn = "Performance6";
4456// break;
9c2149c8 4457 case 7:
d9bea114 4458// gen_helper_dmfc0_performance7(arg);
2423f660
TS
4459 rn = "Performance7";
4460// break;
9c2149c8
TS
4461 default:
4462 goto die;
4463 }
4464 break;
4465 case 26:
d9bea114 4466 tcg_gen_movi_tl(arg, 0); /* unimplemented */
da80682b
AJ
4467 rn = "ECC";
4468 break;
9c2149c8
TS
4469 case 27:
4470 switch (sel) {
4471 /* ignored */
4472 case 0 ... 3:
d9bea114 4473 tcg_gen_movi_tl(arg, 0); /* unimplemented */
2423f660
TS
4474 rn = "CacheErr";
4475 break;
9c2149c8
TS
4476 default:
4477 goto die;
4478 }
4479 break;
4480 case 28:
4481 switch (sel) {
4482 case 0:
4483 case 2:
4484 case 4:
4485 case 6:
d9bea114 4486 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagLo));
9c2149c8
TS
4487 rn = "TagLo";
4488 break;
4489 case 1:
4490 case 3:
4491 case 5:
4492 case 7:
d9bea114 4493 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataLo));
9c2149c8
TS
4494 rn = "DataLo";
4495 break;
4496 default:
4497 goto die;
4498 }
4499 break;
4500 case 29:
4501 switch (sel) {
4502 case 0:
4503 case 2:
4504 case 4:
4505 case 6:
d9bea114 4506 gen_mfc0_load32(arg, offsetof(CPUState, CP0_TagHi));
9c2149c8
TS
4507 rn = "TagHi";
4508 break;
4509 case 1:
4510 case 3:
4511 case 5:
4512 case 7:
d9bea114 4513 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DataHi));
9c2149c8
TS
4514 rn = "DataHi";
4515 break;
4516 default:
4517 goto die;
4518 }
4519 break;
4520 case 30:
4521 switch (sel) {
4522 case 0:
d9bea114 4523 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
4524 rn = "ErrorEPC";
4525 break;
9c2149c8
TS
4526 default:
4527 goto die;
4528 }
4529 break;
4530 case 31:
4531 switch (sel) {
4532 case 0:
f0b3f3ae 4533 /* EJTAG support */
d9bea114 4534 gen_mfc0_load32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
4535 rn = "DESAVE";
4536 break;
9c2149c8
TS
4537 default:
4538 goto die;
4539 }
4540 break;
4541 default:
876d4b07 4542 goto die;
9c2149c8 4543 }
d12d51d5 4544 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4545 return;
4546
4547die:
d12d51d5 4548 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
4549 generate_exception(ctx, EXCP_RI);
4550}
4551
d9bea114 4552static void gen_dmtc0 (CPUState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
9c2149c8
TS
4553{
4554 const char *rn = "invalid";
4555
e189e748
TS
4556 if (sel != 0)
4557 check_insn(env, ctx, ISA_MIPS64);
4558
2e70f6ef
PB
4559 if (use_icount)
4560 gen_io_start();
4561
9c2149c8
TS
4562 switch (reg) {
4563 case 0:
4564 switch (sel) {
4565 case 0:
d9bea114 4566 gen_helper_mtc0_index(arg);
9c2149c8
TS
4567 rn = "Index";
4568 break;
4569 case 1:
7385ac0b 4570 check_insn(env, ctx, ASE_MT);
d9bea114 4571 gen_helper_mtc0_mvpcontrol(arg);
9c2149c8 4572 rn = "MVPControl";
ead9360e 4573 break;
9c2149c8 4574 case 2:
7385ac0b 4575 check_insn(env, ctx, ASE_MT);
ead9360e 4576 /* ignored */
9c2149c8 4577 rn = "MVPConf0";
ead9360e 4578 break;
9c2149c8 4579 case 3:
7385ac0b 4580 check_insn(env, ctx, ASE_MT);
ead9360e 4581 /* ignored */
9c2149c8 4582 rn = "MVPConf1";
ead9360e 4583 break;
9c2149c8
TS
4584 default:
4585 goto die;
4586 }
4587 break;
4588 case 1:
4589 switch (sel) {
4590 case 0:
2423f660 4591 /* ignored */
9c2149c8 4592 rn = "Random";
2423f660 4593 break;
9c2149c8 4594 case 1:
7385ac0b 4595 check_insn(env, ctx, ASE_MT);
d9bea114 4596 gen_helper_mtc0_vpecontrol(arg);
9c2149c8 4597 rn = "VPEControl";
ead9360e 4598 break;
9c2149c8 4599 case 2:
7385ac0b 4600 check_insn(env, ctx, ASE_MT);
d9bea114 4601 gen_helper_mtc0_vpeconf0(arg);
9c2149c8 4602 rn = "VPEConf0";
ead9360e 4603 break;
9c2149c8 4604 case 3:
7385ac0b 4605 check_insn(env, ctx, ASE_MT);
d9bea114 4606 gen_helper_mtc0_vpeconf1(arg);
9c2149c8 4607 rn = "VPEConf1";
ead9360e 4608 break;
9c2149c8 4609 case 4:
7385ac0b 4610 check_insn(env, ctx, ASE_MT);
d9bea114 4611 gen_helper_mtc0_yqmask(arg);
9c2149c8 4612 rn = "YQMask";
ead9360e 4613 break;
9c2149c8 4614 case 5:
7385ac0b 4615 check_insn(env, ctx, ASE_MT);
d9bea114 4616 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPESchedule));
9c2149c8 4617 rn = "VPESchedule";
ead9360e 4618 break;
9c2149c8 4619 case 6:
7385ac0b 4620 check_insn(env, ctx, ASE_MT);
d9bea114 4621 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_VPEScheFBack));
9c2149c8 4622 rn = "VPEScheFBack";
ead9360e 4623 break;
9c2149c8 4624 case 7:
7385ac0b 4625 check_insn(env, ctx, ASE_MT);
d9bea114 4626 gen_helper_mtc0_vpeopt(arg);
9c2149c8 4627 rn = "VPEOpt";
ead9360e 4628 break;
9c2149c8
TS
4629 default:
4630 goto die;
4631 }
4632 break;
4633 case 2:
4634 switch (sel) {
4635 case 0:
d9bea114 4636 gen_helper_mtc0_entrylo0(arg);
2423f660
TS
4637 rn = "EntryLo0";
4638 break;
9c2149c8 4639 case 1:
7385ac0b 4640 check_insn(env, ctx, ASE_MT);
d9bea114 4641 gen_helper_mtc0_tcstatus(arg);
2423f660 4642 rn = "TCStatus";
ead9360e 4643 break;
9c2149c8 4644 case 2:
7385ac0b 4645 check_insn(env, ctx, ASE_MT);
d9bea114 4646 gen_helper_mtc0_tcbind(arg);
2423f660 4647 rn = "TCBind";
ead9360e 4648 break;
9c2149c8 4649 case 3:
7385ac0b 4650 check_insn(env, ctx, ASE_MT);
d9bea114 4651 gen_helper_mtc0_tcrestart(arg);
2423f660 4652 rn = "TCRestart";
ead9360e 4653 break;
9c2149c8 4654 case 4:
7385ac0b 4655 check_insn(env, ctx, ASE_MT);
d9bea114 4656 gen_helper_mtc0_tchalt(arg);
2423f660 4657 rn = "TCHalt";
ead9360e 4658 break;
9c2149c8 4659 case 5:
7385ac0b 4660 check_insn(env, ctx, ASE_MT);
d9bea114 4661 gen_helper_mtc0_tccontext(arg);
2423f660 4662 rn = "TCContext";
ead9360e 4663 break;
9c2149c8 4664 case 6:
7385ac0b 4665 check_insn(env, ctx, ASE_MT);
d9bea114 4666 gen_helper_mtc0_tcschedule(arg);
2423f660 4667 rn = "TCSchedule";
ead9360e 4668 break;
9c2149c8 4669 case 7:
7385ac0b 4670 check_insn(env, ctx, ASE_MT);
d9bea114 4671 gen_helper_mtc0_tcschefback(arg);
2423f660 4672 rn = "TCScheFBack";
ead9360e 4673 break;
9c2149c8
TS
4674 default:
4675 goto die;
4676 }
4677 break;
4678 case 3:
4679 switch (sel) {
4680 case 0:
d9bea114 4681 gen_helper_mtc0_entrylo1(arg);
2423f660
TS
4682 rn = "EntryLo1";
4683 break;
9c2149c8
TS
4684 default:
4685 goto die;
876d4b07 4686 }
9c2149c8
TS
4687 break;
4688 case 4:
4689 switch (sel) {
4690 case 0:
d9bea114 4691 gen_helper_mtc0_context(arg);
2423f660
TS
4692 rn = "Context";
4693 break;
9c2149c8 4694 case 1:
d9bea114 4695// gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
2423f660
TS
4696 rn = "ContextConfig";
4697// break;
9c2149c8
TS
4698 default:
4699 goto die;
876d4b07 4700 }
9c2149c8
TS
4701 break;
4702 case 5:
4703 switch (sel) {
4704 case 0:
d9bea114 4705 gen_helper_mtc0_pagemask(arg);
2423f660
TS
4706 rn = "PageMask";
4707 break;
9c2149c8 4708 case 1:
e189e748 4709 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4710 gen_helper_mtc0_pagegrain(arg);
2423f660
TS
4711 rn = "PageGrain";
4712 break;
9c2149c8
TS
4713 default:
4714 goto die;
876d4b07 4715 }
9c2149c8
TS
4716 break;
4717 case 6:
4718 switch (sel) {
4719 case 0:
d9bea114 4720 gen_helper_mtc0_wired(arg);
2423f660
TS
4721 rn = "Wired";
4722 break;
9c2149c8 4723 case 1:
e189e748 4724 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4725 gen_helper_mtc0_srsconf0(arg);
2423f660 4726 rn = "SRSConf0";
ead9360e 4727 break;
9c2149c8 4728 case 2:
e189e748 4729 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4730 gen_helper_mtc0_srsconf1(arg);
2423f660 4731 rn = "SRSConf1";
ead9360e 4732 break;
9c2149c8 4733 case 3:
e189e748 4734 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4735 gen_helper_mtc0_srsconf2(arg);
2423f660 4736 rn = "SRSConf2";
ead9360e 4737 break;
9c2149c8 4738 case 4:
e189e748 4739 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4740 gen_helper_mtc0_srsconf3(arg);
2423f660 4741 rn = "SRSConf3";
ead9360e 4742 break;
9c2149c8 4743 case 5:
e189e748 4744 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4745 gen_helper_mtc0_srsconf4(arg);
2423f660 4746 rn = "SRSConf4";
ead9360e 4747 break;
9c2149c8
TS
4748 default:
4749 goto die;
876d4b07 4750 }
9c2149c8
TS
4751 break;
4752 case 7:
4753 switch (sel) {
4754 case 0:
e189e748 4755 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4756 gen_helper_mtc0_hwrena(arg);
2423f660
TS
4757 rn = "HWREna";
4758 break;
9c2149c8
TS
4759 default:
4760 goto die;
876d4b07 4761 }
9c2149c8
TS
4762 break;
4763 case 8:
4764 /* ignored */
f0b3f3ae 4765 rn = "BadVAddr";
9c2149c8
TS
4766 break;
4767 case 9:
4768 switch (sel) {
4769 case 0:
d9bea114 4770 gen_helper_mtc0_count(arg);
2423f660
TS
4771 rn = "Count";
4772 break;
876d4b07 4773 /* 6,7 are implementation dependent */
9c2149c8
TS
4774 default:
4775 goto die;
876d4b07
TS
4776 }
4777 /* Stop translation as we may have switched the execution mode */
4778 ctx->bstate = BS_STOP;
9c2149c8
TS
4779 break;
4780 case 10:
4781 switch (sel) {
4782 case 0:
d9bea114 4783 gen_helper_mtc0_entryhi(arg);
2423f660
TS
4784 rn = "EntryHi";
4785 break;
9c2149c8
TS
4786 default:
4787 goto die;
876d4b07 4788 }
9c2149c8
TS
4789 break;
4790 case 11:
4791 switch (sel) {
4792 case 0:
d9bea114 4793 gen_helper_mtc0_compare(arg);
2423f660
TS
4794 rn = "Compare";
4795 break;
876d4b07 4796 /* 6,7 are implementation dependent */
9c2149c8
TS
4797 default:
4798 goto die;
876d4b07 4799 }
de9a95f0
AJ
4800 /* Stop translation as we may have switched the execution mode */
4801 ctx->bstate = BS_STOP;
9c2149c8
TS
4802 break;
4803 case 12:
4804 switch (sel) {
4805 case 0:
867abc7e 4806 save_cpu_state(ctx, 1);
d9bea114 4807 gen_helper_mtc0_status(arg);
8487327a
TS
4808 /* BS_STOP isn't good enough here, hflags may have changed. */
4809 gen_save_pc(ctx->pc + 4);
4810 ctx->bstate = BS_EXCP;
2423f660
TS
4811 rn = "Status";
4812 break;
9c2149c8 4813 case 1:
e189e748 4814 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4815 gen_helper_mtc0_intctl(arg);
8487327a
TS
4816 /* Stop translation as we may have switched the execution mode */
4817 ctx->bstate = BS_STOP;
2423f660
TS
4818 rn = "IntCtl";
4819 break;
9c2149c8 4820 case 2:
e189e748 4821 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4822 gen_helper_mtc0_srsctl(arg);
8487327a
TS
4823 /* Stop translation as we may have switched the execution mode */
4824 ctx->bstate = BS_STOP;
2423f660
TS
4825 rn = "SRSCtl";
4826 break;
9c2149c8 4827 case 3:
e189e748 4828 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4829 gen_mtc0_store32(arg, offsetof(CPUState, CP0_SRSMap));
8487327a
TS
4830 /* Stop translation as we may have switched the execution mode */
4831 ctx->bstate = BS_STOP;
2423f660
TS
4832 rn = "SRSMap";
4833 break;
4834 default:
9c2149c8 4835 goto die;
876d4b07 4836 }
9c2149c8
TS
4837 break;
4838 case 13:
4839 switch (sel) {
4840 case 0:
867abc7e 4841 save_cpu_state(ctx, 1);
d9bea114 4842 gen_helper_mtc0_cause(arg);
2423f660
TS
4843 rn = "Cause";
4844 break;
9c2149c8
TS
4845 default:
4846 goto die;
876d4b07 4847 }
9c2149c8
TS
4848 break;
4849 case 14:
4850 switch (sel) {
4851 case 0:
d9bea114 4852 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_EPC));
2423f660
TS
4853 rn = "EPC";
4854 break;
9c2149c8
TS
4855 default:
4856 goto die;
876d4b07 4857 }
9c2149c8
TS
4858 break;
4859 case 15:
4860 switch (sel) {
4861 case 0:
2423f660
TS
4862 /* ignored */
4863 rn = "PRid";
4864 break;
9c2149c8 4865 case 1:
e189e748 4866 check_insn(env, ctx, ISA_MIPS32R2);
d9bea114 4867 gen_helper_mtc0_ebase(arg);
2423f660
TS
4868 rn = "EBase";
4869 break;
9c2149c8
TS
4870 default:
4871 goto die;
876d4b07 4872 }
9c2149c8
TS
4873 break;
4874 case 16:
4875 switch (sel) {
4876 case 0:
d9bea114 4877 gen_helper_mtc0_config0(arg);
9c2149c8 4878 rn = "Config";
2423f660
TS
4879 /* Stop translation as we may have switched the execution mode */
4880 ctx->bstate = BS_STOP;
9c2149c8
TS
4881 break;
4882 case 1:
1fc7bf6e 4883 /* ignored, read only */
9c2149c8
TS
4884 rn = "Config1";
4885 break;
4886 case 2:
d9bea114 4887 gen_helper_mtc0_config2(arg);
9c2149c8 4888 rn = "Config2";
2423f660
TS
4889 /* Stop translation as we may have switched the execution mode */
4890 ctx->bstate = BS_STOP;
9c2149c8
TS
4891 break;
4892 case 3:
2423f660 4893 /* ignored */
9c2149c8
TS
4894 rn = "Config3";
4895 break;
4896 /* 6,7 are implementation dependent */
4897 default:
4898 rn = "Invalid config selector";
4899 goto die;
4900 }
9c2149c8
TS
4901 break;
4902 case 17:
4903 switch (sel) {
4904 case 0:
2a6e32dd 4905 gen_helper_mtc0_lladdr(arg);
2423f660
TS
4906 rn = "LLAddr";
4907 break;
9c2149c8
TS
4908 default:
4909 goto die;
4910 }
4911 break;
4912 case 18:
4913 switch (sel) {
fd88b6ab 4914 case 0 ... 7:
d9bea114 4915 gen_helper_1i(mtc0_watchlo, arg, sel);
2423f660
TS
4916 rn = "WatchLo";
4917 break;
9c2149c8
TS
4918 default:
4919 goto die;
4920 }
4921 break;
4922 case 19:
4923 switch (sel) {
fd88b6ab 4924 case 0 ... 7:
d9bea114 4925 gen_helper_1i(mtc0_watchhi, arg, sel);
2423f660
TS
4926 rn = "WatchHi";
4927 break;
9c2149c8
TS
4928 default:
4929 goto die;
4930 }
4931 break;
4932 case 20:
4933 switch (sel) {
4934 case 0:
e189e748 4935 check_insn(env, ctx, ISA_MIPS3);
d9bea114 4936 gen_helper_mtc0_xcontext(arg);
2423f660
TS
4937 rn = "XContext";
4938 break;
9c2149c8
TS
4939 default:
4940 goto die;
4941 }
4942 break;
4943 case 21:
4944 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4945 switch (sel) {
4946 case 0:
d9bea114 4947 gen_helper_mtc0_framemask(arg);
2423f660
TS
4948 rn = "Framemask";
4949 break;
9c2149c8
TS
4950 default:
4951 goto die;
4952 }
4953 break;
4954 case 22:
4955 /* ignored */
4956 rn = "Diagnostic"; /* implementation dependent */
876d4b07 4957 break;
9c2149c8
TS
4958 case 23:
4959 switch (sel) {
4960 case 0:
d9bea114 4961 gen_helper_mtc0_debug(arg); /* EJTAG support */
8487327a
TS
4962 /* BS_STOP isn't good enough here, hflags may have changed. */
4963 gen_save_pc(ctx->pc + 4);
4964 ctx->bstate = BS_EXCP;
2423f660
TS
4965 rn = "Debug";
4966 break;
9c2149c8 4967 case 1:
d9bea114 4968// gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
8487327a
TS
4969 /* Stop translation as we may have switched the execution mode */
4970 ctx->bstate = BS_STOP;
2423f660
TS
4971 rn = "TraceControl";
4972// break;
9c2149c8 4973 case 2:
d9bea114 4974// gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
8487327a
TS
4975 /* Stop translation as we may have switched the execution mode */
4976 ctx->bstate = BS_STOP;
2423f660
TS
4977 rn = "TraceControl2";
4978// break;
9c2149c8 4979 case 3:
d9bea114 4980// gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
8487327a
TS
4981 /* Stop translation as we may have switched the execution mode */
4982 ctx->bstate = BS_STOP;
2423f660
TS
4983 rn = "UserTraceData";
4984// break;
9c2149c8 4985 case 4:
d9bea114 4986// gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
8487327a
TS
4987 /* Stop translation as we may have switched the execution mode */
4988 ctx->bstate = BS_STOP;
2423f660
TS
4989 rn = "TraceBPC";
4990// break;
9c2149c8
TS
4991 default:
4992 goto die;
4993 }
9c2149c8
TS
4994 break;
4995 case 24:
4996 switch (sel) {
4997 case 0:
f1aa6320 4998 /* EJTAG support */
d9bea114 4999 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_DEPC));
2423f660
TS
5000 rn = "DEPC";
5001 break;
9c2149c8
TS
5002 default:
5003 goto die;
5004 }
5005 break;
5006 case 25:
5007 switch (sel) {
5008 case 0:
d9bea114 5009 gen_helper_mtc0_performance0(arg);
2423f660
TS
5010 rn = "Performance0";
5011 break;
9c2149c8 5012 case 1:
d9bea114 5013// gen_helper_mtc0_performance1(arg);
2423f660
TS
5014 rn = "Performance1";
5015// break;
9c2149c8 5016 case 2:
d9bea114 5017// gen_helper_mtc0_performance2(arg);
2423f660
TS
5018 rn = "Performance2";
5019// break;
9c2149c8 5020 case 3:
d9bea114 5021// gen_helper_mtc0_performance3(arg);
2423f660
TS
5022 rn = "Performance3";
5023// break;
9c2149c8 5024 case 4:
d9bea114 5025// gen_helper_mtc0_performance4(arg);
2423f660
TS
5026 rn = "Performance4";
5027// break;
9c2149c8 5028 case 5:
d9bea114 5029// gen_helper_mtc0_performance5(arg);
2423f660
TS
5030 rn = "Performance5";
5031// break;
9c2149c8 5032 case 6:
d9bea114 5033// gen_helper_mtc0_performance6(arg);
2423f660
TS
5034 rn = "Performance6";
5035// break;
9c2149c8 5036 case 7:
d9bea114 5037// gen_helper_mtc0_performance7(arg);
2423f660
TS
5038 rn = "Performance7";
5039// break;
9c2149c8
TS
5040 default:
5041 goto die;
5042 }
876d4b07 5043 break;
9c2149c8 5044 case 26:
876d4b07 5045 /* ignored */
9c2149c8 5046 rn = "ECC";
876d4b07 5047 break;
9c2149c8
TS
5048 case 27:
5049 switch (sel) {
5050 case 0 ... 3:
2423f660
TS
5051 /* ignored */
5052 rn = "CacheErr";
5053 break;
9c2149c8
TS
5054 default:
5055 goto die;
5056 }
876d4b07 5057 break;
9c2149c8
TS
5058 case 28:
5059 switch (sel) {
5060 case 0:
5061 case 2:
5062 case 4:
5063 case 6:
d9bea114 5064 gen_helper_mtc0_taglo(arg);
9c2149c8
TS
5065 rn = "TagLo";
5066 break;
5067 case 1:
5068 case 3:
5069 case 5:
5070 case 7:
d9bea114 5071 gen_helper_mtc0_datalo(arg);
9c2149c8
TS
5072 rn = "DataLo";
5073 break;
5074 default:
5075 goto die;
5076 }
5077 break;
5078 case 29:
5079 switch (sel) {
5080 case 0:
5081 case 2:
5082 case 4:
5083 case 6:
d9bea114 5084 gen_helper_mtc0_taghi(arg);
9c2149c8
TS
5085 rn = "TagHi";
5086 break;
5087 case 1:
5088 case 3:
5089 case 5:
5090 case 7:
d9bea114 5091 gen_helper_mtc0_datahi(arg);
9c2149c8
TS
5092 rn = "DataHi";
5093 break;
5094 default:
5095 rn = "invalid sel";
5096 goto die;
5097 }
876d4b07 5098 break;
9c2149c8
TS
5099 case 30:
5100 switch (sel) {
5101 case 0:
d9bea114 5102 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUState, CP0_ErrorEPC));
2423f660
TS
5103 rn = "ErrorEPC";
5104 break;
9c2149c8
TS
5105 default:
5106 goto die;
5107 }
5108 break;
5109 case 31:
5110 switch (sel) {
5111 case 0:
f1aa6320 5112 /* EJTAG support */
d9bea114 5113 gen_mtc0_store32(arg, offsetof(CPUState, CP0_DESAVE));
2423f660
TS
5114 rn = "DESAVE";
5115 break;
9c2149c8
TS
5116 default:
5117 goto die;
5118 }
876d4b07
TS
5119 /* Stop translation as we may have switched the execution mode */
5120 ctx->bstate = BS_STOP;
9c2149c8
TS
5121 break;
5122 default:
876d4b07 5123 goto die;
9c2149c8 5124 }
d12d51d5 5125 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
bf20dc07 5126 /* For simplicity assume that all writes can cause interrupts. */
2e70f6ef
PB
5127 if (use_icount) {
5128 gen_io_end();
5129 ctx->bstate = BS_STOP;
5130 }
9c2149c8
TS
5131 return;
5132
5133die:
d12d51d5 5134 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
9c2149c8
TS
5135 generate_exception(ctx, EXCP_RI);
5136}
d26bc211 5137#endif /* TARGET_MIPS64 */
9c2149c8 5138
6c5c1e20 5139static void gen_mftr(CPUState *env, DisasContext *ctx, int rt, int rd,
ead9360e
TS
5140 int u, int sel, int h)
5141{
5142 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5143 TCGv t0 = tcg_temp_local_new();
ead9360e
TS
5144
5145 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5146 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5147 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
1a3fd9c3 5148 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5149 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5150 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
1a3fd9c3 5151 tcg_gen_movi_tl(t0, -1);
ead9360e
TS
5152 else if (u == 0) {
5153 switch (rt) {
5154 case 2:
5155 switch (sel) {
5156 case 1:
a7812ae4 5157 gen_helper_mftc0_tcstatus(t0);
ead9360e
TS
5158 break;
5159 case 2:
a7812ae4 5160 gen_helper_mftc0_tcbind(t0);
ead9360e
TS
5161 break;
5162 case 3:
a7812ae4 5163 gen_helper_mftc0_tcrestart(t0);
ead9360e
TS
5164 break;
5165 case 4:
a7812ae4 5166 gen_helper_mftc0_tchalt(t0);
ead9360e
TS
5167 break;
5168 case 5:
a7812ae4 5169 gen_helper_mftc0_tccontext(t0);
ead9360e
TS
5170 break;
5171 case 6:
a7812ae4 5172 gen_helper_mftc0_tcschedule(t0);
ead9360e
TS
5173 break;
5174 case 7:
a7812ae4 5175 gen_helper_mftc0_tcschefback(t0);
ead9360e
TS
5176 break;
5177 default:
1a3fd9c3 5178 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5179 break;
5180 }
5181 break;
5182 case 10:
5183 switch (sel) {
5184 case 0:
a7812ae4 5185 gen_helper_mftc0_entryhi(t0);
ead9360e
TS
5186 break;
5187 default:
1a3fd9c3 5188 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5189 break;
5190 }
5191 case 12:
5192 switch (sel) {
5193 case 0:
a7812ae4 5194 gen_helper_mftc0_status(t0);
ead9360e
TS
5195 break;
5196 default:
1a3fd9c3 5197 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5198 break;
5199 }
5200 case 23:
5201 switch (sel) {
5202 case 0:
a7812ae4 5203 gen_helper_mftc0_debug(t0);
ead9360e
TS
5204 break;
5205 default:
1a3fd9c3 5206 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5207 break;
5208 }
5209 break;
5210 default:
1a3fd9c3 5211 gen_mfc0(env, ctx, t0, rt, sel);
ead9360e
TS
5212 }
5213 } else switch (sel) {
5214 /* GPR registers. */
5215 case 0:
a7812ae4 5216 gen_helper_1i(mftgpr, t0, rt);
ead9360e
TS
5217 break;
5218 /* Auxiliary CPU registers */
5219 case 1:
5220 switch (rt) {
5221 case 0:
a7812ae4 5222 gen_helper_1i(mftlo, t0, 0);
ead9360e
TS
5223 break;
5224 case 1:
a7812ae4 5225 gen_helper_1i(mfthi, t0, 0);
ead9360e
TS
5226 break;
5227 case 2:
a7812ae4 5228 gen_helper_1i(mftacx, t0, 0);
ead9360e
TS
5229 break;
5230 case 4:
a7812ae4 5231 gen_helper_1i(mftlo, t0, 1);
ead9360e
TS
5232 break;
5233 case 5:
a7812ae4 5234 gen_helper_1i(mfthi, t0, 1);
ead9360e
TS
5235 break;
5236 case 6:
a7812ae4 5237 gen_helper_1i(mftacx, t0, 1);
ead9360e
TS
5238 break;
5239 case 8:
a7812ae4 5240 gen_helper_1i(mftlo, t0, 2);
ead9360e
TS
5241 break;
5242 case 9:
a7812ae4 5243 gen_helper_1i(mfthi, t0, 2);
ead9360e
TS
5244 break;
5245 case 10:
a7812ae4 5246 gen_helper_1i(mftacx, t0, 2);
ead9360e
TS
5247 break;
5248 case 12:
a7812ae4 5249 gen_helper_1i(mftlo, t0, 3);
ead9360e
TS
5250 break;
5251 case 13:
a7812ae4 5252 gen_helper_1i(mfthi, t0, 3);
ead9360e
TS
5253 break;
5254 case 14:
a7812ae4 5255 gen_helper_1i(mftacx, t0, 3);
ead9360e
TS
5256 break;
5257 case 16:
a7812ae4 5258 gen_helper_mftdsp(t0);
ead9360e
TS
5259 break;
5260 default:
5261 goto die;
5262 }
5263 break;
5264 /* Floating point (COP1). */
5265 case 2:
5266 /* XXX: For now we support only a single FPU context. */
5267 if (h == 0) {
a7812ae4 5268 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5269
5270 gen_load_fpr32(fp0, rt);
5271 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5272 tcg_temp_free_i32(fp0);
ead9360e 5273 } else {
a7812ae4 5274 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5275
5276 gen_load_fpr32h(fp0, rt);
5277 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5278 tcg_temp_free_i32(fp0);
ead9360e
TS
5279 }
5280 break;
5281 case 3:
5282 /* XXX: For now we support only a single FPU context. */
a7812ae4 5283 gen_helper_1i(cfc1, t0, rt);
ead9360e
TS
5284 break;
5285 /* COP2: Not implemented. */
5286 case 4:
5287 case 5:
5288 /* fall through */
5289 default:
5290 goto die;
5291 }
d12d51d5 5292 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
1a3fd9c3
TS
5293 gen_store_gpr(t0, rd);
5294 tcg_temp_free(t0);
ead9360e
TS
5295 return;
5296
5297die:
1a3fd9c3 5298 tcg_temp_free(t0);
d12d51d5 5299 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
ead9360e
TS
5300 generate_exception(ctx, EXCP_RI);
5301}
5302
6c5c1e20 5303static void gen_mttr(CPUState *env, DisasContext *ctx, int rd, int rt,
ead9360e
TS
5304 int u, int sel, int h)
5305{
5306 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
a7812ae4 5307 TCGv t0 = tcg_temp_local_new();
ead9360e 5308
1a3fd9c3 5309 gen_load_gpr(t0, rt);
ead9360e 5310 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
b5dc7732
TS
5311 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5312 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
ead9360e
TS
5313 /* NOP */ ;
5314 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5315 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5316 /* NOP */ ;
5317 else if (u == 0) {
5318 switch (rd) {
5319 case 2:
5320 switch (sel) {
5321 case 1:
a7812ae4 5322 gen_helper_mttc0_tcstatus(t0);
ead9360e
TS
5323 break;
5324 case 2:
a7812ae4 5325 gen_helper_mttc0_tcbind(t0);
ead9360e
TS
5326 break;
5327 case 3:
a7812ae4 5328 gen_helper_mttc0_tcrestart(t0);
ead9360e
TS
5329 break;
5330 case 4:
a7812ae4 5331 gen_helper_mttc0_tchalt(t0);
ead9360e
TS
5332 break;
5333 case 5:
a7812ae4 5334 gen_helper_mttc0_tccontext(t0);
ead9360e
TS
5335 break;
5336 case 6:
a7812ae4 5337 gen_helper_mttc0_tcschedule(t0);
ead9360e
TS
5338 break;
5339 case 7:
a7812ae4 5340 gen_helper_mttc0_tcschefback(t0);
ead9360e
TS
5341 break;
5342 default:
1a3fd9c3 5343 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5344 break;
5345 }
5346 break;
5347 case 10:
5348 switch (sel) {
5349 case 0:
a7812ae4 5350 gen_helper_mttc0_entryhi(t0);
ead9360e
TS
5351 break;
5352 default:
1a3fd9c3 5353 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5354 break;
5355 }
5356 case 12:
5357 switch (sel) {
5358 case 0:
a7812ae4 5359 gen_helper_mttc0_status(t0);
ead9360e
TS
5360 break;
5361 default:
1a3fd9c3 5362 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5363 break;
5364 }
5365 case 23:
5366 switch (sel) {
5367 case 0:
a7812ae4 5368 gen_helper_mttc0_debug(t0);
ead9360e
TS
5369 break;
5370 default:
1a3fd9c3 5371 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5372 break;
5373 }
5374 break;
5375 default:
1a3fd9c3 5376 gen_mtc0(env, ctx, t0, rd, sel);
ead9360e
TS
5377 }
5378 } else switch (sel) {
5379 /* GPR registers. */
5380 case 0:
a7812ae4 5381 gen_helper_1i(mttgpr, t0, rd);
ead9360e
TS
5382 break;
5383 /* Auxiliary CPU registers */
5384 case 1:
5385 switch (rd) {
5386 case 0:
a7812ae4 5387 gen_helper_1i(mttlo, t0, 0);
ead9360e
TS
5388 break;
5389 case 1:
a7812ae4 5390 gen_helper_1i(mtthi, t0, 0);
ead9360e
TS
5391 break;
5392 case 2:
a7812ae4 5393 gen_helper_1i(mttacx, t0, 0);
ead9360e
TS
5394 break;
5395 case 4:
a7812ae4 5396 gen_helper_1i(mttlo, t0, 1);
ead9360e
TS
5397 break;
5398 case 5:
a7812ae4 5399 gen_helper_1i(mtthi, t0, 1);
ead9360e
TS
5400 break;
5401 case 6:
a7812ae4 5402 gen_helper_1i(mttacx, t0, 1);
ead9360e
TS
5403 break;
5404 case 8:
a7812ae4 5405 gen_helper_1i(mttlo, t0, 2);
ead9360e
TS
5406 break;
5407 case 9:
a7812ae4 5408 gen_helper_1i(mtthi, t0, 2);
ead9360e
TS
5409 break;
5410 case 10:
a7812ae4 5411 gen_helper_1i(mttacx, t0, 2);
ead9360e
TS
5412 break;
5413 case 12:
a7812ae4 5414 gen_helper_1i(mttlo, t0, 3);
ead9360e
TS
5415 break;
5416 case 13:
a7812ae4 5417 gen_helper_1i(mtthi, t0, 3);
ead9360e
TS
5418 break;
5419 case 14:
a7812ae4 5420 gen_helper_1i(mttacx, t0, 3);
ead9360e
TS
5421 break;
5422 case 16:
a7812ae4 5423 gen_helper_mttdsp(t0);
ead9360e
TS
5424 break;
5425 default:
5426 goto die;
5427 }
5428 break;
5429 /* Floating point (COP1). */
5430 case 2:
5431 /* XXX: For now we support only a single FPU context. */
5432 if (h == 0) {
a7812ae4 5433 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5434
5435 tcg_gen_trunc_tl_i32(fp0, t0);
5436 gen_store_fpr32(fp0, rd);
a7812ae4 5437 tcg_temp_free_i32(fp0);
ead9360e 5438 } else {
a7812ae4 5439 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5440
5441 tcg_gen_trunc_tl_i32(fp0, t0);
5442 gen_store_fpr32h(fp0, rd);
a7812ae4 5443 tcg_temp_free_i32(fp0);
ead9360e
TS
5444 }
5445 break;
5446 case 3:
5447 /* XXX: For now we support only a single FPU context. */
a7812ae4 5448 gen_helper_1i(ctc1, t0, rd);
ead9360e
TS
5449 break;
5450 /* COP2: Not implemented. */
5451 case 4:
5452 case 5:
5453 /* fall through */
5454 default:
5455 goto die;
5456 }
d12d51d5 5457 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
1a3fd9c3 5458 tcg_temp_free(t0);
ead9360e
TS
5459 return;
5460
5461die:
1a3fd9c3 5462 tcg_temp_free(t0);
d12d51d5 5463 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
ead9360e
TS
5464 generate_exception(ctx, EXCP_RI);
5465}
5466
29929e34 5467static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6af0bf9c 5468{
287c4b84 5469 const char *opn = "ldst";
6af0bf9c 5470
6af0bf9c
FB
5471 switch (opc) {
5472 case OPC_MFC0:
5473 if (rt == 0) {
ead9360e 5474 /* Treat as NOP. */
6af0bf9c
FB
5475 return;
5476 }
1fc7bf6e 5477 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6af0bf9c
FB
5478 opn = "mfc0";
5479 break;
5480 case OPC_MTC0:
1a3fd9c3 5481 {
1fc7bf6e 5482 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5483
5484 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5485 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5486 tcg_temp_free(t0);
5487 }
6af0bf9c
FB
5488 opn = "mtc0";
5489 break;
d26bc211 5490#if defined(TARGET_MIPS64)
9c2149c8 5491 case OPC_DMFC0:
e189e748 5492 check_insn(env, ctx, ISA_MIPS3);
9c2149c8 5493 if (rt == 0) {
ead9360e 5494 /* Treat as NOP. */
9c2149c8
TS
5495 return;
5496 }
1fc7bf6e 5497 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9c2149c8
TS
5498 opn = "dmfc0";
5499 break;
5500 case OPC_DMTC0:
e189e748 5501 check_insn(env, ctx, ISA_MIPS3);
1a3fd9c3 5502 {
1fc7bf6e 5503 TCGv t0 = tcg_temp_new();
1a3fd9c3
TS
5504
5505 gen_load_gpr(t0, rt);
1a3fd9c3
TS
5506 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5507 tcg_temp_free(t0);
5508 }
9c2149c8
TS
5509 opn = "dmtc0";
5510 break;
534ce69f 5511#endif
ead9360e 5512 case OPC_MFTR:
7385ac0b 5513 check_insn(env, ctx, ASE_MT);
ead9360e
TS
5514 if (rd == 0) {
5515 /* Treat as NOP. */
5516 return;
5517 }
6c5c1e20 5518 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
ead9360e 5519 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
ead9360e
TS
5520 opn = "mftr";
5521 break;
5522 case OPC_MTTR:
7385ac0b 5523 check_insn(env, ctx, ASE_MT);
6c5c1e20 5524 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
ead9360e
TS
5525 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5526 opn = "mttr";
5527 break;
6af0bf9c 5528 case OPC_TLBWI:
6af0bf9c 5529 opn = "tlbwi";
c01fccd2 5530 if (!env->tlb->helper_tlbwi)
29929e34 5531 goto die;
a7812ae4 5532 gen_helper_tlbwi();
6af0bf9c
FB
5533 break;
5534 case OPC_TLBWR:
6af0bf9c 5535 opn = "tlbwr";
c01fccd2 5536 if (!env->tlb->helper_tlbwr)
29929e34 5537 goto die;
a7812ae4 5538 gen_helper_tlbwr();
6af0bf9c
FB
5539 break;
5540 case OPC_TLBP:
6af0bf9c 5541 opn = "tlbp";
c01fccd2 5542 if (!env->tlb->helper_tlbp)
29929e34 5543 goto die;
a7812ae4 5544 gen_helper_tlbp();
6af0bf9c
FB
5545 break;
5546 case OPC_TLBR:
6af0bf9c 5547 opn = "tlbr";
c01fccd2 5548 if (!env->tlb->helper_tlbr)
29929e34 5549 goto die;
a7812ae4 5550 gen_helper_tlbr();
6af0bf9c 5551 break;
6af0bf9c
FB
5552 case OPC_ERET:
5553 opn = "eret";
e189e748 5554 check_insn(env, ctx, ISA_MIPS2);
a7812ae4 5555 gen_helper_eret();
6af0bf9c
FB
5556 ctx->bstate = BS_EXCP;
5557 break;
5558 case OPC_DERET:
5559 opn = "deret";
e189e748 5560 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c 5561 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
923617a3 5562 MIPS_INVAL(opn);
6af0bf9c
FB
5563 generate_exception(ctx, EXCP_RI);
5564 } else {
a7812ae4 5565 gen_helper_deret();
6af0bf9c
FB
5566 ctx->bstate = BS_EXCP;
5567 }
5568 break;
4ad40f36
FB
5569 case OPC_WAIT:
5570 opn = "wait";
e189e748 5571 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
4ad40f36
FB
5572 /* If we get an exception, we want to restart at next instruction */
5573 ctx->pc += 4;
5574 save_cpu_state(ctx, 1);
5575 ctx->pc -= 4;
a7812ae4 5576 gen_helper_wait();
4ad40f36
FB
5577 ctx->bstate = BS_EXCP;
5578 break;
6af0bf9c 5579 default:
29929e34 5580 die:
923617a3 5581 MIPS_INVAL(opn);
6af0bf9c
FB
5582 generate_exception(ctx, EXCP_RI);
5583 return;
5584 }
5585 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
5586}
f1aa6320 5587#endif /* !CONFIG_USER_ONLY */
6af0bf9c 5588
6ea83fed 5589/* CP1 Branches (before delay slot) */
e189e748 5590static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
5a5012ec 5591 int32_t cc, int32_t offset)
6ea83fed
FB
5592{
5593 target_ulong btarget;
923617a3 5594 const char *opn = "cp1 cond branch";
a7812ae4 5595 TCGv_i32 t0 = tcg_temp_new_i32();
6ea83fed 5596
e189e748
TS
5597 if (cc != 0)
5598 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
5599
6ea83fed
FB
5600 btarget = ctx->pc + 4 + offset;
5601
7a387fff
TS
5602 switch (op) {
5603 case OPC_BC1F:
d94536f4
AJ
5604 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5605 tcg_gen_not_i32(t0, t0);
5606 tcg_gen_andi_i32(t0, t0, 1);
5607 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5608 opn = "bc1f";
6ea83fed 5609 goto not_likely;
7a387fff 5610 case OPC_BC1FL:
d94536f4
AJ
5611 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5612 tcg_gen_not_i32(t0, t0);
5613 tcg_gen_andi_i32(t0, t0, 1);
5614 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5615 opn = "bc1fl";
6ea83fed 5616 goto likely;
7a387fff 5617 case OPC_BC1T:
d94536f4
AJ
5618 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5619 tcg_gen_andi_i32(t0, t0, 1);
5620 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5621 opn = "bc1t";
5a5012ec 5622 goto not_likely;
7a387fff 5623 case OPC_BC1TL:
d94536f4
AJ
5624 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5625 tcg_gen_andi_i32(t0, t0, 1);
5626 tcg_gen_extu_i32_tl(bcond, t0);
923617a3 5627 opn = "bc1tl";
6ea83fed
FB
5628 likely:
5629 ctx->hflags |= MIPS_HFLAG_BL;
5630 break;
5a5012ec 5631 case OPC_BC1FANY2:
a16336e4 5632 {
d94536f4
AJ
5633 TCGv_i32 t1 = tcg_temp_new_i32();
5634 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5635 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
deb4203d 5636 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 5637 tcg_temp_free_i32(t1);
d94536f4
AJ
5638 tcg_gen_andi_i32(t0, t0, 1);
5639 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5640 }
fd4a04eb 5641 opn = "bc1any2f";
5a5012ec
TS
5642 goto not_likely;
5643 case OPC_BC1TANY2:
a16336e4 5644 {
d94536f4
AJ
5645 TCGv_i32 t1 = tcg_temp_new_i32();
5646 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5647 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5648 tcg_gen_or_i32(t0, t0, t1);
5649 tcg_temp_free_i32(t1);
5650 tcg_gen_andi_i32(t0, t0, 1);
5651 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5652 }
fd4a04eb 5653 opn = "bc1any2t";
5a5012ec
TS
5654 goto not_likely;
5655 case OPC_BC1FANY4:
a16336e4 5656 {
d94536f4
AJ
5657 TCGv_i32 t1 = tcg_temp_new_i32();
5658 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5659 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5660 tcg_gen_or_i32(t0, t0, t1);
5661 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5662 tcg_gen_or_i32(t0, t0, t1);
5663 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
deb4203d 5664 tcg_gen_nor_i32(t0, t0, t1);
d94536f4 5665 tcg_temp_free_i32(t1);
d94536f4
AJ
5666 tcg_gen_andi_i32(t0, t0, 1);
5667 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5668 }
fd4a04eb 5669 opn = "bc1any4f";
5a5012ec
TS
5670 goto not_likely;
5671 case OPC_BC1TANY4:
a16336e4 5672 {
d94536f4
AJ
5673 TCGv_i32 t1 = tcg_temp_new_i32();
5674 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
5675 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
5676 tcg_gen_or_i32(t0, t0, t1);
5677 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
5678 tcg_gen_or_i32(t0, t0, t1);
5679 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
5680 tcg_gen_or_i32(t0, t0, t1);
5681 tcg_temp_free_i32(t1);
5682 tcg_gen_andi_i32(t0, t0, 1);
5683 tcg_gen_extu_i32_tl(bcond, t0);
a16336e4 5684 }
fd4a04eb 5685 opn = "bc1any4t";
5a5012ec
TS
5686 not_likely:
5687 ctx->hflags |= MIPS_HFLAG_BC;
5a5012ec
TS
5688 break;
5689 default:
923617a3 5690 MIPS_INVAL(opn);
e397ee33 5691 generate_exception (ctx, EXCP_RI);
6c5c1e20 5692 goto out;
6ea83fed 5693 }
923617a3 5694 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6ea83fed
FB
5695 ctx->hflags, btarget);
5696 ctx->btarget = btarget;
6c5c1e20
TS
5697
5698 out:
a7812ae4 5699 tcg_temp_free_i32(t0);
6ea83fed
FB
5700}
5701
6af0bf9c 5702/* Coprocessor 1 (FPU) */
5a5012ec 5703
5a5012ec
TS
5704#define FOP(func, fmt) (((fmt) << 21) | (func))
5705
7a387fff 5706static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6ea83fed 5707{
923617a3 5708 const char *opn = "cp1 move";
72c3a3ee 5709 TCGv t0 = tcg_temp_new();
6ea83fed
FB
5710
5711 switch (opc) {
5712 case OPC_MFC1:
b6d96bed 5713 {
a7812ae4 5714 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5715
5716 gen_load_fpr32(fp0, fs);
5717 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5718 tcg_temp_free_i32(fp0);
6958549d 5719 }
6c5c1e20 5720 gen_store_gpr(t0, rt);
6ea83fed
FB
5721 opn = "mfc1";
5722 break;
5723 case OPC_MTC1:
6c5c1e20 5724 gen_load_gpr(t0, rt);
b6d96bed 5725 {
a7812ae4 5726 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5727
5728 tcg_gen_trunc_tl_i32(fp0, t0);
5729 gen_store_fpr32(fp0, fs);
a7812ae4 5730 tcg_temp_free_i32(fp0);
6958549d 5731 }
6ea83fed
FB
5732 opn = "mtc1";
5733 break;
5734 case OPC_CFC1:
a7812ae4 5735 gen_helper_1i(cfc1, t0, fs);
6c5c1e20 5736 gen_store_gpr(t0, rt);
6ea83fed
FB
5737 opn = "cfc1";
5738 break;
5739 case OPC_CTC1:
6c5c1e20 5740 gen_load_gpr(t0, rt);
a7812ae4 5741 gen_helper_1i(ctc1, t0, fs);
6ea83fed
FB
5742 opn = "ctc1";
5743 break;
72c3a3ee 5744#if defined(TARGET_MIPS64)
9c2149c8 5745 case OPC_DMFC1:
72c3a3ee 5746 gen_load_fpr64(ctx, t0, fs);
6c5c1e20 5747 gen_store_gpr(t0, rt);
5a5012ec
TS
5748 opn = "dmfc1";
5749 break;
9c2149c8 5750 case OPC_DMTC1:
6c5c1e20 5751 gen_load_gpr(t0, rt);
72c3a3ee 5752 gen_store_fpr64(ctx, t0, fs);
5a5012ec
TS
5753 opn = "dmtc1";
5754 break;
72c3a3ee 5755#endif
5a5012ec 5756 case OPC_MFHC1:
b6d96bed 5757 {
a7812ae4 5758 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5759
5760 gen_load_fpr32h(fp0, fs);
5761 tcg_gen_ext_i32_tl(t0, fp0);
a7812ae4 5762 tcg_temp_free_i32(fp0);
6958549d 5763 }
6c5c1e20 5764 gen_store_gpr(t0, rt);
5a5012ec
TS
5765 opn = "mfhc1";
5766 break;
5767 case OPC_MTHC1:
6c5c1e20 5768 gen_load_gpr(t0, rt);
b6d96bed 5769 {
a7812ae4 5770 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5771
5772 tcg_gen_trunc_tl_i32(fp0, t0);
5773 gen_store_fpr32h(fp0, fs);
a7812ae4 5774 tcg_temp_free_i32(fp0);
6958549d 5775 }
5a5012ec
TS
5776 opn = "mthc1";
5777 break;
6ea83fed 5778 default:
923617a3 5779 MIPS_INVAL(opn);
e397ee33 5780 generate_exception (ctx, EXCP_RI);
6c5c1e20 5781 goto out;
6ea83fed
FB
5782 }
5783 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6c5c1e20
TS
5784
5785 out:
5786 tcg_temp_free(t0);
6ea83fed
FB
5787}
5788
5a5012ec
TS
5789static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
5790{
af58f9ca 5791 int l1;
e214b9bb 5792 TCGCond cond;
af58f9ca
AJ
5793 TCGv_i32 t0;
5794
5795 if (rd == 0) {
5796 /* Treat as NOP. */
5797 return;
5798 }
6ea83fed 5799
e214b9bb 5800 if (tf)
e214b9bb 5801 cond = TCG_COND_EQ;
27848470
TS
5802 else
5803 cond = TCG_COND_NE;
5804
af58f9ca
AJ
5805 l1 = gen_new_label();
5806 t0 = tcg_temp_new_i32();
fa31af0e 5807 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
af58f9ca 5808 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 5809 tcg_temp_free_i32(t0);
af58f9ca
AJ
5810 if (rs == 0) {
5811 tcg_gen_movi_tl(cpu_gpr[rd], 0);
5812 } else {
5813 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
5814 }
e214b9bb 5815 gen_set_label(l1);
5a5012ec
TS
5816}
5817
b6d96bed 5818static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
a16336e4 5819{
a16336e4 5820 int cond;
cbc37b28 5821 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
5822 int l1 = gen_new_label();
5823
a16336e4
TS
5824 if (tf)
5825 cond = TCG_COND_EQ;
5826 else
5827 cond = TCG_COND_NE;
5828
fa31af0e 5829 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
5830 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5831 gen_load_fpr32(t0, fs);
5832 gen_store_fpr32(t0, fd);
a16336e4 5833 gen_set_label(l1);
cbc37b28 5834 tcg_temp_free_i32(t0);
5a5012ec 5835}
a16336e4 5836
b6d96bed 5837static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
a16336e4 5838{
a16336e4 5839 int cond;
cbc37b28
AJ
5840 TCGv_i32 t0 = tcg_temp_new_i32();
5841 TCGv_i64 fp0;
a16336e4
TS
5842 int l1 = gen_new_label();
5843
a16336e4
TS
5844 if (tf)
5845 cond = TCG_COND_EQ;
5846 else
5847 cond = TCG_COND_NE;
5848
fa31af0e 5849 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28 5850 tcg_gen_brcondi_i32(cond, t0, 0, l1);
a4e8338d 5851 tcg_temp_free_i32(t0);
11f94258 5852 fp0 = tcg_temp_new_i64();
9bf3eb2c 5853 gen_load_fpr64(ctx, fp0, fs);
9bf3eb2c 5854 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 5855 tcg_temp_free_i64(fp0);
cbc37b28 5856 gen_set_label(l1);
a16336e4
TS
5857}
5858
b6d96bed 5859static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
a16336e4
TS
5860{
5861 int cond;
cbc37b28 5862 TCGv_i32 t0 = tcg_temp_new_i32();
a16336e4
TS
5863 int l1 = gen_new_label();
5864 int l2 = gen_new_label();
5865
5866 if (tf)
5867 cond = TCG_COND_EQ;
5868 else
5869 cond = TCG_COND_NE;
5870
fa31af0e 5871 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
cbc37b28
AJ
5872 tcg_gen_brcondi_i32(cond, t0, 0, l1);
5873 gen_load_fpr32(t0, fs);
5874 gen_store_fpr32(t0, fd);
a16336e4 5875 gen_set_label(l1);
9bf3eb2c 5876
fa31af0e 5877 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
cbc37b28
AJ
5878 tcg_gen_brcondi_i32(cond, t0, 0, l2);
5879 gen_load_fpr32h(t0, fs);
5880 gen_store_fpr32h(t0, fd);
52a0e9eb 5881 tcg_temp_free_i32(t0);
a16336e4 5882 gen_set_label(l2);
a16336e4
TS
5883}
5884
6ea83fed 5885
5e755519
TS
5886static void gen_farith (DisasContext *ctx, uint32_t op1,
5887 int ft, int fs, int fd, int cc)
6ea83fed 5888{
923617a3 5889 const char *opn = "farith";
6ea83fed
FB
5890 const char *condnames[] = {
5891 "c.f",
5892 "c.un",
5893 "c.eq",
5894 "c.ueq",
5895 "c.olt",
5896 "c.ult",
5897 "c.ole",
5898 "c.ule",
5899 "c.sf",
5900 "c.ngle",
5901 "c.seq",
5902 "c.ngl",
5903 "c.lt",
5904 "c.nge",
5905 "c.le",
5906 "c.ngt",
5907 };
5a1e8ffb
TS
5908 const char *condnames_abs[] = {
5909 "cabs.f",
5910 "cabs.un",
5911 "cabs.eq",
5912 "cabs.ueq",
5913 "cabs.olt",
5914 "cabs.ult",
5915 "cabs.ole",
5916 "cabs.ule",
5917 "cabs.sf",
5918 "cabs.ngle",
5919 "cabs.seq",
5920 "cabs.ngl",
5921 "cabs.lt",
5922 "cabs.nge",
5923 "cabs.le",
5924 "cabs.ngt",
5925 };
5926 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7a387fff
TS
5927 uint32_t func = ctx->opcode & 0x3f;
5928
6ea83fed 5929 switch (ctx->opcode & FOP(0x3f, 0x1f)) {
5a5012ec 5930 case FOP(0, 16):
b6d96bed 5931 {
a7812ae4
PB
5932 TCGv_i32 fp0 = tcg_temp_new_i32();
5933 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5934
5935 gen_load_fpr32(fp0, fs);
5936 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5937 gen_helper_float_add_s(fp0, fp0, fp1);
5938 tcg_temp_free_i32(fp1);
b6d96bed 5939 gen_store_fpr32(fp0, fd);
a7812ae4 5940 tcg_temp_free_i32(fp0);
b6d96bed 5941 }
5a5012ec 5942 opn = "add.s";
5a1e8ffb 5943 optype = BINOP;
5a5012ec
TS
5944 break;
5945 case FOP(1, 16):
b6d96bed 5946 {
a7812ae4
PB
5947 TCGv_i32 fp0 = tcg_temp_new_i32();
5948 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5949
5950 gen_load_fpr32(fp0, fs);
5951 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5952 gen_helper_float_sub_s(fp0, fp0, fp1);
5953 tcg_temp_free_i32(fp1);
b6d96bed 5954 gen_store_fpr32(fp0, fd);
a7812ae4 5955 tcg_temp_free_i32(fp0);
b6d96bed 5956 }
5a5012ec 5957 opn = "sub.s";
5a1e8ffb 5958 optype = BINOP;
5a5012ec
TS
5959 break;
5960 case FOP(2, 16):
b6d96bed 5961 {
a7812ae4
PB
5962 TCGv_i32 fp0 = tcg_temp_new_i32();
5963 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5964
5965 gen_load_fpr32(fp0, fs);
5966 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5967 gen_helper_float_mul_s(fp0, fp0, fp1);
5968 tcg_temp_free_i32(fp1);
b6d96bed 5969 gen_store_fpr32(fp0, fd);
a7812ae4 5970 tcg_temp_free_i32(fp0);
b6d96bed 5971 }
5a5012ec 5972 opn = "mul.s";
5a1e8ffb 5973 optype = BINOP;
5a5012ec
TS
5974 break;
5975 case FOP(3, 16):
b6d96bed 5976 {
a7812ae4
PB
5977 TCGv_i32 fp0 = tcg_temp_new_i32();
5978 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
5979
5980 gen_load_fpr32(fp0, fs);
5981 gen_load_fpr32(fp1, ft);
a7812ae4
PB
5982 gen_helper_float_div_s(fp0, fp0, fp1);
5983 tcg_temp_free_i32(fp1);
b6d96bed 5984 gen_store_fpr32(fp0, fd);
a7812ae4 5985 tcg_temp_free_i32(fp0);
b6d96bed 5986 }
5a5012ec 5987 opn = "div.s";
5a1e8ffb 5988 optype = BINOP;
5a5012ec
TS
5989 break;
5990 case FOP(4, 16):
b6d96bed 5991 {
a7812ae4 5992 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
5993
5994 gen_load_fpr32(fp0, fs);
a7812ae4 5995 gen_helper_float_sqrt_s(fp0, fp0);
b6d96bed 5996 gen_store_fpr32(fp0, fd);
a7812ae4 5997 tcg_temp_free_i32(fp0);
b6d96bed 5998 }
5a5012ec
TS
5999 opn = "sqrt.s";
6000 break;
6001 case FOP(5, 16):
b6d96bed 6002 {
a7812ae4 6003 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6004
6005 gen_load_fpr32(fp0, fs);
a7812ae4 6006 gen_helper_float_abs_s(fp0, fp0);
b6d96bed 6007 gen_store_fpr32(fp0, fd);
a7812ae4 6008 tcg_temp_free_i32(fp0);
b6d96bed 6009 }
5a5012ec
TS
6010 opn = "abs.s";
6011 break;
6012 case FOP(6, 16):
b6d96bed 6013 {
a7812ae4 6014 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6015
6016 gen_load_fpr32(fp0, fs);
6017 gen_store_fpr32(fp0, fd);
a7812ae4 6018 tcg_temp_free_i32(fp0);
b6d96bed 6019 }
5a5012ec
TS
6020 opn = "mov.s";
6021 break;
6022 case FOP(7, 16):
b6d96bed 6023 {
a7812ae4 6024 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6025
6026 gen_load_fpr32(fp0, fs);
a7812ae4 6027 gen_helper_float_chs_s(fp0, fp0);
b6d96bed 6028 gen_store_fpr32(fp0, fd);
a7812ae4 6029 tcg_temp_free_i32(fp0);
b6d96bed 6030 }
5a5012ec
TS
6031 opn = "neg.s";
6032 break;
6033 case FOP(8, 16):
5e755519 6034 check_cp1_64bitmode(ctx);
b6d96bed 6035 {
a7812ae4
PB
6036 TCGv_i32 fp32 = tcg_temp_new_i32();
6037 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6038
6039 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6040 gen_helper_float_roundl_s(fp64, fp32);
6041 tcg_temp_free_i32(fp32);
b6d96bed 6042 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6043 tcg_temp_free_i64(fp64);
b6d96bed 6044 }
5a5012ec
TS
6045 opn = "round.l.s";
6046 break;
6047 case FOP(9, 16):
5e755519 6048 check_cp1_64bitmode(ctx);
b6d96bed 6049 {
a7812ae4
PB
6050 TCGv_i32 fp32 = tcg_temp_new_i32();
6051 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6052
6053 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6054 gen_helper_float_truncl_s(fp64, fp32);
6055 tcg_temp_free_i32(fp32);
b6d96bed 6056 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6057 tcg_temp_free_i64(fp64);
b6d96bed 6058 }
5a5012ec
TS
6059 opn = "trunc.l.s";
6060 break;
6061 case FOP(10, 16):
5e755519 6062 check_cp1_64bitmode(ctx);
b6d96bed 6063 {
a7812ae4
PB
6064 TCGv_i32 fp32 = tcg_temp_new_i32();
6065 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6066
6067 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6068 gen_helper_float_ceill_s(fp64, fp32);
6069 tcg_temp_free_i32(fp32);
b6d96bed 6070 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6071 tcg_temp_free_i64(fp64);
b6d96bed 6072 }
5a5012ec
TS
6073 opn = "ceil.l.s";
6074 break;
6075 case FOP(11, 16):
5e755519 6076 check_cp1_64bitmode(ctx);
b6d96bed 6077 {
a7812ae4
PB
6078 TCGv_i32 fp32 = tcg_temp_new_i32();
6079 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6080
6081 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6082 gen_helper_float_floorl_s(fp64, fp32);
6083 tcg_temp_free_i32(fp32);
b6d96bed 6084 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6085 tcg_temp_free_i64(fp64);
b6d96bed 6086 }
5a5012ec
TS
6087 opn = "floor.l.s";
6088 break;
6089 case FOP(12, 16):
b6d96bed 6090 {
a7812ae4 6091 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6092
6093 gen_load_fpr32(fp0, fs);
a7812ae4 6094 gen_helper_float_roundw_s(fp0, fp0);
b6d96bed 6095 gen_store_fpr32(fp0, fd);
a7812ae4 6096 tcg_temp_free_i32(fp0);
b6d96bed 6097 }
5a5012ec
TS
6098 opn = "round.w.s";
6099 break;
6100 case FOP(13, 16):
b6d96bed 6101 {
a7812ae4 6102 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6103
6104 gen_load_fpr32(fp0, fs);
a7812ae4 6105 gen_helper_float_truncw_s(fp0, fp0);
b6d96bed 6106 gen_store_fpr32(fp0, fd);
a7812ae4 6107 tcg_temp_free_i32(fp0);
b6d96bed 6108 }
5a5012ec
TS
6109 opn = "trunc.w.s";
6110 break;
6111 case FOP(14, 16):
b6d96bed 6112 {
a7812ae4 6113 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6114
6115 gen_load_fpr32(fp0, fs);
a7812ae4 6116 gen_helper_float_ceilw_s(fp0, fp0);
b6d96bed 6117 gen_store_fpr32(fp0, fd);
a7812ae4 6118 tcg_temp_free_i32(fp0);
b6d96bed 6119 }
5a5012ec
TS
6120 opn = "ceil.w.s";
6121 break;
6122 case FOP(15, 16):
b6d96bed 6123 {
a7812ae4 6124 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6125
6126 gen_load_fpr32(fp0, fs);
a7812ae4 6127 gen_helper_float_floorw_s(fp0, fp0);
b6d96bed 6128 gen_store_fpr32(fp0, fd);
a7812ae4 6129 tcg_temp_free_i32(fp0);
b6d96bed 6130 }
5a5012ec
TS
6131 opn = "floor.w.s";
6132 break;
6133 case FOP(17, 16):
b6d96bed 6134 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec
TS
6135 opn = "movcf.s";
6136 break;
6137 case FOP(18, 16):
a16336e4
TS
6138 {
6139 int l1 = gen_new_label();
c9297f4d 6140 TCGv_i32 fp0;
a16336e4 6141
c9297f4d
AJ
6142 if (ft != 0) {
6143 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6144 }
6145 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6146 gen_load_fpr32(fp0, fs);
6147 gen_store_fpr32(fp0, fd);
a7812ae4 6148 tcg_temp_free_i32(fp0);
a16336e4
TS
6149 gen_set_label(l1);
6150 }
5a5012ec
TS
6151 opn = "movz.s";
6152 break;
6153 case FOP(19, 16):
a16336e4
TS
6154 {
6155 int l1 = gen_new_label();
c9297f4d
AJ
6156 TCGv_i32 fp0;
6157
6158 if (ft != 0) {
6159 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6160 fp0 = tcg_temp_new_i32();
6161 gen_load_fpr32(fp0, fs);
6162 gen_store_fpr32(fp0, fd);
6163 tcg_temp_free_i32(fp0);
6164 gen_set_label(l1);
6165 }
a16336e4 6166 }
5a5012ec
TS
6167 opn = "movn.s";
6168 break;
57fa1fb3 6169 case FOP(21, 16):
b8aa4598 6170 check_cop1x(ctx);
b6d96bed 6171 {
a7812ae4 6172 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6173
6174 gen_load_fpr32(fp0, fs);
a7812ae4 6175 gen_helper_float_recip_s(fp0, fp0);
b6d96bed 6176 gen_store_fpr32(fp0, fd);
a7812ae4 6177 tcg_temp_free_i32(fp0);
b6d96bed 6178 }
57fa1fb3
TS
6179 opn = "recip.s";
6180 break;
6181 case FOP(22, 16):
b8aa4598 6182 check_cop1x(ctx);
b6d96bed 6183 {
a7812ae4 6184 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6185
6186 gen_load_fpr32(fp0, fs);
a7812ae4 6187 gen_helper_float_rsqrt_s(fp0, fp0);
b6d96bed 6188 gen_store_fpr32(fp0, fd);
a7812ae4 6189 tcg_temp_free_i32(fp0);
b6d96bed 6190 }
57fa1fb3
TS
6191 opn = "rsqrt.s";
6192 break;
6193 case FOP(28, 16):
5e755519 6194 check_cp1_64bitmode(ctx);
b6d96bed 6195 {
a7812ae4
PB
6196 TCGv_i32 fp0 = tcg_temp_new_i32();
6197 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6198
6199 gen_load_fpr32(fp0, fs);
6200 gen_load_fpr32(fp1, fd);
a7812ae4
PB
6201 gen_helper_float_recip2_s(fp0, fp0, fp1);
6202 tcg_temp_free_i32(fp1);
b6d96bed 6203 gen_store_fpr32(fp0, fd);
a7812ae4 6204 tcg_temp_free_i32(fp0);
b6d96bed 6205 }
57fa1fb3
TS
6206 opn = "recip2.s";
6207 break;
6208 case FOP(29, 16):
5e755519 6209 check_cp1_64bitmode(ctx);
b6d96bed 6210 {
a7812ae4 6211 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6212
6213 gen_load_fpr32(fp0, fs);
a7812ae4 6214 gen_helper_float_recip1_s(fp0, fp0);
b6d96bed 6215 gen_store_fpr32(fp0, fd);
a7812ae4 6216 tcg_temp_free_i32(fp0);
b6d96bed 6217 }
57fa1fb3
TS
6218 opn = "recip1.s";
6219 break;
6220 case FOP(30, 16):
5e755519 6221 check_cp1_64bitmode(ctx);
b6d96bed 6222 {
a7812ae4 6223 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6224
6225 gen_load_fpr32(fp0, fs);
a7812ae4 6226 gen_helper_float_rsqrt1_s(fp0, fp0);
b6d96bed 6227 gen_store_fpr32(fp0, fd);
a7812ae4 6228 tcg_temp_free_i32(fp0);
b6d96bed 6229 }
57fa1fb3
TS
6230 opn = "rsqrt1.s";
6231 break;
6232 case FOP(31, 16):
5e755519 6233 check_cp1_64bitmode(ctx);
b6d96bed 6234 {
a7812ae4
PB
6235 TCGv_i32 fp0 = tcg_temp_new_i32();
6236 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6237
6238 gen_load_fpr32(fp0, fs);
6239 gen_load_fpr32(fp1, ft);
a7812ae4
PB
6240 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6241 tcg_temp_free_i32(fp1);
b6d96bed 6242 gen_store_fpr32(fp0, fd);
a7812ae4 6243 tcg_temp_free_i32(fp0);
b6d96bed 6244 }
57fa1fb3
TS
6245 opn = "rsqrt2.s";
6246 break;
5a5012ec 6247 case FOP(33, 16):
5e755519 6248 check_cp1_registers(ctx, fd);
b6d96bed 6249 {
a7812ae4
PB
6250 TCGv_i32 fp32 = tcg_temp_new_i32();
6251 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6252
6253 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6254 gen_helper_float_cvtd_s(fp64, fp32);
6255 tcg_temp_free_i32(fp32);
b6d96bed 6256 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6257 tcg_temp_free_i64(fp64);
b6d96bed 6258 }
5a5012ec
TS
6259 opn = "cvt.d.s";
6260 break;
6261 case FOP(36, 16):
b6d96bed 6262 {
a7812ae4 6263 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6264
6265 gen_load_fpr32(fp0, fs);
a7812ae4 6266 gen_helper_float_cvtw_s(fp0, fp0);
b6d96bed 6267 gen_store_fpr32(fp0, fd);
a7812ae4 6268 tcg_temp_free_i32(fp0);
b6d96bed 6269 }
5a5012ec
TS
6270 opn = "cvt.w.s";
6271 break;
6272 case FOP(37, 16):
5e755519 6273 check_cp1_64bitmode(ctx);
b6d96bed 6274 {
a7812ae4
PB
6275 TCGv_i32 fp32 = tcg_temp_new_i32();
6276 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6277
6278 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6279 gen_helper_float_cvtl_s(fp64, fp32);
6280 tcg_temp_free_i32(fp32);
b6d96bed 6281 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6282 tcg_temp_free_i64(fp64);
b6d96bed 6283 }
5a5012ec
TS
6284 opn = "cvt.l.s";
6285 break;
6286 case FOP(38, 16):
5e755519 6287 check_cp1_64bitmode(ctx);
b6d96bed 6288 {
a7812ae4
PB
6289 TCGv_i64 fp64 = tcg_temp_new_i64();
6290 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6291 TCGv_i32 fp32_1 = tcg_temp_new_i32();
b6d96bed
TS
6292
6293 gen_load_fpr32(fp32_0, fs);
6294 gen_load_fpr32(fp32_1, ft);
36aa55dc 6295 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
a7812ae4
PB
6296 tcg_temp_free_i32(fp32_1);
6297 tcg_temp_free_i32(fp32_0);
36aa55dc 6298 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6299 tcg_temp_free_i64(fp64);
b6d96bed 6300 }
5a5012ec
TS
6301 opn = "cvt.ps.s";
6302 break;
6303 case FOP(48, 16):
6304 case FOP(49, 16):
6305 case FOP(50, 16):
6306 case FOP(51, 16):
6307 case FOP(52, 16):
6308 case FOP(53, 16):
6309 case FOP(54, 16):
6310 case FOP(55, 16):
6311 case FOP(56, 16):
6312 case FOP(57, 16):
6313 case FOP(58, 16):
6314 case FOP(59, 16):
6315 case FOP(60, 16):
6316 case FOP(61, 16):
6317 case FOP(62, 16):
6318 case FOP(63, 16):
b6d96bed 6319 {
a7812ae4
PB
6320 TCGv_i32 fp0 = tcg_temp_new_i32();
6321 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
6322
6323 gen_load_fpr32(fp0, fs);
6324 gen_load_fpr32(fp1, ft);
6325 if (ctx->opcode & (1 << 6)) {
8c0ab41f 6326 check_cop1x(ctx);
b6d96bed
TS
6327 gen_cmpabs_s(func-48, fp0, fp1, cc);
6328 opn = condnames_abs[func-48];
6329 } else {
6330 gen_cmp_s(func-48, fp0, fp1, cc);
6331 opn = condnames[func-48];
6332 }
a7812ae4
PB
6333 tcg_temp_free_i32(fp0);
6334 tcg_temp_free_i32(fp1);
5a1e8ffb 6335 }
5a5012ec 6336 break;
6ea83fed 6337 case FOP(0, 17):
5e755519 6338 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6339 {
a7812ae4
PB
6340 TCGv_i64 fp0 = tcg_temp_new_i64();
6341 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6342
6343 gen_load_fpr64(ctx, fp0, fs);
6344 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6345 gen_helper_float_add_d(fp0, fp0, fp1);
6346 tcg_temp_free_i64(fp1);
b6d96bed 6347 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6348 tcg_temp_free_i64(fp0);
b6d96bed 6349 }
6ea83fed 6350 opn = "add.d";
5a1e8ffb 6351 optype = BINOP;
6ea83fed
FB
6352 break;
6353 case FOP(1, 17):
5e755519 6354 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6355 {
a7812ae4
PB
6356 TCGv_i64 fp0 = tcg_temp_new_i64();
6357 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6358
6359 gen_load_fpr64(ctx, fp0, fs);
6360 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6361 gen_helper_float_sub_d(fp0, fp0, fp1);
6362 tcg_temp_free_i64(fp1);
b6d96bed 6363 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6364 tcg_temp_free_i64(fp0);
b6d96bed 6365 }
6ea83fed 6366 opn = "sub.d";
5a1e8ffb 6367 optype = BINOP;
6ea83fed
FB
6368 break;
6369 case FOP(2, 17):
5e755519 6370 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6371 {
a7812ae4
PB
6372 TCGv_i64 fp0 = tcg_temp_new_i64();
6373 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6374
6375 gen_load_fpr64(ctx, fp0, fs);
6376 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6377 gen_helper_float_mul_d(fp0, fp0, fp1);
6378 tcg_temp_free_i64(fp1);
b6d96bed 6379 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6380 tcg_temp_free_i64(fp0);
b6d96bed 6381 }
6ea83fed 6382 opn = "mul.d";
5a1e8ffb 6383 optype = BINOP;
6ea83fed
FB
6384 break;
6385 case FOP(3, 17):
5e755519 6386 check_cp1_registers(ctx, fs | ft | fd);
b6d96bed 6387 {
a7812ae4
PB
6388 TCGv_i64 fp0 = tcg_temp_new_i64();
6389 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6390
6391 gen_load_fpr64(ctx, fp0, fs);
6392 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6393 gen_helper_float_div_d(fp0, fp0, fp1);
6394 tcg_temp_free_i64(fp1);
b6d96bed 6395 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6396 tcg_temp_free_i64(fp0);
b6d96bed 6397 }
6ea83fed 6398 opn = "div.d";
5a1e8ffb 6399 optype = BINOP;
6ea83fed
FB
6400 break;
6401 case FOP(4, 17):
5e755519 6402 check_cp1_registers(ctx, fs | fd);
b6d96bed 6403 {
a7812ae4 6404 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6405
6406 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6407 gen_helper_float_sqrt_d(fp0, fp0);
b6d96bed 6408 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6409 tcg_temp_free_i64(fp0);
b6d96bed 6410 }
6ea83fed
FB
6411 opn = "sqrt.d";
6412 break;
6413 case FOP(5, 17):
5e755519 6414 check_cp1_registers(ctx, fs | fd);
b6d96bed 6415 {
a7812ae4 6416 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6417
6418 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6419 gen_helper_float_abs_d(fp0, fp0);
b6d96bed 6420 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6421 tcg_temp_free_i64(fp0);
b6d96bed 6422 }
6ea83fed
FB
6423 opn = "abs.d";
6424 break;
6425 case FOP(6, 17):
5e755519 6426 check_cp1_registers(ctx, fs | fd);
b6d96bed 6427 {
a7812ae4 6428 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6429
6430 gen_load_fpr64(ctx, fp0, fs);
6431 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6432 tcg_temp_free_i64(fp0);
b6d96bed 6433 }
6ea83fed
FB
6434 opn = "mov.d";
6435 break;
6436 case FOP(7, 17):
5e755519 6437 check_cp1_registers(ctx, fs | fd);
b6d96bed 6438 {
a7812ae4 6439 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6440
6441 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6442 gen_helper_float_chs_d(fp0, fp0);
b6d96bed 6443 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6444 tcg_temp_free_i64(fp0);
b6d96bed 6445 }
6ea83fed
FB
6446 opn = "neg.d";
6447 break;
5a5012ec 6448 case FOP(8, 17):
5e755519 6449 check_cp1_64bitmode(ctx);
b6d96bed 6450 {
a7812ae4 6451 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6452
6453 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6454 gen_helper_float_roundl_d(fp0, fp0);
b6d96bed 6455 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6456 tcg_temp_free_i64(fp0);
b6d96bed 6457 }
5a5012ec
TS
6458 opn = "round.l.d";
6459 break;
6460 case FOP(9, 17):
5e755519 6461 check_cp1_64bitmode(ctx);
b6d96bed 6462 {
a7812ae4 6463 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6464
6465 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6466 gen_helper_float_truncl_d(fp0, fp0);
b6d96bed 6467 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6468 tcg_temp_free_i64(fp0);
b6d96bed 6469 }
5a5012ec
TS
6470 opn = "trunc.l.d";
6471 break;
6472 case FOP(10, 17):
5e755519 6473 check_cp1_64bitmode(ctx);
b6d96bed 6474 {
a7812ae4 6475 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6476
6477 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6478 gen_helper_float_ceill_d(fp0, fp0);
b6d96bed 6479 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6480 tcg_temp_free_i64(fp0);
b6d96bed 6481 }
5a5012ec
TS
6482 opn = "ceil.l.d";
6483 break;
6484 case FOP(11, 17):
5e755519 6485 check_cp1_64bitmode(ctx);
b6d96bed 6486 {
a7812ae4 6487 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6488
6489 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6490 gen_helper_float_floorl_d(fp0, fp0);
b6d96bed 6491 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6492 tcg_temp_free_i64(fp0);
b6d96bed 6493 }
5a5012ec
TS
6494 opn = "floor.l.d";
6495 break;
6ea83fed 6496 case FOP(12, 17):
5e755519 6497 check_cp1_registers(ctx, fs);
b6d96bed 6498 {
a7812ae4
PB
6499 TCGv_i32 fp32 = tcg_temp_new_i32();
6500 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6501
6502 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6503 gen_helper_float_roundw_d(fp32, fp64);
6504 tcg_temp_free_i64(fp64);
b6d96bed 6505 gen_store_fpr32(fp32, fd);
a7812ae4 6506 tcg_temp_free_i32(fp32);
b6d96bed 6507 }
6ea83fed
FB
6508 opn = "round.w.d";
6509 break;
6510 case FOP(13, 17):
5e755519 6511 check_cp1_registers(ctx, fs);
b6d96bed 6512 {
a7812ae4
PB
6513 TCGv_i32 fp32 = tcg_temp_new_i32();
6514 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6515
6516 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6517 gen_helper_float_truncw_d(fp32, fp64);
6518 tcg_temp_free_i64(fp64);
b6d96bed 6519 gen_store_fpr32(fp32, fd);
a7812ae4 6520 tcg_temp_free_i32(fp32);
b6d96bed 6521 }
6ea83fed
FB
6522 opn = "trunc.w.d";
6523 break;
6524 case FOP(14, 17):
5e755519 6525 check_cp1_registers(ctx, fs);
b6d96bed 6526 {
a7812ae4
PB
6527 TCGv_i32 fp32 = tcg_temp_new_i32();
6528 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6529
6530 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6531 gen_helper_float_ceilw_d(fp32, fp64);
6532 tcg_temp_free_i64(fp64);
b6d96bed 6533 gen_store_fpr32(fp32, fd);
a7812ae4 6534 tcg_temp_free_i32(fp32);
b6d96bed 6535 }
6ea83fed
FB
6536 opn = "ceil.w.d";
6537 break;
6538 case FOP(15, 17):
5e755519 6539 check_cp1_registers(ctx, fs);
b6d96bed 6540 {
a7812ae4
PB
6541 TCGv_i32 fp32 = tcg_temp_new_i32();
6542 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6543
6544 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6545 gen_helper_float_floorw_d(fp32, fp64);
6546 tcg_temp_free_i64(fp64);
b6d96bed 6547 gen_store_fpr32(fp32, fd);
a7812ae4 6548 tcg_temp_free_i32(fp32);
b6d96bed 6549 }
7a387fff 6550 opn = "floor.w.d";
6ea83fed 6551 break;
5a5012ec 6552 case FOP(17, 17):
b6d96bed 6553 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6554 opn = "movcf.d";
dd016883 6555 break;
5a5012ec 6556 case FOP(18, 17):
a16336e4
TS
6557 {
6558 int l1 = gen_new_label();
c9297f4d 6559 TCGv_i64 fp0;
a16336e4 6560
c9297f4d
AJ
6561 if (ft != 0) {
6562 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6563 }
6564 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6565 gen_load_fpr64(ctx, fp0, fs);
6566 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6567 tcg_temp_free_i64(fp0);
a16336e4
TS
6568 gen_set_label(l1);
6569 }
5a5012ec
TS
6570 opn = "movz.d";
6571 break;
6572 case FOP(19, 17):
a16336e4
TS
6573 {
6574 int l1 = gen_new_label();
c9297f4d
AJ
6575 TCGv_i64 fp0;
6576
6577 if (ft != 0) {
6578 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6579 fp0 = tcg_temp_new_i64();
6580 gen_load_fpr64(ctx, fp0, fs);
6581 gen_store_fpr64(ctx, fp0, fd);
6582 tcg_temp_free_i64(fp0);
6583 gen_set_label(l1);
6584 }
a16336e4 6585 }
5a5012ec 6586 opn = "movn.d";
6ea83fed 6587 break;
57fa1fb3 6588 case FOP(21, 17):
b8aa4598 6589 check_cp1_64bitmode(ctx);
b6d96bed 6590 {
a7812ae4 6591 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6592
6593 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6594 gen_helper_float_recip_d(fp0, fp0);
b6d96bed 6595 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6596 tcg_temp_free_i64(fp0);
b6d96bed 6597 }
57fa1fb3
TS
6598 opn = "recip.d";
6599 break;
6600 case FOP(22, 17):
b8aa4598 6601 check_cp1_64bitmode(ctx);
b6d96bed 6602 {
a7812ae4 6603 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6604
6605 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6606 gen_helper_float_rsqrt_d(fp0, fp0);
b6d96bed 6607 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6608 tcg_temp_free_i64(fp0);
b6d96bed 6609 }
57fa1fb3
TS
6610 opn = "rsqrt.d";
6611 break;
6612 case FOP(28, 17):
5e755519 6613 check_cp1_64bitmode(ctx);
b6d96bed 6614 {
a7812ae4
PB
6615 TCGv_i64 fp0 = tcg_temp_new_i64();
6616 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6617
6618 gen_load_fpr64(ctx, fp0, fs);
6619 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6620 gen_helper_float_recip2_d(fp0, fp0, fp1);
6621 tcg_temp_free_i64(fp1);
b6d96bed 6622 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6623 tcg_temp_free_i64(fp0);
b6d96bed 6624 }
57fa1fb3
TS
6625 opn = "recip2.d";
6626 break;
6627 case FOP(29, 17):
5e755519 6628 check_cp1_64bitmode(ctx);
b6d96bed 6629 {
a7812ae4 6630 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6631
6632 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6633 gen_helper_float_recip1_d(fp0, fp0);
b6d96bed 6634 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6635 tcg_temp_free_i64(fp0);
b6d96bed 6636 }
57fa1fb3
TS
6637 opn = "recip1.d";
6638 break;
6639 case FOP(30, 17):
5e755519 6640 check_cp1_64bitmode(ctx);
b6d96bed 6641 {
a7812ae4 6642 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6643
6644 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6645 gen_helper_float_rsqrt1_d(fp0, fp0);
b6d96bed 6646 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6647 tcg_temp_free_i64(fp0);
b6d96bed 6648 }
57fa1fb3
TS
6649 opn = "rsqrt1.d";
6650 break;
6651 case FOP(31, 17):
5e755519 6652 check_cp1_64bitmode(ctx);
b6d96bed 6653 {
a7812ae4
PB
6654 TCGv_i64 fp0 = tcg_temp_new_i64();
6655 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6656
6657 gen_load_fpr64(ctx, fp0, fs);
6658 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6659 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
6660 tcg_temp_free_i64(fp1);
b6d96bed 6661 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6662 tcg_temp_free_i64(fp0);
b6d96bed 6663 }
57fa1fb3
TS
6664 opn = "rsqrt2.d";
6665 break;
6ea83fed
FB
6666 case FOP(48, 17):
6667 case FOP(49, 17):
6668 case FOP(50, 17):
6669 case FOP(51, 17):
6670 case FOP(52, 17):
6671 case FOP(53, 17):
6672 case FOP(54, 17):
6673 case FOP(55, 17):
6674 case FOP(56, 17):
6675 case FOP(57, 17):
6676 case FOP(58, 17):
6677 case FOP(59, 17):
6678 case FOP(60, 17):
6679 case FOP(61, 17):
6680 case FOP(62, 17):
6681 case FOP(63, 17):
b6d96bed 6682 {
a7812ae4
PB
6683 TCGv_i64 fp0 = tcg_temp_new_i64();
6684 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6685
6686 gen_load_fpr64(ctx, fp0, fs);
6687 gen_load_fpr64(ctx, fp1, ft);
6688 if (ctx->opcode & (1 << 6)) {
8c0ab41f
AJ
6689 check_cop1x(ctx);
6690 check_cp1_registers(ctx, fs | ft);
b6d96bed
TS
6691 gen_cmpabs_d(func-48, fp0, fp1, cc);
6692 opn = condnames_abs[func-48];
6693 } else {
8c0ab41f 6694 check_cp1_registers(ctx, fs | ft);
b6d96bed
TS
6695 gen_cmp_d(func-48, fp0, fp1, cc);
6696 opn = condnames[func-48];
6697 }
a7812ae4
PB
6698 tcg_temp_free_i64(fp0);
6699 tcg_temp_free_i64(fp1);
5a1e8ffb 6700 }
6ea83fed 6701 break;
5a5012ec 6702 case FOP(32, 17):
5e755519 6703 check_cp1_registers(ctx, fs);
b6d96bed 6704 {
a7812ae4
PB
6705 TCGv_i32 fp32 = tcg_temp_new_i32();
6706 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6707
6708 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6709 gen_helper_float_cvts_d(fp32, fp64);
6710 tcg_temp_free_i64(fp64);
b6d96bed 6711 gen_store_fpr32(fp32, fd);
a7812ae4 6712 tcg_temp_free_i32(fp32);
b6d96bed 6713 }
5a5012ec
TS
6714 opn = "cvt.s.d";
6715 break;
6716 case FOP(36, 17):
5e755519 6717 check_cp1_registers(ctx, fs);
b6d96bed 6718 {
a7812ae4
PB
6719 TCGv_i32 fp32 = tcg_temp_new_i32();
6720 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6721
6722 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6723 gen_helper_float_cvtw_d(fp32, fp64);
6724 tcg_temp_free_i64(fp64);
b6d96bed 6725 gen_store_fpr32(fp32, fd);
a7812ae4 6726 tcg_temp_free_i32(fp32);
b6d96bed 6727 }
5a5012ec
TS
6728 opn = "cvt.w.d";
6729 break;
6730 case FOP(37, 17):
5e755519 6731 check_cp1_64bitmode(ctx);
b6d96bed 6732 {
a7812ae4 6733 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6734
6735 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6736 gen_helper_float_cvtl_d(fp0, fp0);
b6d96bed 6737 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6738 tcg_temp_free_i64(fp0);
b6d96bed 6739 }
5a5012ec
TS
6740 opn = "cvt.l.d";
6741 break;
6742 case FOP(32, 20):
b6d96bed 6743 {
a7812ae4 6744 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
6745
6746 gen_load_fpr32(fp0, fs);
a7812ae4 6747 gen_helper_float_cvts_w(fp0, fp0);
b6d96bed 6748 gen_store_fpr32(fp0, fd);
a7812ae4 6749 tcg_temp_free_i32(fp0);
b6d96bed 6750 }
5a5012ec 6751 opn = "cvt.s.w";
6ea83fed 6752 break;
5a5012ec 6753 case FOP(33, 20):
5e755519 6754 check_cp1_registers(ctx, fd);
b6d96bed 6755 {
a7812ae4
PB
6756 TCGv_i32 fp32 = tcg_temp_new_i32();
6757 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6758
6759 gen_load_fpr32(fp32, fs);
a7812ae4
PB
6760 gen_helper_float_cvtd_w(fp64, fp32);
6761 tcg_temp_free_i32(fp32);
b6d96bed 6762 gen_store_fpr64(ctx, fp64, fd);
a7812ae4 6763 tcg_temp_free_i64(fp64);
b6d96bed 6764 }
5a5012ec
TS
6765 opn = "cvt.d.w";
6766 break;
6767 case FOP(32, 21):
5e755519 6768 check_cp1_64bitmode(ctx);
b6d96bed 6769 {
a7812ae4
PB
6770 TCGv_i32 fp32 = tcg_temp_new_i32();
6771 TCGv_i64 fp64 = tcg_temp_new_i64();
b6d96bed
TS
6772
6773 gen_load_fpr64(ctx, fp64, fs);
a7812ae4
PB
6774 gen_helper_float_cvts_l(fp32, fp64);
6775 tcg_temp_free_i64(fp64);
b6d96bed 6776 gen_store_fpr32(fp32, fd);
a7812ae4 6777 tcg_temp_free_i32(fp32);
b6d96bed 6778 }
5a5012ec
TS
6779 opn = "cvt.s.l";
6780 break;
6781 case FOP(33, 21):
5e755519 6782 check_cp1_64bitmode(ctx);
b6d96bed 6783 {
a7812ae4 6784 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6785
6786 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6787 gen_helper_float_cvtd_l(fp0, fp0);
b6d96bed 6788 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6789 tcg_temp_free_i64(fp0);
b6d96bed 6790 }
5a5012ec
TS
6791 opn = "cvt.d.l";
6792 break;
6793 case FOP(38, 20):
5e755519 6794 check_cp1_64bitmode(ctx);
b6d96bed 6795 {
a7812ae4 6796 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6797
6798 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6799 gen_helper_float_cvtps_pw(fp0, fp0);
b6d96bed 6800 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6801 tcg_temp_free_i64(fp0);
b6d96bed 6802 }
5a5012ec
TS
6803 opn = "cvt.ps.pw";
6804 break;
6805 case FOP(0, 22):
5e755519 6806 check_cp1_64bitmode(ctx);
b6d96bed 6807 {
a7812ae4
PB
6808 TCGv_i64 fp0 = tcg_temp_new_i64();
6809 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6810
6811 gen_load_fpr64(ctx, fp0, fs);
6812 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6813 gen_helper_float_add_ps(fp0, fp0, fp1);
6814 tcg_temp_free_i64(fp1);
b6d96bed 6815 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6816 tcg_temp_free_i64(fp0);
b6d96bed 6817 }
5a5012ec 6818 opn = "add.ps";
6ea83fed 6819 break;
5a5012ec 6820 case FOP(1, 22):
5e755519 6821 check_cp1_64bitmode(ctx);
b6d96bed 6822 {
a7812ae4
PB
6823 TCGv_i64 fp0 = tcg_temp_new_i64();
6824 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6825
6826 gen_load_fpr64(ctx, fp0, fs);
6827 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6828 gen_helper_float_sub_ps(fp0, fp0, fp1);
6829 tcg_temp_free_i64(fp1);
b6d96bed 6830 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6831 tcg_temp_free_i64(fp0);
b6d96bed 6832 }
5a5012ec 6833 opn = "sub.ps";
6ea83fed 6834 break;
5a5012ec 6835 case FOP(2, 22):
5e755519 6836 check_cp1_64bitmode(ctx);
b6d96bed 6837 {
a7812ae4
PB
6838 TCGv_i64 fp0 = tcg_temp_new_i64();
6839 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6840
6841 gen_load_fpr64(ctx, fp0, fs);
6842 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
6843 gen_helper_float_mul_ps(fp0, fp0, fp1);
6844 tcg_temp_free_i64(fp1);
b6d96bed 6845 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6846 tcg_temp_free_i64(fp0);
b6d96bed 6847 }
5a5012ec 6848 opn = "mul.ps";
6ea83fed 6849 break;
5a5012ec 6850 case FOP(5, 22):
5e755519 6851 check_cp1_64bitmode(ctx);
b6d96bed 6852 {
a7812ae4 6853 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6854
6855 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6856 gen_helper_float_abs_ps(fp0, fp0);
b6d96bed 6857 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6858 tcg_temp_free_i64(fp0);
b6d96bed 6859 }
5a5012ec 6860 opn = "abs.ps";
6ea83fed 6861 break;
5a5012ec 6862 case FOP(6, 22):
5e755519 6863 check_cp1_64bitmode(ctx);
b6d96bed 6864 {
a7812ae4 6865 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6866
6867 gen_load_fpr64(ctx, fp0, fs);
6868 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6869 tcg_temp_free_i64(fp0);
b6d96bed 6870 }
5a5012ec 6871 opn = "mov.ps";
6ea83fed 6872 break;
5a5012ec 6873 case FOP(7, 22):
5e755519 6874 check_cp1_64bitmode(ctx);
b6d96bed 6875 {
a7812ae4 6876 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6877
6878 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6879 gen_helper_float_chs_ps(fp0, fp0);
b6d96bed 6880 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6881 tcg_temp_free_i64(fp0);
b6d96bed 6882 }
5a5012ec 6883 opn = "neg.ps";
6ea83fed 6884 break;
5a5012ec 6885 case FOP(17, 22):
5e755519 6886 check_cp1_64bitmode(ctx);
b6d96bed 6887 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
5a5012ec 6888 opn = "movcf.ps";
6ea83fed 6889 break;
5a5012ec 6890 case FOP(18, 22):
5e755519 6891 check_cp1_64bitmode(ctx);
a16336e4
TS
6892 {
6893 int l1 = gen_new_label();
30a3848b 6894 TCGv_i64 fp0;
a16336e4 6895
c9297f4d
AJ
6896 if (ft != 0)
6897 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6898 fp0 = tcg_temp_new_i64();
6899 gen_load_fpr64(ctx, fp0, fs);
6900 gen_store_fpr64(ctx, fp0, fd);
6901 tcg_temp_free_i64(fp0);
a16336e4
TS
6902 gen_set_label(l1);
6903 }
5a5012ec 6904 opn = "movz.ps";
6ea83fed 6905 break;
5a5012ec 6906 case FOP(19, 22):
5e755519 6907 check_cp1_64bitmode(ctx);
a16336e4
TS
6908 {
6909 int l1 = gen_new_label();
30a3848b 6910 TCGv_i64 fp0;
c9297f4d
AJ
6911
6912 if (ft != 0) {
6913 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6914 fp0 = tcg_temp_new_i64();
6915 gen_load_fpr64(ctx, fp0, fs);
6916 gen_store_fpr64(ctx, fp0, fd);
6917 tcg_temp_free_i64(fp0);
6918 gen_set_label(l1);
6919 }
a16336e4 6920 }
5a5012ec 6921 opn = "movn.ps";
6ea83fed 6922 break;
fbcc6828 6923 case FOP(24, 22):
5e755519 6924 check_cp1_64bitmode(ctx);
b6d96bed 6925 {
a7812ae4
PB
6926 TCGv_i64 fp0 = tcg_temp_new_i64();
6927 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6928
6929 gen_load_fpr64(ctx, fp0, ft);
6930 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6931 gen_helper_float_addr_ps(fp0, fp0, fp1);
6932 tcg_temp_free_i64(fp1);
b6d96bed 6933 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6934 tcg_temp_free_i64(fp0);
b6d96bed 6935 }
fbcc6828
TS
6936 opn = "addr.ps";
6937 break;
57fa1fb3 6938 case FOP(26, 22):
5e755519 6939 check_cp1_64bitmode(ctx);
b6d96bed 6940 {
a7812ae4
PB
6941 TCGv_i64 fp0 = tcg_temp_new_i64();
6942 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6943
6944 gen_load_fpr64(ctx, fp0, ft);
6945 gen_load_fpr64(ctx, fp1, fs);
a7812ae4
PB
6946 gen_helper_float_mulr_ps(fp0, fp0, fp1);
6947 tcg_temp_free_i64(fp1);
b6d96bed 6948 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6949 tcg_temp_free_i64(fp0);
b6d96bed 6950 }
57fa1fb3
TS
6951 opn = "mulr.ps";
6952 break;
6953 case FOP(28, 22):
5e755519 6954 check_cp1_64bitmode(ctx);
b6d96bed 6955 {
a7812ae4
PB
6956 TCGv_i64 fp0 = tcg_temp_new_i64();
6957 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6958
6959 gen_load_fpr64(ctx, fp0, fs);
6960 gen_load_fpr64(ctx, fp1, fd);
a7812ae4
PB
6961 gen_helper_float_recip2_ps(fp0, fp0, fp1);
6962 tcg_temp_free_i64(fp1);
b6d96bed 6963 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6964 tcg_temp_free_i64(fp0);
b6d96bed 6965 }
57fa1fb3
TS
6966 opn = "recip2.ps";
6967 break;
6968 case FOP(29, 22):
5e755519 6969 check_cp1_64bitmode(ctx);
b6d96bed 6970 {
a7812ae4 6971 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6972
6973 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6974 gen_helper_float_recip1_ps(fp0, fp0);
b6d96bed 6975 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6976 tcg_temp_free_i64(fp0);
b6d96bed 6977 }
57fa1fb3
TS
6978 opn = "recip1.ps";
6979 break;
6980 case FOP(30, 22):
5e755519 6981 check_cp1_64bitmode(ctx);
b6d96bed 6982 {
a7812ae4 6983 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
6984
6985 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 6986 gen_helper_float_rsqrt1_ps(fp0, fp0);
b6d96bed 6987 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 6988 tcg_temp_free_i64(fp0);
b6d96bed 6989 }
57fa1fb3
TS
6990 opn = "rsqrt1.ps";
6991 break;
6992 case FOP(31, 22):
5e755519 6993 check_cp1_64bitmode(ctx);
b6d96bed 6994 {
a7812ae4
PB
6995 TCGv_i64 fp0 = tcg_temp_new_i64();
6996 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
6997
6998 gen_load_fpr64(ctx, fp0, fs);
6999 gen_load_fpr64(ctx, fp1, ft);
a7812ae4
PB
7000 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7001 tcg_temp_free_i64(fp1);
b6d96bed 7002 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7003 tcg_temp_free_i64(fp0);
b6d96bed 7004 }
57fa1fb3
TS
7005 opn = "rsqrt2.ps";
7006 break;
5a5012ec 7007 case FOP(32, 22):
5e755519 7008 check_cp1_64bitmode(ctx);
b6d96bed 7009 {
a7812ae4 7010 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7011
7012 gen_load_fpr32h(fp0, fs);
a7812ae4 7013 gen_helper_float_cvts_pu(fp0, fp0);
b6d96bed 7014 gen_store_fpr32(fp0, fd);
a7812ae4 7015 tcg_temp_free_i32(fp0);
b6d96bed 7016 }
5a5012ec 7017 opn = "cvt.s.pu";
dd016883 7018 break;
5a5012ec 7019 case FOP(36, 22):
5e755519 7020 check_cp1_64bitmode(ctx);
b6d96bed 7021 {
a7812ae4 7022 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7023
7024 gen_load_fpr64(ctx, fp0, fs);
a7812ae4 7025 gen_helper_float_cvtpw_ps(fp0, fp0);
b6d96bed 7026 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7027 tcg_temp_free_i64(fp0);
b6d96bed 7028 }
5a5012ec 7029 opn = "cvt.pw.ps";
6ea83fed 7030 break;
5a5012ec 7031 case FOP(40, 22):
5e755519 7032 check_cp1_64bitmode(ctx);
b6d96bed 7033 {
a7812ae4 7034 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed
TS
7035
7036 gen_load_fpr32(fp0, fs);
a7812ae4 7037 gen_helper_float_cvts_pl(fp0, fp0);
b6d96bed 7038 gen_store_fpr32(fp0, fd);
a7812ae4 7039 tcg_temp_free_i32(fp0);
b6d96bed 7040 }
5a5012ec 7041 opn = "cvt.s.pl";
6ea83fed 7042 break;
5a5012ec 7043 case FOP(44, 22):
5e755519 7044 check_cp1_64bitmode(ctx);
b6d96bed 7045 {
a7812ae4
PB
7046 TCGv_i32 fp0 = tcg_temp_new_i32();
7047 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7048
7049 gen_load_fpr32(fp0, fs);
7050 gen_load_fpr32(fp1, ft);
7051 gen_store_fpr32h(fp0, fd);
7052 gen_store_fpr32(fp1, fd);
a7812ae4
PB
7053 tcg_temp_free_i32(fp0);
7054 tcg_temp_free_i32(fp1);
b6d96bed 7055 }
5a5012ec 7056 opn = "pll.ps";
6ea83fed 7057 break;
5a5012ec 7058 case FOP(45, 22):
5e755519 7059 check_cp1_64bitmode(ctx);
b6d96bed 7060 {
a7812ae4
PB
7061 TCGv_i32 fp0 = tcg_temp_new_i32();
7062 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7063
7064 gen_load_fpr32(fp0, fs);
7065 gen_load_fpr32h(fp1, ft);
7066 gen_store_fpr32(fp1, fd);
7067 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7068 tcg_temp_free_i32(fp0);
7069 tcg_temp_free_i32(fp1);
b6d96bed 7070 }
5a5012ec
TS
7071 opn = "plu.ps";
7072 break;
7073 case FOP(46, 22):
5e755519 7074 check_cp1_64bitmode(ctx);
b6d96bed 7075 {
a7812ae4
PB
7076 TCGv_i32 fp0 = tcg_temp_new_i32();
7077 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7078
7079 gen_load_fpr32h(fp0, fs);
7080 gen_load_fpr32(fp1, ft);
7081 gen_store_fpr32(fp1, fd);
7082 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7083 tcg_temp_free_i32(fp0);
7084 tcg_temp_free_i32(fp1);
b6d96bed 7085 }
5a5012ec
TS
7086 opn = "pul.ps";
7087 break;
7088 case FOP(47, 22):
5e755519 7089 check_cp1_64bitmode(ctx);
b6d96bed 7090 {
a7812ae4
PB
7091 TCGv_i32 fp0 = tcg_temp_new_i32();
7092 TCGv_i32 fp1 = tcg_temp_new_i32();
b6d96bed
TS
7093
7094 gen_load_fpr32h(fp0, fs);
7095 gen_load_fpr32h(fp1, ft);
7096 gen_store_fpr32(fp1, fd);
7097 gen_store_fpr32h(fp0, fd);
a7812ae4
PB
7098 tcg_temp_free_i32(fp0);
7099 tcg_temp_free_i32(fp1);
b6d96bed 7100 }
5a5012ec
TS
7101 opn = "puu.ps";
7102 break;
7103 case FOP(48, 22):
7104 case FOP(49, 22):
7105 case FOP(50, 22):
7106 case FOP(51, 22):
7107 case FOP(52, 22):
7108 case FOP(53, 22):
7109 case FOP(54, 22):
7110 case FOP(55, 22):
7111 case FOP(56, 22):
7112 case FOP(57, 22):
7113 case FOP(58, 22):
7114 case FOP(59, 22):
7115 case FOP(60, 22):
7116 case FOP(61, 22):
7117 case FOP(62, 22):
7118 case FOP(63, 22):
5e755519 7119 check_cp1_64bitmode(ctx);
b6d96bed 7120 {
a7812ae4
PB
7121 TCGv_i64 fp0 = tcg_temp_new_i64();
7122 TCGv_i64 fp1 = tcg_temp_new_i64();
b6d96bed
TS
7123
7124 gen_load_fpr64(ctx, fp0, fs);
7125 gen_load_fpr64(ctx, fp1, ft);
7126 if (ctx->opcode & (1 << 6)) {
7127 gen_cmpabs_ps(func-48, fp0, fp1, cc);
7128 opn = condnames_abs[func-48];
7129 } else {
7130 gen_cmp_ps(func-48, fp0, fp1, cc);
7131 opn = condnames[func-48];
7132 }
a7812ae4
PB
7133 tcg_temp_free_i64(fp0);
7134 tcg_temp_free_i64(fp1);
5a1e8ffb 7135 }
6ea83fed 7136 break;
5a5012ec 7137 default:
923617a3 7138 MIPS_INVAL(opn);
e397ee33 7139 generate_exception (ctx, EXCP_RI);
6ea83fed
FB
7140 return;
7141 }
5a1e8ffb
TS
7142 switch (optype) {
7143 case BINOP:
6ea83fed 7144 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
5a1e8ffb
TS
7145 break;
7146 case CMPOP:
7147 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7148 break;
7149 default:
6ea83fed 7150 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
5a1e8ffb
TS
7151 break;
7152 }
6ea83fed 7153}
6af0bf9c 7154
5a5012ec 7155/* Coprocessor 3 (FPU) */
5e755519
TS
7156static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7157 int fd, int fs, int base, int index)
7a387fff 7158{
923617a3 7159 const char *opn = "extended float load/store";
93b12ccc 7160 int store = 0;
4e2474d6 7161 TCGv t0 = tcg_temp_new();
7a387fff 7162
93b12ccc 7163 if (base == 0) {
6c5c1e20 7164 gen_load_gpr(t0, index);
93b12ccc 7165 } else if (index == 0) {
6c5c1e20 7166 gen_load_gpr(t0, base);
93b12ccc 7167 } else {
e9203484 7168 gen_load_gpr(t0, index);
941694d0 7169 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
93b12ccc 7170 }
5a5012ec 7171 /* Don't do NOP if destination is zero: we must perform the actual
ead9360e 7172 memory access. */
4e2474d6 7173 save_cpu_state(ctx, 0);
5a5012ec
TS
7174 switch (opc) {
7175 case OPC_LWXC1:
8c0ab41f 7176 check_cop1x(ctx);
b6d96bed 7177 {
a7812ae4 7178 TCGv_i32 fp0 = tcg_temp_new_i32();
b6d96bed 7179
585c88d5
AJ
7180 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7181 tcg_gen_trunc_tl_i32(fp0, t0);
b6d96bed 7182 gen_store_fpr32(fp0, fd);
a7812ae4 7183 tcg_temp_free_i32(fp0);
b6d96bed 7184 }
5a5012ec
TS
7185 opn = "lwxc1";
7186 break;
7187 case OPC_LDXC1:
8c0ab41f
AJ
7188 check_cop1x(ctx);
7189 check_cp1_registers(ctx, fd);
b6d96bed 7190 {
a7812ae4 7191 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7192
7193 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7194 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7195 tcg_temp_free_i64(fp0);
b6d96bed 7196 }
5a5012ec
TS
7197 opn = "ldxc1";
7198 break;
7199 case OPC_LUXC1:
8c0ab41f 7200 check_cp1_64bitmode(ctx);
6c5c1e20 7201 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7202 {
a7812ae4 7203 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7204
7205 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7206 gen_store_fpr64(ctx, fp0, fd);
a7812ae4 7207 tcg_temp_free_i64(fp0);
b6d96bed 7208 }
5a5012ec
TS
7209 opn = "luxc1";
7210 break;
7211 case OPC_SWXC1:
8c0ab41f 7212 check_cop1x(ctx);
b6d96bed 7213 {
a7812ae4 7214 TCGv_i32 fp0 = tcg_temp_new_i32();
585c88d5 7215 TCGv t1 = tcg_temp_new();
b6d96bed
TS
7216
7217 gen_load_fpr32(fp0, fs);
a7812ae4
PB
7218 tcg_gen_extu_i32_tl(t1, fp0);
7219 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7220 tcg_temp_free_i32(fp0);
a6035857 7221 tcg_temp_free(t1);
b6d96bed 7222 }
5a5012ec 7223 opn = "swxc1";
93b12ccc 7224 store = 1;
5a5012ec
TS
7225 break;
7226 case OPC_SDXC1:
8c0ab41f
AJ
7227 check_cop1x(ctx);
7228 check_cp1_registers(ctx, fs);
b6d96bed 7229 {
a7812ae4 7230 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7231
7232 gen_load_fpr64(ctx, fp0, fs);
7233 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7234 tcg_temp_free_i64(fp0);
b6d96bed 7235 }
5a5012ec 7236 opn = "sdxc1";
93b12ccc 7237 store = 1;
5a5012ec
TS
7238 break;
7239 case OPC_SUXC1:
8c0ab41f 7240 check_cp1_64bitmode(ctx);
6c5c1e20 7241 tcg_gen_andi_tl(t0, t0, ~0x7);
b6d96bed 7242 {
a7812ae4 7243 TCGv_i64 fp0 = tcg_temp_new_i64();
b6d96bed
TS
7244
7245 gen_load_fpr64(ctx, fp0, fs);
7246 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
a7812ae4 7247 tcg_temp_free_i64(fp0);
b6d96bed 7248 }
5a5012ec 7249 opn = "suxc1";
93b12ccc 7250 store = 1;
5a5012ec 7251 break;
5a5012ec 7252 }
6c5c1e20 7253 tcg_temp_free(t0);
93b12ccc
TS
7254 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7255 regnames[index], regnames[base]);
5a5012ec
TS
7256}
7257
5e755519
TS
7258static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7259 int fd, int fr, int fs, int ft)
5a5012ec 7260{
923617a3 7261 const char *opn = "flt3_arith";
5a5012ec 7262
5a5012ec
TS
7263 switch (opc) {
7264 case OPC_ALNV_PS:
b8aa4598 7265 check_cp1_64bitmode(ctx);
a16336e4 7266 {
a7812ae4 7267 TCGv t0 = tcg_temp_local_new();
c905fdac
AJ
7268 TCGv_i32 fp = tcg_temp_new_i32();
7269 TCGv_i32 fph = tcg_temp_new_i32();
a16336e4
TS
7270 int l1 = gen_new_label();
7271 int l2 = gen_new_label();
7272
6c5c1e20
TS
7273 gen_load_gpr(t0, fr);
7274 tcg_gen_andi_tl(t0, t0, 0x7);
6c5c1e20
TS
7275
7276 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
c905fdac
AJ
7277 gen_load_fpr32(fp, fs);
7278 gen_load_fpr32h(fph, fs);
7279 gen_store_fpr32(fp, fd);
7280 gen_store_fpr32h(fph, fd);
a16336e4
TS
7281 tcg_gen_br(l2);
7282 gen_set_label(l1);
6c5c1e20
TS
7283 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7284 tcg_temp_free(t0);
a16336e4 7285#ifdef TARGET_WORDS_BIGENDIAN
c905fdac
AJ
7286 gen_load_fpr32(fp, fs);
7287 gen_load_fpr32h(fph, ft);
7288 gen_store_fpr32h(fp, fd);
7289 gen_store_fpr32(fph, fd);
a16336e4 7290#else
c905fdac
AJ
7291 gen_load_fpr32h(fph, fs);
7292 gen_load_fpr32(fp, ft);
7293 gen_store_fpr32(fph, fd);
7294 gen_store_fpr32h(fp, fd);
a16336e4
TS
7295#endif
7296 gen_set_label(l2);
c905fdac
AJ
7297 tcg_temp_free_i32(fp);
7298 tcg_temp_free_i32(fph);
a16336e4 7299 }
5a5012ec
TS
7300 opn = "alnv.ps";
7301 break;
7302 case OPC_MADD_S:
b8aa4598 7303 check_cop1x(ctx);
b6d96bed 7304 {
a7812ae4
PB
7305 TCGv_i32 fp0 = tcg_temp_new_i32();
7306 TCGv_i32 fp1 = tcg_temp_new_i32();
7307 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7308
7309 gen_load_fpr32(fp0, fs);
7310 gen_load_fpr32(fp1, ft);
7311 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7312 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7313 tcg_temp_free_i32(fp0);
7314 tcg_temp_free_i32(fp1);
b6d96bed 7315 gen_store_fpr32(fp2, fd);
a7812ae4 7316 tcg_temp_free_i32(fp2);
b6d96bed 7317 }
5a5012ec
TS
7318 opn = "madd.s";
7319 break;
7320 case OPC_MADD_D:
b8aa4598
TS
7321 check_cop1x(ctx);
7322 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7323 {
a7812ae4
PB
7324 TCGv_i64 fp0 = tcg_temp_new_i64();
7325 TCGv_i64 fp1 = tcg_temp_new_i64();
7326 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7327
7328 gen_load_fpr64(ctx, fp0, fs);
7329 gen_load_fpr64(ctx, fp1, ft);
7330 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7331 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7332 tcg_temp_free_i64(fp0);
7333 tcg_temp_free_i64(fp1);
b6d96bed 7334 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7335 tcg_temp_free_i64(fp2);
b6d96bed 7336 }
5a5012ec
TS
7337 opn = "madd.d";
7338 break;
7339 case OPC_MADD_PS:
b8aa4598 7340 check_cp1_64bitmode(ctx);
b6d96bed 7341 {
a7812ae4
PB
7342 TCGv_i64 fp0 = tcg_temp_new_i64();
7343 TCGv_i64 fp1 = tcg_temp_new_i64();
7344 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7345
7346 gen_load_fpr64(ctx, fp0, fs);
7347 gen_load_fpr64(ctx, fp1, ft);
7348 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7349 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7350 tcg_temp_free_i64(fp0);
7351 tcg_temp_free_i64(fp1);
b6d96bed 7352 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7353 tcg_temp_free_i64(fp2);
b6d96bed 7354 }
5a5012ec
TS
7355 opn = "madd.ps";
7356 break;
7357 case OPC_MSUB_S:
b8aa4598 7358 check_cop1x(ctx);
b6d96bed 7359 {
a7812ae4
PB
7360 TCGv_i32 fp0 = tcg_temp_new_i32();
7361 TCGv_i32 fp1 = tcg_temp_new_i32();
7362 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7363
7364 gen_load_fpr32(fp0, fs);
7365 gen_load_fpr32(fp1, ft);
7366 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7367 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7368 tcg_temp_free_i32(fp0);
7369 tcg_temp_free_i32(fp1);
b6d96bed 7370 gen_store_fpr32(fp2, fd);
a7812ae4 7371 tcg_temp_free_i32(fp2);
b6d96bed 7372 }
5a5012ec
TS
7373 opn = "msub.s";
7374 break;
7375 case OPC_MSUB_D:
b8aa4598
TS
7376 check_cop1x(ctx);
7377 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7378 {
a7812ae4
PB
7379 TCGv_i64 fp0 = tcg_temp_new_i64();
7380 TCGv_i64 fp1 = tcg_temp_new_i64();
7381 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7382
7383 gen_load_fpr64(ctx, fp0, fs);
7384 gen_load_fpr64(ctx, fp1, ft);
7385 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7386 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7387 tcg_temp_free_i64(fp0);
7388 tcg_temp_free_i64(fp1);
b6d96bed 7389 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7390 tcg_temp_free_i64(fp2);
b6d96bed 7391 }
5a5012ec
TS
7392 opn = "msub.d";
7393 break;
7394 case OPC_MSUB_PS:
b8aa4598 7395 check_cp1_64bitmode(ctx);
b6d96bed 7396 {
a7812ae4
PB
7397 TCGv_i64 fp0 = tcg_temp_new_i64();
7398 TCGv_i64 fp1 = tcg_temp_new_i64();
7399 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7400
7401 gen_load_fpr64(ctx, fp0, fs);
7402 gen_load_fpr64(ctx, fp1, ft);
7403 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7404 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7405 tcg_temp_free_i64(fp0);
7406 tcg_temp_free_i64(fp1);
b6d96bed 7407 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7408 tcg_temp_free_i64(fp2);
b6d96bed 7409 }
5a5012ec
TS
7410 opn = "msub.ps";
7411 break;
7412 case OPC_NMADD_S:
b8aa4598 7413 check_cop1x(ctx);
b6d96bed 7414 {
a7812ae4
PB
7415 TCGv_i32 fp0 = tcg_temp_new_i32();
7416 TCGv_i32 fp1 = tcg_temp_new_i32();
7417 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7418
7419 gen_load_fpr32(fp0, fs);
7420 gen_load_fpr32(fp1, ft);
7421 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7422 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
7423 tcg_temp_free_i32(fp0);
7424 tcg_temp_free_i32(fp1);
b6d96bed 7425 gen_store_fpr32(fp2, fd);
a7812ae4 7426 tcg_temp_free_i32(fp2);
b6d96bed 7427 }
5a5012ec
TS
7428 opn = "nmadd.s";
7429 break;
7430 case OPC_NMADD_D:
b8aa4598
TS
7431 check_cop1x(ctx);
7432 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7433 {
a7812ae4
PB
7434 TCGv_i64 fp0 = tcg_temp_new_i64();
7435 TCGv_i64 fp1 = tcg_temp_new_i64();
7436 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7437
7438 gen_load_fpr64(ctx, fp0, fs);
7439 gen_load_fpr64(ctx, fp1, ft);
7440 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7441 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
7442 tcg_temp_free_i64(fp0);
7443 tcg_temp_free_i64(fp1);
b6d96bed 7444 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7445 tcg_temp_free_i64(fp2);
b6d96bed 7446 }
5a5012ec
TS
7447 opn = "nmadd.d";
7448 break;
7449 case OPC_NMADD_PS:
b8aa4598 7450 check_cp1_64bitmode(ctx);
b6d96bed 7451 {
a7812ae4
PB
7452 TCGv_i64 fp0 = tcg_temp_new_i64();
7453 TCGv_i64 fp1 = tcg_temp_new_i64();
7454 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7455
7456 gen_load_fpr64(ctx, fp0, fs);
7457 gen_load_fpr64(ctx, fp1, ft);
7458 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7459 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
7460 tcg_temp_free_i64(fp0);
7461 tcg_temp_free_i64(fp1);
b6d96bed 7462 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7463 tcg_temp_free_i64(fp2);
b6d96bed 7464 }
5a5012ec
TS
7465 opn = "nmadd.ps";
7466 break;
7467 case OPC_NMSUB_S:
b8aa4598 7468 check_cop1x(ctx);
b6d96bed 7469 {
a7812ae4
PB
7470 TCGv_i32 fp0 = tcg_temp_new_i32();
7471 TCGv_i32 fp1 = tcg_temp_new_i32();
7472 TCGv_i32 fp2 = tcg_temp_new_i32();
b6d96bed
TS
7473
7474 gen_load_fpr32(fp0, fs);
7475 gen_load_fpr32(fp1, ft);
7476 gen_load_fpr32(fp2, fr);
a7812ae4
PB
7477 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
7478 tcg_temp_free_i32(fp0);
7479 tcg_temp_free_i32(fp1);
b6d96bed 7480 gen_store_fpr32(fp2, fd);
a7812ae4 7481 tcg_temp_free_i32(fp2);
b6d96bed 7482 }
5a5012ec
TS
7483 opn = "nmsub.s";
7484 break;
7485 case OPC_NMSUB_D:
b8aa4598
TS
7486 check_cop1x(ctx);
7487 check_cp1_registers(ctx, fd | fs | ft | fr);
b6d96bed 7488 {
a7812ae4
PB
7489 TCGv_i64 fp0 = tcg_temp_new_i64();
7490 TCGv_i64 fp1 = tcg_temp_new_i64();
7491 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7492
7493 gen_load_fpr64(ctx, fp0, fs);
7494 gen_load_fpr64(ctx, fp1, ft);
7495 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7496 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
7497 tcg_temp_free_i64(fp0);
7498 tcg_temp_free_i64(fp1);
b6d96bed 7499 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7500 tcg_temp_free_i64(fp2);
b6d96bed 7501 }
5a5012ec
TS
7502 opn = "nmsub.d";
7503 break;
7504 case OPC_NMSUB_PS:
b8aa4598 7505 check_cp1_64bitmode(ctx);
b6d96bed 7506 {
a7812ae4
PB
7507 TCGv_i64 fp0 = tcg_temp_new_i64();
7508 TCGv_i64 fp1 = tcg_temp_new_i64();
7509 TCGv_i64 fp2 = tcg_temp_new_i64();
b6d96bed
TS
7510
7511 gen_load_fpr64(ctx, fp0, fs);
7512 gen_load_fpr64(ctx, fp1, ft);
7513 gen_load_fpr64(ctx, fp2, fr);
a7812ae4
PB
7514 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
7515 tcg_temp_free_i64(fp0);
7516 tcg_temp_free_i64(fp1);
b6d96bed 7517 gen_store_fpr64(ctx, fp2, fd);
a7812ae4 7518 tcg_temp_free_i64(fp2);
b6d96bed 7519 }
5a5012ec
TS
7520 opn = "nmsub.ps";
7521 break;
923617a3
TS
7522 default:
7523 MIPS_INVAL(opn);
5a5012ec
TS
7524 generate_exception (ctx, EXCP_RI);
7525 return;
7526 }
7527 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
7528 fregnames[fs], fregnames[ft]);
7a387fff
TS
7529}
7530
c9602061
NF
7531static void handle_delay_slot (CPUState *env, DisasContext *ctx,
7532 int insn_bytes)
7533{
7534 if (ctx->hflags & MIPS_HFLAG_BMASK) {
364d4831 7535 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
c9602061
NF
7536 /* Branches completion */
7537 ctx->hflags &= ~MIPS_HFLAG_BMASK;
7538 ctx->bstate = BS_BRANCH;
7539 save_cpu_state(ctx, 0);
7540 /* FIXME: Need to clear can_do_io. */
364d4831 7541 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
c9602061
NF
7542 case MIPS_HFLAG_B:
7543 /* unconditional branch */
7544 MIPS_DEBUG("unconditional branch");
364d4831
NF
7545 if (proc_hflags & MIPS_HFLAG_BX) {
7546 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
7547 }
c9602061
NF
7548 gen_goto_tb(ctx, 0, ctx->btarget);
7549 break;
7550 case MIPS_HFLAG_BL:
7551 /* blikely taken case */
7552 MIPS_DEBUG("blikely branch taken");
7553 gen_goto_tb(ctx, 0, ctx->btarget);
7554 break;
7555 case MIPS_HFLAG_BC:
7556 /* Conditional branch */
7557 MIPS_DEBUG("conditional branch");
7558 {
7559 int l1 = gen_new_label();
7560
7561 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
7562 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
7563 gen_set_label(l1);
7564 gen_goto_tb(ctx, 0, ctx->btarget);
7565 }
7566 break;
7567 case MIPS_HFLAG_BR:
7568 /* unconditional branch to register */
7569 MIPS_DEBUG("branch to register");
364d4831
NF
7570 if (env->insn_flags & ASE_MIPS16) {
7571 TCGv t0 = tcg_temp_new();
7572 TCGv_i32 t1 = tcg_temp_new_i32();
7573
7574 tcg_gen_andi_tl(t0, btarget, 0x1);
7575 tcg_gen_trunc_tl_i32(t1, t0);
7576 tcg_temp_free(t0);
7577 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
7578 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
7579 tcg_gen_or_i32(hflags, hflags, t1);
7580 tcg_temp_free_i32(t1);
7581
7582 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
7583 } else {
7584 tcg_gen_mov_tl(cpu_PC, btarget);
7585 }
c9602061
NF
7586 if (ctx->singlestep_enabled) {
7587 save_cpu_state(ctx, 0);
7588 gen_helper_0i(raise_exception, EXCP_DEBUG);
7589 }
7590 tcg_gen_exit_tb(0);
7591 break;
7592 default:
7593 MIPS_DEBUG("unknown branch");
7594 break;
7595 }
7596 }
7597}
7598
7a387fff 7599/* ISA extensions (ASEs) */
6af0bf9c 7600/* MIPS16 extension to MIPS32 */
6ea219d0
NF
7601
7602/* MIPS16 major opcodes */
7603enum {
7604 M16_OPC_ADDIUSP = 0x00,
7605 M16_OPC_ADDIUPC = 0x01,
7606 M16_OPC_B = 0x02,
7607 M16_OPC_JAL = 0x03,
7608 M16_OPC_BEQZ = 0x04,
7609 M16_OPC_BNEQZ = 0x05,
7610 M16_OPC_SHIFT = 0x06,
7611 M16_OPC_LD = 0x07,
7612 M16_OPC_RRIA = 0x08,
7613 M16_OPC_ADDIU8 = 0x09,
7614 M16_OPC_SLTI = 0x0a,
7615 M16_OPC_SLTIU = 0x0b,
7616 M16_OPC_I8 = 0x0c,
7617 M16_OPC_LI = 0x0d,
7618 M16_OPC_CMPI = 0x0e,
7619 M16_OPC_SD = 0x0f,
7620 M16_OPC_LB = 0x10,
7621 M16_OPC_LH = 0x11,
7622 M16_OPC_LWSP = 0x12,
7623 M16_OPC_LW = 0x13,
7624 M16_OPC_LBU = 0x14,
7625 M16_OPC_LHU = 0x15,
7626 M16_OPC_LWPC = 0x16,
7627 M16_OPC_LWU = 0x17,
7628 M16_OPC_SB = 0x18,
7629 M16_OPC_SH = 0x19,
7630 M16_OPC_SWSP = 0x1a,
7631 M16_OPC_SW = 0x1b,
7632 M16_OPC_RRR = 0x1c,
7633 M16_OPC_RR = 0x1d,
7634 M16_OPC_EXTEND = 0x1e,
7635 M16_OPC_I64 = 0x1f
7636};
7637
7638/* I8 funct field */
7639enum {
7640 I8_BTEQZ = 0x0,
7641 I8_BTNEZ = 0x1,
7642 I8_SWRASP = 0x2,
7643 I8_ADJSP = 0x3,
7644 I8_SVRS = 0x4,
7645 I8_MOV32R = 0x5,
7646 I8_MOVR32 = 0x7
7647};
7648
7649/* RRR f field */
7650enum {
7651 RRR_DADDU = 0x0,
7652 RRR_ADDU = 0x1,
7653 RRR_DSUBU = 0x2,
7654 RRR_SUBU = 0x3
7655};
7656
7657/* RR funct field */
7658enum {
7659 RR_JR = 0x00,
7660 RR_SDBBP = 0x01,
7661 RR_SLT = 0x02,
7662 RR_SLTU = 0x03,
7663 RR_SLLV = 0x04,
7664 RR_BREAK = 0x05,
7665 RR_SRLV = 0x06,
7666 RR_SRAV = 0x07,
7667 RR_DSRL = 0x08,
7668 RR_CMP = 0x0a,
7669 RR_NEG = 0x0b,
7670 RR_AND = 0x0c,
7671 RR_OR = 0x0d,
7672 RR_XOR = 0x0e,
7673 RR_NOT = 0x0f,
7674 RR_MFHI = 0x10,
7675 RR_CNVT = 0x11,
7676 RR_MFLO = 0x12,
7677 RR_DSRA = 0x13,
7678 RR_DSLLV = 0x14,
7679 RR_DSRLV = 0x16,
7680 RR_DSRAV = 0x17,
7681 RR_MULT = 0x18,
7682 RR_MULTU = 0x19,
7683 RR_DIV = 0x1a,
7684 RR_DIVU = 0x1b,
7685 RR_DMULT = 0x1c,
7686 RR_DMULTU = 0x1d,
7687 RR_DDIV = 0x1e,
7688 RR_DDIVU = 0x1f
7689};
7690
7691/* I64 funct field */
7692enum {
7693 I64_LDSP = 0x0,
7694 I64_SDSP = 0x1,
7695 I64_SDRASP = 0x2,
7696 I64_DADJSP = 0x3,
7697 I64_LDPC = 0x4,
364d4831 7698 I64_DADDIU5 = 0x5,
6ea219d0
NF
7699 I64_DADDIUPC = 0x6,
7700 I64_DADDIUSP = 0x7
7701};
7702
7703/* RR ry field for CNVT */
7704enum {
7705 RR_RY_CNVT_ZEB = 0x0,
7706 RR_RY_CNVT_ZEH = 0x1,
7707 RR_RY_CNVT_ZEW = 0x2,
7708 RR_RY_CNVT_SEB = 0x4,
7709 RR_RY_CNVT_SEH = 0x5,
7710 RR_RY_CNVT_SEW = 0x6,
7711};
7712
364d4831
NF
7713static int xlat (int r)
7714{
7715 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
7716
7717 return map[r];
7718}
7719
7720static void gen_mips16_save (DisasContext *ctx,
7721 int xsregs, int aregs,
7722 int do_ra, int do_s0, int do_s1,
7723 int framesize)
7724{
7725 TCGv t0 = tcg_temp_new();
7726 TCGv t1 = tcg_temp_new();
7727 int args, astatic;
7728
7729 switch (aregs) {
7730 case 0:
7731 case 1:
7732 case 2:
7733 case 3:
7734 case 11:
7735 args = 0;
7736 break;
7737 case 4:
7738 case 5:
7739 case 6:
7740 case 7:
7741 args = 1;
7742 break;
7743 case 8:
7744 case 9:
7745 case 10:
7746 args = 2;
7747 break;
7748 case 12:
7749 case 13:
7750 args = 3;
7751 break;
7752 case 14:
7753 args = 4;
7754 break;
7755 default:
7756 generate_exception(ctx, EXCP_RI);
7757 return;
7758 }
7759
7760 switch (args) {
7761 case 4:
7762 gen_base_offset_addr(ctx, t0, 29, 12);
7763 gen_load_gpr(t1, 7);
7764 op_ldst_sw(t1, t0, ctx);
7765 /* Fall through */
7766 case 3:
7767 gen_base_offset_addr(ctx, t0, 29, 8);
7768 gen_load_gpr(t1, 6);
7769 op_ldst_sw(t1, t0, ctx);
7770 /* Fall through */
7771 case 2:
7772 gen_base_offset_addr(ctx, t0, 29, 4);
7773 gen_load_gpr(t1, 5);
7774 op_ldst_sw(t1, t0, ctx);
7775 /* Fall through */
7776 case 1:
7777 gen_base_offset_addr(ctx, t0, 29, 0);
7778 gen_load_gpr(t1, 4);
7779 op_ldst_sw(t1, t0, ctx);
7780 }
7781
7782 gen_load_gpr(t0, 29);
7783
7784#define DECR_AND_STORE(reg) do { \
7785 tcg_gen_subi_tl(t0, t0, 4); \
7786 gen_load_gpr(t1, reg); \
7787 op_ldst_sw(t1, t0, ctx); \
7788 } while (0)
7789
7790 if (do_ra) {
7791 DECR_AND_STORE(31);
7792 }
7793
7794 switch (xsregs) {
7795 case 7:
7796 DECR_AND_STORE(30);
7797 /* Fall through */
7798 case 6:
7799 DECR_AND_STORE(23);
7800 /* Fall through */
7801 case 5:
7802 DECR_AND_STORE(22);
7803 /* Fall through */
7804 case 4:
7805 DECR_AND_STORE(21);
7806 /* Fall through */
7807 case 3:
7808 DECR_AND_STORE(20);
7809 /* Fall through */
7810 case 2:
7811 DECR_AND_STORE(19);
7812 /* Fall through */
7813 case 1:
7814 DECR_AND_STORE(18);
7815 }
7816
7817 if (do_s1) {
7818 DECR_AND_STORE(17);
7819 }
7820 if (do_s0) {
7821 DECR_AND_STORE(16);
7822 }
7823
7824 switch (aregs) {
7825 case 0:
7826 case 4:
7827 case 8:
7828 case 12:
7829 case 14:
7830 astatic = 0;
7831 break;
7832 case 1:
7833 case 5:
7834 case 9:
7835 case 13:
7836 astatic = 1;
7837 break;
7838 case 2:
7839 case 6:
7840 case 10:
7841 astatic = 2;
7842 break;
7843 case 3:
7844 case 7:
7845 astatic = 3;
7846 break;
7847 case 11:
7848 astatic = 4;
7849 break;
7850 default:
7851 generate_exception(ctx, EXCP_RI);
7852 return;
7853 }
7854
7855 if (astatic > 0) {
7856 DECR_AND_STORE(7);
7857 if (astatic > 1) {
7858 DECR_AND_STORE(6);
7859 if (astatic > 2) {
7860 DECR_AND_STORE(5);
7861 if (astatic > 3) {
7862 DECR_AND_STORE(4);
7863 }
7864 }
7865 }
7866 }
7867#undef DECR_AND_STORE
7868
7869 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7870 tcg_temp_free(t0);
7871 tcg_temp_free(t1);
7872}
7873
7874static void gen_mips16_restore (DisasContext *ctx,
7875 int xsregs, int aregs,
7876 int do_ra, int do_s0, int do_s1,
7877 int framesize)
7878{
7879 int astatic;
7880 TCGv t0 = tcg_temp_new();
7881 TCGv t1 = tcg_temp_new();
7882
7883 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
7884
7885#define DECR_AND_LOAD(reg) do { \
7886 tcg_gen_subi_tl(t0, t0, 4); \
7887 op_ldst_lw(t1, t0, ctx); \
7888 gen_store_gpr(t1, reg); \
7889 } while (0)
7890
7891 if (do_ra) {
7892 DECR_AND_LOAD(31);
7893 }
7894
7895 switch (xsregs) {
7896 case 7:
7897 DECR_AND_LOAD(30);
7898 /* Fall through */
7899 case 6:
7900 DECR_AND_LOAD(23);
7901 /* Fall through */
7902 case 5:
7903 DECR_AND_LOAD(22);
7904 /* Fall through */
7905 case 4:
7906 DECR_AND_LOAD(21);
7907 /* Fall through */
7908 case 3:
7909 DECR_AND_LOAD(20);
7910 /* Fall through */
7911 case 2:
7912 DECR_AND_LOAD(19);
7913 /* Fall through */
7914 case 1:
7915 DECR_AND_LOAD(18);
7916 }
7917
7918 if (do_s1) {
7919 DECR_AND_LOAD(17);
7920 }
7921 if (do_s0) {
7922 DECR_AND_LOAD(16);
7923 }
7924
7925 switch (aregs) {
7926 case 0:
7927 case 4:
7928 case 8:
7929 case 12:
7930 case 14:
7931 astatic = 0;
7932 break;
7933 case 1:
7934 case 5:
7935 case 9:
7936 case 13:
7937 astatic = 1;
7938 break;
7939 case 2:
7940 case 6:
7941 case 10:
7942 astatic = 2;
7943 break;
7944 case 3:
7945 case 7:
7946 astatic = 3;
7947 break;
7948 case 11:
7949 astatic = 4;
7950 break;
7951 default:
7952 generate_exception(ctx, EXCP_RI);
7953 return;
7954 }
7955
7956 if (astatic > 0) {
7957 DECR_AND_LOAD(7);
7958 if (astatic > 1) {
7959 DECR_AND_LOAD(6);
7960 if (astatic > 2) {
7961 DECR_AND_LOAD(5);
7962 if (astatic > 3) {
7963 DECR_AND_LOAD(4);
7964 }
7965 }
7966 }
7967 }
7968#undef DECR_AND_LOAD
7969
7970 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
7971 tcg_temp_free(t0);
7972 tcg_temp_free(t1);
7973}
7974
7975static void gen_addiupc (DisasContext *ctx, int rx, int imm,
7976 int is_64_bit, int extended)
7977{
7978 TCGv t0;
7979
7980 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
7981 generate_exception(ctx, EXCP_RI);
7982 return;
7983 }
7984
7985 t0 = tcg_temp_new();
7986
7987 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
7988 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
7989 if (!is_64_bit) {
7990 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
7991 }
7992
7993 tcg_temp_free(t0);
7994}
7995
7996#if defined(TARGET_MIPS64)
7997static void decode_i64_mips16 (CPUState *env, DisasContext *ctx,
7998 int ry, int funct, int16_t offset,
7999 int extended)
8000{
8001 switch (funct) {
8002 case I64_LDSP:
8003 check_mips_64(ctx);
8004 offset = extended ? offset : offset << 3;
8005 gen_ldst(ctx, OPC_LD, ry, 29, offset);
8006 break;
8007 case I64_SDSP:
8008 check_mips_64(ctx);
8009 offset = extended ? offset : offset << 3;
8010 gen_ldst(ctx, OPC_SD, ry, 29, offset);
8011 break;
8012 case I64_SDRASP:
8013 check_mips_64(ctx);
8014 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8015 gen_ldst(ctx, OPC_SD, 31, 29, offset);
8016 break;
8017 case I64_DADJSP:
8018 check_mips_64(ctx);
8019 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8020 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8021 break;
8022 case I64_LDPC:
8023 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8024 generate_exception(ctx, EXCP_RI);
8025 } else {
8026 offset = extended ? offset : offset << 3;
8027 gen_ldst(ctx, OPC_LDPC, ry, 0, offset);
8028 }
8029 break;
8030 case I64_DADDIU5:
8031 check_mips_64(ctx);
8032 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8033 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8034 break;
8035 case I64_DADDIUPC:
8036 check_mips_64(ctx);
8037 offset = extended ? offset : offset << 2;
8038 gen_addiupc(ctx, ry, offset, 1, extended);
8039 break;
8040 case I64_DADDIUSP:
8041 check_mips_64(ctx);
8042 offset = extended ? offset : offset << 2;
8043 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8044 break;
8045 }
8046}
8047#endif
8048
8049static int decode_extended_mips16_opc (CPUState *env, DisasContext *ctx,
8050 int *is_branch)
8051{
8052 int extend = lduw_code(ctx->pc + 2);
8053 int op, rx, ry, funct, sa;
8054 int16_t imm, offset;
8055
8056 ctx->opcode = (ctx->opcode << 16) | extend;
8057 op = (ctx->opcode >> 11) & 0x1f;
8058 sa = (ctx->opcode >> 22) & 0x1f;
8059 funct = (ctx->opcode >> 8) & 0x7;
8060 rx = xlat((ctx->opcode >> 8) & 0x7);
8061 ry = xlat((ctx->opcode >> 5) & 0x7);
8062 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8063 | ((ctx->opcode >> 21) & 0x3f) << 5
8064 | (ctx->opcode & 0x1f));
8065
8066 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8067 counterparts. */
8068 switch (op) {
8069 case M16_OPC_ADDIUSP:
8070 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8071 break;
8072 case M16_OPC_ADDIUPC:
8073 gen_addiupc(ctx, rx, imm, 0, 1);
8074 break;
8075 case M16_OPC_B:
8076 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8077 /* No delay slot, so just process as a normal instruction */
8078 break;
8079 case M16_OPC_BEQZ:
8080 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8081 /* No delay slot, so just process as a normal instruction */
8082 break;
8083 case M16_OPC_BNEQZ:
8084 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8085 /* No delay slot, so just process as a normal instruction */
8086 break;
8087 case M16_OPC_SHIFT:
8088 switch (ctx->opcode & 0x3) {
8089 case 0x0:
8090 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8091 break;
8092 case 0x1:
8093#if defined(TARGET_MIPS64)
8094 check_mips_64(ctx);
8095 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8096#else
8097 generate_exception(ctx, EXCP_RI);
8098#endif
8099 break;
8100 case 0x2:
8101 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8102 break;
8103 case 0x3:
8104 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8105 break;
8106 }
8107 break;
8108#if defined(TARGET_MIPS64)
8109 case M16_OPC_LD:
8110 check_mips_64(ctx);
8111 gen_ldst(ctx, OPC_LD, ry, rx, offset);
8112 break;
8113#endif
8114 case M16_OPC_RRIA:
8115 imm = ctx->opcode & 0xf;
8116 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8117 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8118 imm = (int16_t) (imm << 1) >> 1;
8119 if ((ctx->opcode >> 4) & 0x1) {
8120#if defined(TARGET_MIPS64)
8121 check_mips_64(ctx);
8122 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8123#else
8124 generate_exception(ctx, EXCP_RI);
8125#endif
8126 } else {
8127 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8128 }
8129 break;
8130 case M16_OPC_ADDIU8:
8131 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8132 break;
8133 case M16_OPC_SLTI:
8134 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8135 break;
8136 case M16_OPC_SLTIU:
8137 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8138 break;
8139 case M16_OPC_I8:
8140 switch (funct) {
8141 case I8_BTEQZ:
8142 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8143 break;
8144 case I8_BTNEZ:
8145 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8146 break;
8147 case I8_SWRASP:
8148 gen_ldst(ctx, OPC_SW, 31, 29, imm);
8149 break;
8150 case I8_ADJSP:
8151 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8152 break;
8153 case I8_SVRS:
8154 {
8155 int xsregs = (ctx->opcode >> 24) & 0x7;
8156 int aregs = (ctx->opcode >> 16) & 0xf;
8157 int do_ra = (ctx->opcode >> 6) & 0x1;
8158 int do_s0 = (ctx->opcode >> 5) & 0x1;
8159 int do_s1 = (ctx->opcode >> 4) & 0x1;
8160 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8161 | (ctx->opcode & 0xf)) << 3;
8162
8163 if (ctx->opcode & (1 << 7)) {
8164 gen_mips16_save(ctx, xsregs, aregs,
8165 do_ra, do_s0, do_s1,
8166 framesize);
8167 } else {
8168 gen_mips16_restore(ctx, xsregs, aregs,
8169 do_ra, do_s0, do_s1,
8170 framesize);
8171 }
8172 }
8173 break;
8174 default:
8175 generate_exception(ctx, EXCP_RI);
8176 break;
8177 }
8178 break;
8179 case M16_OPC_LI:
8180 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8181 break;
8182 case M16_OPC_CMPI:
8183 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8184 break;
8185#if defined(TARGET_MIPS64)
8186 case M16_OPC_SD:
8187 gen_ldst(ctx, OPC_SD, ry, rx, offset);
8188 break;
8189#endif
8190 case M16_OPC_LB:
8191 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8192 break;
8193 case M16_OPC_LH:
8194 gen_ldst(ctx, OPC_LH, ry, rx, offset);
8195 break;
8196 case M16_OPC_LWSP:
8197 gen_ldst(ctx, OPC_LW, rx, 29, offset);
8198 break;
8199 case M16_OPC_LW:
8200 gen_ldst(ctx, OPC_LW, ry, rx, offset);
8201 break;
8202 case M16_OPC_LBU:
8203 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8204 break;
8205 case M16_OPC_LHU:
8206 gen_ldst(ctx, OPC_LHU, ry, rx, offset);
8207 break;
8208 case M16_OPC_LWPC:
8209 gen_ldst(ctx, OPC_LWPC, rx, 0, offset);
8210 break;
8211#if defined(TARGET_MIPS64)
8212 case M16_OPC_LWU:
8213 gen_ldst(ctx, OPC_LWU, ry, rx, offset);
8214 break;
8215#endif
8216 case M16_OPC_SB:
8217 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8218 break;
8219 case M16_OPC_SH:
8220 gen_ldst(ctx, OPC_SH, ry, rx, offset);
8221 break;
8222 case M16_OPC_SWSP:
8223 gen_ldst(ctx, OPC_SW, rx, 29, offset);
8224 break;
8225 case M16_OPC_SW:
8226 gen_ldst(ctx, OPC_SW, ry, rx, offset);
8227 break;
8228#if defined(TARGET_MIPS64)
8229 case M16_OPC_I64:
8230 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8231 break;
8232#endif
8233 default:
8234 generate_exception(ctx, EXCP_RI);
8235 break;
8236 }
8237
8238 return 4;
8239}
8240
8241static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
8242 int *is_branch)
8243{
8244 int rx, ry;
8245 int sa;
8246 int op, cnvt_op, op1, offset;
8247 int funct;
8248 int n_bytes;
8249
8250 op = (ctx->opcode >> 11) & 0x1f;
8251 sa = (ctx->opcode >> 2) & 0x7;
8252 sa = sa == 0 ? 8 : sa;
8253 rx = xlat((ctx->opcode >> 8) & 0x7);
8254 cnvt_op = (ctx->opcode >> 5) & 0x7;
8255 ry = xlat((ctx->opcode >> 5) & 0x7);
8256 op1 = offset = ctx->opcode & 0x1f;
8257
8258 n_bytes = 2;
8259
8260 switch (op) {
8261 case M16_OPC_ADDIUSP:
8262 {
8263 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8264
8265 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8266 }
8267 break;
8268 case M16_OPC_ADDIUPC:
8269 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8270 break;
8271 case M16_OPC_B:
8272 offset = (ctx->opcode & 0x7ff) << 1;
8273 offset = (int16_t)(offset << 4) >> 4;
8274 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8275 /* No delay slot, so just process as a normal instruction */
8276 break;
8277 case M16_OPC_JAL:
8278 offset = lduw_code(ctx->pc + 2);
8279 offset = (((ctx->opcode & 0x1f) << 21)
8280 | ((ctx->opcode >> 5) & 0x1f) << 16
8281 | offset) << 2;
8282 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
8283 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8284 n_bytes = 4;
8285 *is_branch = 1;
8286 break;
8287 case M16_OPC_BEQZ:
8288 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8289 /* No delay slot, so just process as a normal instruction */
8290 break;
8291 case M16_OPC_BNEQZ:
8292 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8293 /* No delay slot, so just process as a normal instruction */
8294 break;
8295 case M16_OPC_SHIFT:
8296 switch (ctx->opcode & 0x3) {
8297 case 0x0:
8298 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8299 break;
8300 case 0x1:
8301#if defined(TARGET_MIPS64)
8302 check_mips_64(ctx);
8303 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8304#else
8305 generate_exception(ctx, EXCP_RI);
8306#endif
8307 break;
8308 case 0x2:
8309 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8310 break;
8311 case 0x3:
8312 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8313 break;
8314 }
8315 break;
8316#if defined(TARGET_MIPS64)
8317 case M16_OPC_LD:
8318 check_mips_64(ctx);
8319 gen_ldst(ctx, OPC_LD, ry, rx, offset << 3);
8320 break;
8321#endif
8322 case M16_OPC_RRIA:
8323 {
8324 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8325
8326 if ((ctx->opcode >> 4) & 1) {
8327#if defined(TARGET_MIPS64)
8328 check_mips_64(ctx);
8329 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8330#else
8331 generate_exception(ctx, EXCP_RI);
8332#endif
8333 } else {
8334 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8335 }
8336 }
8337 break;
8338 case M16_OPC_ADDIU8:
8339 {
8340 int16_t imm = (int8_t) ctx->opcode;
8341
8342 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8343 }
8344 break;
8345 case M16_OPC_SLTI:
8346 {
8347 int16_t imm = (uint8_t) ctx->opcode;
8348
8349 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8350 }
8351 break;
8352 case M16_OPC_SLTIU:
8353 {
8354 int16_t imm = (uint8_t) ctx->opcode;
8355
8356 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8357 }
8358 break;
8359 case M16_OPC_I8:
8360 {
8361 int reg32;
8362
8363 funct = (ctx->opcode >> 8) & 0x7;
8364 switch (funct) {
8365 case I8_BTEQZ:
8366 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8367 ((int8_t)ctx->opcode) << 1);
8368 break;
8369 case I8_BTNEZ:
8370 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8371 ((int8_t)ctx->opcode) << 1);
8372 break;
8373 case I8_SWRASP:
8374 gen_ldst(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
8375 break;
8376 case I8_ADJSP:
8377 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
8378 ((int8_t)ctx->opcode) << 3);
8379 break;
8380 case I8_SVRS:
8381 {
8382 int do_ra = ctx->opcode & (1 << 6);
8383 int do_s0 = ctx->opcode & (1 << 5);
8384 int do_s1 = ctx->opcode & (1 << 4);
8385 int framesize = ctx->opcode & 0xf;
8386
8387 if (framesize == 0) {
8388 framesize = 128;
8389 } else {
8390 framesize = framesize << 3;
8391 }
8392
8393 if (ctx->opcode & (1 << 7)) {
8394 gen_mips16_save(ctx, 0, 0,
8395 do_ra, do_s0, do_s1, framesize);
8396 } else {
8397 gen_mips16_restore(ctx, 0, 0,
8398 do_ra, do_s0, do_s1, framesize);
8399 }
8400 }
8401 break;
8402 case I8_MOV32R:
8403 {
8404 int rz = xlat(ctx->opcode & 0x7);
8405
8406 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
8407 ((ctx->opcode >> 5) & 0x7);
8408 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
8409 }
8410 break;
8411 case I8_MOVR32:
8412 reg32 = ctx->opcode & 0x1f;
8413 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
8414 break;
8415 default:
8416 generate_exception(ctx, EXCP_RI);
8417 break;
8418 }
8419 }
8420 break;
8421 case M16_OPC_LI:
8422 {
8423 int16_t imm = (uint8_t) ctx->opcode;
8424
8425 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
8426 }
8427 break;
8428 case M16_OPC_CMPI:
8429 {
8430 int16_t imm = (uint8_t) ctx->opcode;
8431
8432 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
8433 }
8434 break;
8435#if defined(TARGET_MIPS64)
8436 case M16_OPC_SD:
8437 check_mips_64(ctx);
8438 gen_ldst(ctx, OPC_SD, ry, rx, offset << 3);
8439 break;
8440#endif
8441 case M16_OPC_LB:
8442 gen_ldst(ctx, OPC_LB, ry, rx, offset);
8443 break;
8444 case M16_OPC_LH:
8445 gen_ldst(ctx, OPC_LH, ry, rx, offset << 1);
8446 break;
8447 case M16_OPC_LWSP:
8448 gen_ldst(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8449 break;
8450 case M16_OPC_LW:
8451 gen_ldst(ctx, OPC_LW, ry, rx, offset << 2);
8452 break;
8453 case M16_OPC_LBU:
8454 gen_ldst(ctx, OPC_LBU, ry, rx, offset);
8455 break;
8456 case M16_OPC_LHU:
8457 gen_ldst(ctx, OPC_LHU, ry, rx, offset << 1);
8458 break;
8459 case M16_OPC_LWPC:
8460 gen_ldst(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
8461 break;
8462#if defined (TARGET_MIPS64)
8463 case M16_OPC_LWU:
8464 check_mips_64(ctx);
8465 gen_ldst(ctx, OPC_LWU, ry, rx, offset << 2);
8466 break;
8467#endif
8468 case M16_OPC_SB:
8469 gen_ldst(ctx, OPC_SB, ry, rx, offset);
8470 break;
8471 case M16_OPC_SH:
8472 gen_ldst(ctx, OPC_SH, ry, rx, offset << 1);
8473 break;
8474 case M16_OPC_SWSP:
8475 gen_ldst(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
8476 break;
8477 case M16_OPC_SW:
8478 gen_ldst(ctx, OPC_SW, ry, rx, offset << 2);
8479 break;
8480 case M16_OPC_RRR:
8481 {
8482 int rz = xlat((ctx->opcode >> 2) & 0x7);
8483 int mips32_op;
8484
8485 switch (ctx->opcode & 0x3) {
8486 case RRR_ADDU:
8487 mips32_op = OPC_ADDU;
8488 break;
8489 case RRR_SUBU:
8490 mips32_op = OPC_SUBU;
8491 break;
8492#if defined(TARGET_MIPS64)
8493 case RRR_DADDU:
8494 mips32_op = OPC_DADDU;
8495 check_mips_64(ctx);
8496 break;
8497 case RRR_DSUBU:
8498 mips32_op = OPC_DSUBU;
8499 check_mips_64(ctx);
8500 break;
8501#endif
8502 default:
8503 generate_exception(ctx, EXCP_RI);
8504 goto done;
8505 }
8506
8507 gen_arith(env, ctx, mips32_op, rz, rx, ry);
8508 done:
8509 ;
8510 }
8511 break;
8512 case M16_OPC_RR:
8513 switch (op1) {
8514 case RR_JR:
8515 {
8516 int nd = (ctx->opcode >> 7) & 0x1;
8517 int link = (ctx->opcode >> 6) & 0x1;
8518 int ra = (ctx->opcode >> 5) & 0x1;
8519
8520 if (link) {
8521 op = nd ? OPC_JALRC : OPC_JALR;
8522 } else {
8523 op = OPC_JR;
8524 }
8525
8526 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
8527 if (!nd) {
8528 *is_branch = 1;
8529 }
8530 }
8531 break;
8532 case RR_SDBBP:
8533 /* XXX: not clear which exception should be raised
8534 * when in debug mode...
8535 */
8536 check_insn(env, ctx, ISA_MIPS32);
8537 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8538 generate_exception(ctx, EXCP_DBp);
8539 } else {
8540 generate_exception(ctx, EXCP_DBp);
8541 }
8542 break;
8543 case RR_SLT:
8544 gen_slt(env, OPC_SLT, 24, rx, ry);
8545 break;
8546 case RR_SLTU:
8547 gen_slt(env, OPC_SLTU, 24, rx, ry);
8548 break;
8549 case RR_BREAK:
8550 generate_exception(ctx, EXCP_BREAK);
8551 break;
8552 case RR_SLLV:
8553 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
8554 break;
8555 case RR_SRLV:
8556 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
8557 break;
8558 case RR_SRAV:
8559 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
8560 break;
8561#if defined (TARGET_MIPS64)
8562 case RR_DSRL:
8563 check_mips_64(ctx);
8564 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
8565 break;
8566#endif
8567 case RR_CMP:
8568 gen_logic(env, OPC_XOR, 24, rx, ry);
8569 break;
8570 case RR_NEG:
8571 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
8572 break;
8573 case RR_AND:
8574 gen_logic(env, OPC_AND, rx, rx, ry);
8575 break;
8576 case RR_OR:
8577 gen_logic(env, OPC_OR, rx, rx, ry);
8578 break;
8579 case RR_XOR:
8580 gen_logic(env, OPC_XOR, rx, rx, ry);
8581 break;
8582 case RR_NOT:
8583 gen_logic(env, OPC_NOR, rx, ry, 0);
8584 break;
8585 case RR_MFHI:
8586 gen_HILO(ctx, OPC_MFHI, rx);
8587 break;
8588 case RR_CNVT:
8589 switch (cnvt_op) {
8590 case RR_RY_CNVT_ZEB:
8591 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8592 break;
8593 case RR_RY_CNVT_ZEH:
8594 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8595 break;
8596 case RR_RY_CNVT_SEB:
8597 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8598 break;
8599 case RR_RY_CNVT_SEH:
8600 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8601 break;
8602#if defined (TARGET_MIPS64)
8603 case RR_RY_CNVT_ZEW:
8604 check_mips_64(ctx);
8605 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
8606 break;
8607 case RR_RY_CNVT_SEW:
8608 check_mips_64(ctx);
8609 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8610 break;
8611#endif
8612 default:
8613 generate_exception(ctx, EXCP_RI);
8614 break;
8615 }
8616 break;
8617 case RR_MFLO:
8618 gen_HILO(ctx, OPC_MFLO, rx);
8619 break;
8620#if defined (TARGET_MIPS64)
8621 case RR_DSRA:
8622 check_mips_64(ctx);
8623 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
8624 break;
8625 case RR_DSLLV:
8626 check_mips_64(ctx);
8627 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
8628 break;
8629 case RR_DSRLV:
8630 check_mips_64(ctx);
8631 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
8632 break;
8633 case RR_DSRAV:
8634 check_mips_64(ctx);
8635 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
8636 break;
8637#endif
8638 case RR_MULT:
8639 gen_muldiv(ctx, OPC_MULT, rx, ry);
8640 break;
8641 case RR_MULTU:
8642 gen_muldiv(ctx, OPC_MULTU, rx, ry);
8643 break;
8644 case RR_DIV:
8645 gen_muldiv(ctx, OPC_DIV, rx, ry);
8646 break;
8647 case RR_DIVU:
8648 gen_muldiv(ctx, OPC_DIVU, rx, ry);
8649 break;
8650#if defined (TARGET_MIPS64)
8651 case RR_DMULT:
8652 check_mips_64(ctx);
8653 gen_muldiv(ctx, OPC_DMULT, rx, ry);
8654 break;
8655 case RR_DMULTU:
8656 check_mips_64(ctx);
8657 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
8658 break;
8659 case RR_DDIV:
8660 check_mips_64(ctx);
8661 gen_muldiv(ctx, OPC_DDIV, rx, ry);
8662 break;
8663 case RR_DDIVU:
8664 check_mips_64(ctx);
8665 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
8666 break;
8667#endif
8668 default:
8669 generate_exception(ctx, EXCP_RI);
8670 break;
8671 }
8672 break;
8673 case M16_OPC_EXTEND:
8674 decode_extended_mips16_opc(env, ctx, is_branch);
8675 n_bytes = 4;
8676 break;
8677#if defined(TARGET_MIPS64)
8678 case M16_OPC_I64:
8679 funct = (ctx->opcode >> 8) & 0x7;
8680 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
8681 break;
8682#endif
8683 default:
8684 generate_exception(ctx, EXCP_RI);
8685 break;
8686 }
8687
8688 return n_bytes;
8689}
8690
6af0bf9c
FB
8691/* SmartMIPS extension to MIPS32 */
8692
d26bc211 8693#if defined(TARGET_MIPS64)
6af0bf9c
FB
8694
8695/* MDMX extension to MIPS64 */
6af0bf9c
FB
8696
8697#endif
8698
c9602061 8699static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
6af0bf9c
FB
8700{
8701 int32_t offset;
8702 int rs, rt, rd, sa;
7a387fff 8703 uint32_t op, op1, op2;
6af0bf9c
FB
8704 int16_t imm;
8705
d796321b
FB
8706 /* make sure instructions are on a word boundary */
8707 if (ctx->pc & 0x3) {
cbeb0857 8708 env->CP0_BadVAddr = ctx->pc;
d796321b
FB
8709 generate_exception(ctx, EXCP_AdEL);
8710 return;
8711 }
8712
8e9ade68 8713 /* Handle blikely not taken case */
c9602061 8714 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
8e9ade68
TS
8715 int l1 = gen_new_label();
8716
3594c774 8717 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
1ba74fb8 8718 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
41db4607 8719 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
5a5012ec
TS
8720 gen_goto_tb(ctx, 1, ctx->pc + 4);
8721 gen_set_label(l1);
6af0bf9c 8722 }
618b0fe9
AJ
8723
8724 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
8725 tcg_gen_debug_insn_start(ctx->pc);
8726
7a387fff
TS
8727 op = MASK_OP_MAJOR(ctx->opcode);
8728 rs = (ctx->opcode >> 21) & 0x1f;
8729 rt = (ctx->opcode >> 16) & 0x1f;
8730 rd = (ctx->opcode >> 11) & 0x1f;
8731 sa = (ctx->opcode >> 6) & 0x1f;
6af0bf9c
FB
8732 imm = (int16_t)ctx->opcode;
8733 switch (op) {
7a387fff
TS
8734 case OPC_SPECIAL:
8735 op1 = MASK_SPECIAL(ctx->opcode);
6af0bf9c 8736 switch (op1) {
324d9e32
AJ
8737 case OPC_SLL: /* Shift with immediate */
8738 case OPC_SRA:
324d9e32 8739 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 8740 break;
ea63e2c3
NF
8741 case OPC_SRL:
8742 switch ((ctx->opcode >> 21) & 0x1f) {
8743 case 1:
8744 /* rotr is decoded as srl on non-R2 CPUs */
8745 if (env->insn_flags & ISA_MIPS32R2) {
8746 op1 = OPC_ROTR;
8747 }
8748 /* Fallthrough */
8749 case 0:
8750 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8751 break;
8752 default:
8753 generate_exception(ctx, EXCP_RI);
8754 break;
8755 }
8756 break;
460f00c4
AJ
8757 case OPC_MOVN: /* Conditional move */
8758 case OPC_MOVZ:
e189e748 8759 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
460f00c4
AJ
8760 gen_cond_move(env, op1, rd, rs, rt);
8761 break;
8762 case OPC_ADD ... OPC_SUBU:
e189e748 8763 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 8764 break;
460f00c4 8765 case OPC_SLLV: /* Shifts */
460f00c4
AJ
8766 case OPC_SRAV:
8767 gen_shift(env, ctx, op1, rd, rs, rt);
8768 break;
ea63e2c3
NF
8769 case OPC_SRLV:
8770 switch ((ctx->opcode >> 6) & 0x1f) {
8771 case 1:
8772 /* rotrv is decoded as srlv on non-R2 CPUs */
8773 if (env->insn_flags & ISA_MIPS32R2) {
8774 op1 = OPC_ROTRV;
8775 }
8776 /* Fallthrough */
8777 case 0:
8778 gen_shift(env, ctx, op1, rd, rs, rt);
8779 break;
8780 default:
8781 generate_exception(ctx, EXCP_RI);
8782 break;
8783 }
8784 break;
460f00c4
AJ
8785 case OPC_SLT: /* Set on less than */
8786 case OPC_SLTU:
8787 gen_slt(env, op1, rd, rs, rt);
8788 break;
8789 case OPC_AND: /* Logic*/
8790 case OPC_OR:
8791 case OPC_NOR:
8792 case OPC_XOR:
8793 gen_logic(env, op1, rd, rs, rt);
8794 break;
7a387fff 8795 case OPC_MULT ... OPC_DIVU:
e9c71dd1
TS
8796 if (sa) {
8797 check_insn(env, ctx, INSN_VR54XX);
8798 op1 = MASK_MUL_VR54XX(ctx->opcode);
8799 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
8800 } else
8801 gen_muldiv(ctx, op1, rs, rt);
7a387fff
TS
8802 break;
8803 case OPC_JR ... OPC_JALR:
7dca4ad0 8804 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
c9602061
NF
8805 *is_branch = 1;
8806 break;
7a387fff
TS
8807 case OPC_TGE ... OPC_TEQ: /* Traps */
8808 case OPC_TNE:
8809 gen_trap(ctx, op1, rs, rt, -1);
6af0bf9c 8810 break;
7a387fff
TS
8811 case OPC_MFHI: /* Move from HI/LO */
8812 case OPC_MFLO:
8813 gen_HILO(ctx, op1, rd);
6af0bf9c 8814 break;
7a387fff
TS
8815 case OPC_MTHI:
8816 case OPC_MTLO: /* Move to HI/LO */
8817 gen_HILO(ctx, op1, rs);
6af0bf9c 8818 break;
b48cfdff
TS
8819 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
8820#ifdef MIPS_STRICT_STANDARD
8821 MIPS_INVAL("PMON / selsl");
8822 generate_exception(ctx, EXCP_RI);
8823#else
a7812ae4 8824 gen_helper_0i(pmon, sa);
b48cfdff 8825#endif
7a387fff
TS
8826 break;
8827 case OPC_SYSCALL:
6af0bf9c 8828 generate_exception(ctx, EXCP_SYSCALL);
8e0f950d 8829 ctx->bstate = BS_STOP;
6af0bf9c 8830 break;
7a387fff 8831 case OPC_BREAK:
6af0bf9c
FB
8832 generate_exception(ctx, EXCP_BREAK);
8833 break;
b48cfdff
TS
8834 case OPC_SPIM:
8835#ifdef MIPS_STRICT_STANDARD
8836 MIPS_INVAL("SPIM");
8837 generate_exception(ctx, EXCP_RI);
8838#else
7a387fff
TS
8839 /* Implemented as RI exception for now. */
8840 MIPS_INVAL("spim (unofficial)");
8841 generate_exception(ctx, EXCP_RI);
b48cfdff 8842#endif
6af0bf9c 8843 break;
7a387fff 8844 case OPC_SYNC:
ead9360e 8845 /* Treat as NOP. */
6af0bf9c 8846 break;
4ad40f36 8847
7a387fff 8848 case OPC_MOVCI:
e189e748 8849 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
36d23958 8850 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 8851 check_cp1_enabled(ctx);
36d23958
TS
8852 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
8853 (ctx->opcode >> 16) & 1);
8854 } else {
e397ee33 8855 generate_exception_err(ctx, EXCP_CpU, 1);
36d23958 8856 }
4ad40f36
FB
8857 break;
8858
d26bc211 8859#if defined(TARGET_MIPS64)
7a387fff
TS
8860 /* MIPS64 specific opcodes */
8861 case OPC_DSLL:
324d9e32 8862 case OPC_DSRA:
7a387fff 8863 case OPC_DSLL32:
324d9e32 8864 case OPC_DSRA32:
e189e748
TS
8865 check_insn(env, ctx, ISA_MIPS3);
8866 check_mips_64(ctx);
324d9e32 8867 gen_shift_imm(env, ctx, op1, rd, rt, sa);
7a387fff 8868 break;
ea63e2c3
NF
8869 case OPC_DSRL:
8870 switch ((ctx->opcode >> 21) & 0x1f) {
8871 case 1:
8872 /* drotr is decoded as dsrl on non-R2 CPUs */
8873 if (env->insn_flags & ISA_MIPS32R2) {
8874 op1 = OPC_DROTR;
8875 }
8876 /* Fallthrough */
8877 case 0:
8878 check_insn(env, ctx, ISA_MIPS3);
8879 check_mips_64(ctx);
8880 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8881 break;
8882 default:
8883 generate_exception(ctx, EXCP_RI);
8884 break;
8885 }
8886 break;
8887 case OPC_DSRL32:
8888 switch ((ctx->opcode >> 21) & 0x1f) {
8889 case 1:
8890 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
8891 if (env->insn_flags & ISA_MIPS32R2) {
8892 op1 = OPC_DROTR32;
8893 }
8894 /* Fallthrough */
8895 case 0:
8896 check_insn(env, ctx, ISA_MIPS3);
8897 check_mips_64(ctx);
8898 gen_shift_imm(env, ctx, op1, rd, rt, sa);
8899 break;
8900 default:
8901 generate_exception(ctx, EXCP_RI);
8902 break;
8903 }
8904 break;
7a387fff 8905 case OPC_DADD ... OPC_DSUBU:
e189e748
TS
8906 check_insn(env, ctx, ISA_MIPS3);
8907 check_mips_64(ctx);
8908 gen_arith(env, ctx, op1, rd, rs, rt);
7a387fff 8909 break;
460f00c4
AJ
8910 case OPC_DSLLV:
8911 case OPC_DSRAV:
460f00c4
AJ
8912 check_insn(env, ctx, ISA_MIPS3);
8913 check_mips_64(ctx);
8914 gen_shift(env, ctx, op1, rd, rs, rt);
8915 break;
ea63e2c3
NF
8916 case OPC_DSRLV:
8917 switch ((ctx->opcode >> 6) & 0x1f) {
8918 case 1:
8919 /* drotrv is decoded as dsrlv on non-R2 CPUs */
8920 if (env->insn_flags & ISA_MIPS32R2) {
8921 op1 = OPC_DROTRV;
8922 }
8923 /* Fallthrough */
8924 case 0:
8925 check_insn(env, ctx, ISA_MIPS3);
8926 check_mips_64(ctx);
8927 gen_shift(env, ctx, op1, rd, rs, rt);
8928 break;
8929 default:
8930 generate_exception(ctx, EXCP_RI);
8931 break;
8932 }
8933 break;
7a387fff 8934 case OPC_DMULT ... OPC_DDIVU:
e189e748
TS
8935 check_insn(env, ctx, ISA_MIPS3);
8936 check_mips_64(ctx);
7a387fff
TS
8937 gen_muldiv(ctx, op1, rs, rt);
8938 break;
6af0bf9c
FB
8939#endif
8940 default: /* Invalid */
8941 MIPS_INVAL("special");
8942 generate_exception(ctx, EXCP_RI);
8943 break;
8944 }
8945 break;
7a387fff
TS
8946 case OPC_SPECIAL2:
8947 op1 = MASK_SPECIAL2(ctx->opcode);
6af0bf9c 8948 switch (op1) {
7a387fff
TS
8949 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
8950 case OPC_MSUB ... OPC_MSUBU:
e189e748 8951 check_insn(env, ctx, ISA_MIPS32);
7a387fff 8952 gen_muldiv(ctx, op1, rs, rt);
6af0bf9c 8953 break;
7a387fff 8954 case OPC_MUL:
e189e748 8955 gen_arith(env, ctx, op1, rd, rs, rt);
6af0bf9c 8956 break;
20e1fb52
AJ
8957 case OPC_CLO:
8958 case OPC_CLZ:
e189e748 8959 check_insn(env, ctx, ISA_MIPS32);
7a387fff 8960 gen_cl(ctx, op1, rd, rs);
6af0bf9c 8961 break;
7a387fff 8962 case OPC_SDBBP:
6af0bf9c
FB
8963 /* XXX: not clear which exception should be raised
8964 * when in debug mode...
8965 */
e189e748 8966 check_insn(env, ctx, ISA_MIPS32);
6af0bf9c
FB
8967 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8968 generate_exception(ctx, EXCP_DBp);
8969 } else {
8970 generate_exception(ctx, EXCP_DBp);
8971 }
ead9360e 8972 /* Treat as NOP. */
6af0bf9c 8973 break;
d26bc211 8974#if defined(TARGET_MIPS64)
20e1fb52
AJ
8975 case OPC_DCLO:
8976 case OPC_DCLZ:
e189e748
TS
8977 check_insn(env, ctx, ISA_MIPS64);
8978 check_mips_64(ctx);
7a387fff
TS
8979 gen_cl(ctx, op1, rd, rs);
8980 break;
8981#endif
6af0bf9c
FB
8982 default: /* Invalid */
8983 MIPS_INVAL("special2");
8984 generate_exception(ctx, EXCP_RI);
8985 break;
8986 }
8987 break;
7a387fff 8988 case OPC_SPECIAL3:
2b0233ab
TS
8989 op1 = MASK_SPECIAL3(ctx->opcode);
8990 switch (op1) {
8991 case OPC_EXT:
8992 case OPC_INS:
8993 check_insn(env, ctx, ISA_MIPS32R2);
8994 gen_bitops(ctx, op1, rt, rs, sa, rd);
8995 break;
8996 case OPC_BSHFL:
8997 check_insn(env, ctx, ISA_MIPS32R2);
8998 op2 = MASK_BSHFL(ctx->opcode);
49bcf33c 8999 gen_bshfl(ctx, op2, rt, rd);
7a387fff 9000 break;
1579a72e 9001 case OPC_RDHWR:
e189e748 9002 check_insn(env, ctx, ISA_MIPS32R2);
6c5c1e20 9003 {
35fbce2c 9004 TCGv t0 = tcg_temp_new();
6c5c1e20
TS
9005
9006 switch (rd) {
9007 case 0:
9008 save_cpu_state(ctx, 1);
a7812ae4 9009 gen_helper_rdhwr_cpunum(t0);
35fbce2c 9010 gen_store_gpr(t0, rt);
6c5c1e20
TS
9011 break;
9012 case 1:
9013 save_cpu_state(ctx, 1);
a7812ae4 9014 gen_helper_rdhwr_synci_step(t0);
35fbce2c 9015 gen_store_gpr(t0, rt);
6c5c1e20
TS
9016 break;
9017 case 2:
9018 save_cpu_state(ctx, 1);
a7812ae4 9019 gen_helper_rdhwr_cc(t0);
35fbce2c 9020 gen_store_gpr(t0, rt);
6c5c1e20
TS
9021 break;
9022 case 3:
9023 save_cpu_state(ctx, 1);
a7812ae4 9024 gen_helper_rdhwr_ccres(t0);
35fbce2c 9025 gen_store_gpr(t0, rt);
6c5c1e20
TS
9026 break;
9027 case 29:
932e71cd
AJ
9028#if defined(CONFIG_USER_ONLY)
9029 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
35fbce2c 9030 gen_store_gpr(t0, rt);
932e71cd
AJ
9031 break;
9032#else
9033 /* XXX: Some CPUs implement this in hardware.
9034 Not supported yet. */
9035#endif
6c5c1e20
TS
9036 default: /* Invalid */
9037 MIPS_INVAL("rdhwr");
9038 generate_exception(ctx, EXCP_RI);
9039 break;
9040 }
6c5c1e20 9041 tcg_temp_free(t0);
1579a72e 9042 }
1579a72e 9043 break;
ead9360e 9044 case OPC_FORK:
7385ac0b 9045 check_insn(env, ctx, ASE_MT);
6c5c1e20 9046 {
35fbce2c
AJ
9047 TCGv t0 = tcg_temp_new();
9048 TCGv t1 = tcg_temp_new();
6c5c1e20
TS
9049
9050 gen_load_gpr(t0, rt);
9051 gen_load_gpr(t1, rs);
a7812ae4 9052 gen_helper_fork(t0, t1);
6c5c1e20
TS
9053 tcg_temp_free(t0);
9054 tcg_temp_free(t1);
9055 }
ead9360e
TS
9056 break;
9057 case OPC_YIELD:
7385ac0b 9058 check_insn(env, ctx, ASE_MT);
6c5c1e20 9059 {
35fbce2c 9060 TCGv t0 = tcg_temp_new();
6c5c1e20 9061
35fbce2c 9062 save_cpu_state(ctx, 1);
6c5c1e20 9063 gen_load_gpr(t0, rs);
a7812ae4 9064 gen_helper_yield(t0, t0);
6c5c1e20
TS
9065 gen_store_gpr(t0, rd);
9066 tcg_temp_free(t0);
9067 }
ead9360e 9068 break;
d26bc211 9069#if defined(TARGET_MIPS64)
1579a72e
TS
9070 case OPC_DEXTM ... OPC_DEXT:
9071 case OPC_DINSM ... OPC_DINS:
e189e748
TS
9072 check_insn(env, ctx, ISA_MIPS64R2);
9073 check_mips_64(ctx);
1579a72e 9074 gen_bitops(ctx, op1, rt, rs, sa, rd);
7a387fff 9075 break;
1579a72e 9076 case OPC_DBSHFL:
e189e748
TS
9077 check_insn(env, ctx, ISA_MIPS64R2);
9078 check_mips_64(ctx);
1579a72e 9079 op2 = MASK_DBSHFL(ctx->opcode);
49bcf33c 9080 gen_bshfl(ctx, op2, rt, rd);
c6d6dd7c 9081 break;
7a387fff
TS
9082#endif
9083 default: /* Invalid */
9084 MIPS_INVAL("special3");
9085 generate_exception(ctx, EXCP_RI);
9086 break;
9087 }
9088 break;
9089 case OPC_REGIMM:
9090 op1 = MASK_REGIMM(ctx->opcode);
9091 switch (op1) {
9092 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
9093 case OPC_BLTZAL ... OPC_BGEZALL:
7dca4ad0 9094 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
c9602061
NF
9095 *is_branch = 1;
9096 break;
7a387fff
TS
9097 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
9098 case OPC_TNEI:
9099 gen_trap(ctx, op1, rs, -1, imm);
9100 break;
9101 case OPC_SYNCI:
e189e748 9102 check_insn(env, ctx, ISA_MIPS32R2);
ead9360e 9103 /* Treat as NOP. */
6af0bf9c
FB
9104 break;
9105 default: /* Invalid */
923617a3 9106 MIPS_INVAL("regimm");
6af0bf9c
FB
9107 generate_exception(ctx, EXCP_RI);
9108 break;
9109 }
9110 break;
7a387fff 9111 case OPC_CP0:
387a8fe5 9112 check_cp0_enabled(ctx);
7a387fff 9113 op1 = MASK_CP0(ctx->opcode);
6af0bf9c 9114 switch (op1) {
7a387fff
TS
9115 case OPC_MFC0:
9116 case OPC_MTC0:
ead9360e
TS
9117 case OPC_MFTR:
9118 case OPC_MTTR:
d26bc211 9119#if defined(TARGET_MIPS64)
7a387fff
TS
9120 case OPC_DMFC0:
9121 case OPC_DMTC0:
9122#endif
f1aa6320 9123#ifndef CONFIG_USER_ONLY
932e71cd 9124 gen_cp0(env, ctx, op1, rt, rd);
0eaef5aa 9125#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
9126 break;
9127 case OPC_C0_FIRST ... OPC_C0_LAST:
f1aa6320 9128#ifndef CONFIG_USER_ONLY
932e71cd 9129 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
0eaef5aa 9130#endif /* !CONFIG_USER_ONLY */
7a387fff
TS
9131 break;
9132 case OPC_MFMC0:
8706c382 9133#ifndef CONFIG_USER_ONLY
932e71cd 9134 {
35fbce2c 9135 TCGv t0 = tcg_temp_new();
6c5c1e20 9136
0eaef5aa 9137 op2 = MASK_MFMC0(ctx->opcode);
6c5c1e20
TS
9138 switch (op2) {
9139 case OPC_DMT:
9140 check_insn(env, ctx, ASE_MT);
a7812ae4 9141 gen_helper_dmt(t0, t0);
35fbce2c 9142 gen_store_gpr(t0, rt);
6c5c1e20
TS
9143 break;
9144 case OPC_EMT:
9145 check_insn(env, ctx, ASE_MT);
a7812ae4 9146 gen_helper_emt(t0, t0);
35fbce2c 9147 gen_store_gpr(t0, rt);
da80682b 9148 break;
6c5c1e20
TS
9149 case OPC_DVPE:
9150 check_insn(env, ctx, ASE_MT);
a7812ae4 9151 gen_helper_dvpe(t0, t0);
35fbce2c 9152 gen_store_gpr(t0, rt);
6c5c1e20
TS
9153 break;
9154 case OPC_EVPE:
9155 check_insn(env, ctx, ASE_MT);
a7812ae4 9156 gen_helper_evpe(t0, t0);
35fbce2c 9157 gen_store_gpr(t0, rt);
6c5c1e20
TS
9158 break;
9159 case OPC_DI:
9160 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 9161 save_cpu_state(ctx, 1);
a7812ae4 9162 gen_helper_di(t0);
35fbce2c 9163 gen_store_gpr(t0, rt);
6c5c1e20
TS
9164 /* Stop translation as we may have switched the execution mode */
9165 ctx->bstate = BS_STOP;
9166 break;
9167 case OPC_EI:
9168 check_insn(env, ctx, ISA_MIPS32R2);
867abc7e 9169 save_cpu_state(ctx, 1);
a7812ae4 9170 gen_helper_ei(t0);
35fbce2c 9171 gen_store_gpr(t0, rt);
6c5c1e20
TS
9172 /* Stop translation as we may have switched the execution mode */
9173 ctx->bstate = BS_STOP;
9174 break;
9175 default: /* Invalid */
9176 MIPS_INVAL("mfmc0");
9177 generate_exception(ctx, EXCP_RI);
9178 break;
9179 }
6c5c1e20 9180 tcg_temp_free(t0);
7a387fff 9181 }
0eaef5aa 9182#endif /* !CONFIG_USER_ONLY */
6af0bf9c 9183 break;
7a387fff 9184 case OPC_RDPGPR:
e189e748 9185 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 9186 gen_load_srsgpr(rt, rd);
ead9360e 9187 break;
7a387fff 9188 case OPC_WRPGPR:
e189e748 9189 check_insn(env, ctx, ISA_MIPS32R2);
be24bb4f 9190 gen_store_srsgpr(rt, rd);
38121543 9191 break;
6af0bf9c 9192 default:
923617a3 9193 MIPS_INVAL("cp0");
7a387fff 9194 generate_exception(ctx, EXCP_RI);
6af0bf9c
FB
9195 break;
9196 }
9197 break;
324d9e32
AJ
9198 case OPC_ADDI: /* Arithmetic with immediate opcode */
9199 case OPC_ADDIU:
e189e748 9200 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 9201 break;
324d9e32
AJ
9202 case OPC_SLTI: /* Set on less than with immediate opcode */
9203 case OPC_SLTIU:
9204 gen_slt_imm(env, op, rt, rs, imm);
9205 break;
9206 case OPC_ANDI: /* Arithmetic with immediate opcode */
9207 case OPC_LUI:
9208 case OPC_ORI:
9209 case OPC_XORI:
9210 gen_logic_imm(env, op, rt, rs, imm);
9211 break;
7a387fff
TS
9212 case OPC_J ... OPC_JAL: /* Jump */
9213 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
7dca4ad0 9214 gen_compute_branch(ctx, op, 4, rs, rt, offset);
c9602061
NF
9215 *is_branch = 1;
9216 break;
7a387fff
TS
9217 case OPC_BEQ ... OPC_BGTZ: /* Branch */
9218 case OPC_BEQL ... OPC_BGTZL:
7dca4ad0 9219 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
c9602061
NF
9220 *is_branch = 1;
9221 break;
7a387fff
TS
9222 case OPC_LB ... OPC_LWR: /* Load and stores */
9223 case OPC_SB ... OPC_SW:
9224 case OPC_SWR:
9225 case OPC_LL:
7a387fff
TS
9226 gen_ldst(ctx, op, rt, rs, imm);
9227 break;
d66c7132
AJ
9228 case OPC_SC:
9229 gen_st_cond(ctx, op, rt, rs, imm);
9230 break;
7a387fff 9231 case OPC_CACHE:
e189e748 9232 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
ead9360e 9233 /* Treat as NOP. */
34ae7b51 9234 break;
7a387fff 9235 case OPC_PREF:
e189e748 9236 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
ead9360e 9237 /* Treat as NOP. */
6af0bf9c 9238 break;
4ad40f36 9239
923617a3 9240 /* Floating point (COP1). */
7a387fff
TS
9241 case OPC_LWC1:
9242 case OPC_LDC1:
9243 case OPC_SWC1:
9244 case OPC_SDC1:
36d23958 9245 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 9246 check_cp1_enabled(ctx);
36d23958
TS
9247 gen_flt_ldst(ctx, op, rt, rs, imm);
9248 } else {
9249 generate_exception_err(ctx, EXCP_CpU, 1);
9250 }
6ea83fed
FB
9251 break;
9252
7a387fff 9253 case OPC_CP1:
36d23958 9254 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 9255 check_cp1_enabled(ctx);
36d23958
TS
9256 op1 = MASK_CP1(ctx->opcode);
9257 switch (op1) {
3a95e3a7
TS
9258 case OPC_MFHC1:
9259 case OPC_MTHC1:
e189e748 9260 check_insn(env, ctx, ISA_MIPS32R2);
36d23958
TS
9261 case OPC_MFC1:
9262 case OPC_CFC1:
9263 case OPC_MTC1:
9264 case OPC_CTC1:
e189e748
TS
9265 gen_cp1(ctx, op1, rt, rd);
9266 break;
d26bc211 9267#if defined(TARGET_MIPS64)
36d23958
TS
9268 case OPC_DMFC1:
9269 case OPC_DMTC1:
e189e748 9270 check_insn(env, ctx, ISA_MIPS3);
36d23958
TS
9271 gen_cp1(ctx, op1, rt, rd);
9272 break;
e189e748 9273#endif
fbcc6828
TS
9274 case OPC_BC1ANY2:
9275 case OPC_BC1ANY4:
b8aa4598 9276 check_cop1x(ctx);
7385ac0b 9277 check_insn(env, ctx, ASE_MIPS3D);
d8a5950a
TS
9278 /* fall through */
9279 case OPC_BC1:
e189e748 9280 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
5a5012ec 9281 (rt >> 2) & 0x7, imm << 2);
c9602061
NF
9282 *is_branch = 1;
9283 break;
36d23958
TS
9284 case OPC_S_FMT:
9285 case OPC_D_FMT:
9286 case OPC_W_FMT:
9287 case OPC_L_FMT:
5a5012ec
TS
9288 case OPC_PS_FMT:
9289 gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
9290 (imm >> 8) & 0x7);
36d23958
TS
9291 break;
9292 default:
923617a3 9293 MIPS_INVAL("cp1");
e397ee33 9294 generate_exception (ctx, EXCP_RI);
36d23958
TS
9295 break;
9296 }
9297 } else {
9298 generate_exception_err(ctx, EXCP_CpU, 1);
6ea83fed 9299 }
4ad40f36
FB
9300 break;
9301
9302 /* COP2. */
7a387fff
TS
9303 case OPC_LWC2:
9304 case OPC_LDC2:
9305 case OPC_SWC2:
9306 case OPC_SDC2:
9307 case OPC_CP2:
9308 /* COP2: Not implemented. */
4ad40f36
FB
9309 generate_exception_err(ctx, EXCP_CpU, 2);
9310 break;
9311
7a387fff 9312 case OPC_CP3:
36d23958 9313 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
5e755519 9314 check_cp1_enabled(ctx);
36d23958
TS
9315 op1 = MASK_CP3(ctx->opcode);
9316 switch (op1) {
5a5012ec
TS
9317 case OPC_LWXC1:
9318 case OPC_LDXC1:
9319 case OPC_LUXC1:
9320 case OPC_SWXC1:
9321 case OPC_SDXC1:
9322 case OPC_SUXC1:
93b12ccc 9323 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
5a5012ec 9324 break;
e0c84da7 9325 case OPC_PREFX:
ead9360e 9326 /* Treat as NOP. */
e0c84da7 9327 break;
5a5012ec
TS
9328 case OPC_ALNV_PS:
9329 case OPC_MADD_S:
9330 case OPC_MADD_D:
9331 case OPC_MADD_PS:
9332 case OPC_MSUB_S:
9333 case OPC_MSUB_D:
9334 case OPC_MSUB_PS:
9335 case OPC_NMADD_S:
9336 case OPC_NMADD_D:
9337 case OPC_NMADD_PS:
9338 case OPC_NMSUB_S:
9339 case OPC_NMSUB_D:
9340 case OPC_NMSUB_PS:
9341 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
9342 break;
36d23958 9343 default:
923617a3 9344 MIPS_INVAL("cp3");
e397ee33 9345 generate_exception (ctx, EXCP_RI);
36d23958
TS
9346 break;
9347 }
9348 } else {
e397ee33 9349 generate_exception_err(ctx, EXCP_CpU, 1);
7a387fff 9350 }
4ad40f36
FB
9351 break;
9352
d26bc211 9353#if defined(TARGET_MIPS64)
7a387fff
TS
9354 /* MIPS64 opcodes */
9355 case OPC_LWU:
9356 case OPC_LDL ... OPC_LDR:
9357 case OPC_SDL ... OPC_SDR:
9358 case OPC_LLD:
9359 case OPC_LD:
7a387fff 9360 case OPC_SD:
e189e748
TS
9361 check_insn(env, ctx, ISA_MIPS3);
9362 check_mips_64(ctx);
7a387fff
TS
9363 gen_ldst(ctx, op, rt, rs, imm);
9364 break;
d66c7132
AJ
9365 case OPC_SCD:
9366 check_insn(env, ctx, ISA_MIPS3);
9367 check_mips_64(ctx);
9368 gen_st_cond(ctx, op, rt, rs, imm);
9369 break;
324d9e32
AJ
9370 case OPC_DADDI:
9371 case OPC_DADDIU:
e189e748
TS
9372 check_insn(env, ctx, ISA_MIPS3);
9373 check_mips_64(ctx);
9374 gen_arith_imm(env, ctx, op, rt, rs, imm);
7a387fff 9375 break;
6af0bf9c 9376#endif
7a387fff 9377 case OPC_JALX:
e189e748 9378 check_insn(env, ctx, ASE_MIPS16);
364d4831
NF
9379 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
9380 gen_compute_branch(ctx, op, 4, rs, rt, offset);
9381 *is_branch = 1;
9382 break;
7a387fff 9383 case OPC_MDMX:
e189e748 9384 check_insn(env, ctx, ASE_MDMX);
7a387fff 9385 /* MDMX: Not implemented. */
6af0bf9c 9386 default: /* Invalid */
923617a3 9387 MIPS_INVAL("major opcode");
6af0bf9c
FB
9388 generate_exception(ctx, EXCP_RI);
9389 break;
9390 }
6af0bf9c
FB
9391}
9392
2cfc5f17 9393static inline void
820e00f2
TS
9394gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
9395 int search_pc)
6af0bf9c 9396{
278d0702 9397 DisasContext ctx;
6af0bf9c
FB
9398 target_ulong pc_start;
9399 uint16_t *gen_opc_end;
a1d1bb31 9400 CPUBreakpoint *bp;
6af0bf9c 9401 int j, lj = -1;
2e70f6ef
PB
9402 int num_insns;
9403 int max_insns;
c9602061
NF
9404 int insn_bytes;
9405 int is_branch;
6af0bf9c 9406
93fcfe39
AL
9407 if (search_pc)
9408 qemu_log("search pc %d\n", search_pc);
4ad40f36 9409
6af0bf9c 9410 pc_start = tb->pc;
d42320c2 9411 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6af0bf9c 9412 ctx.pc = pc_start;
4ad40f36 9413 ctx.saved_pc = -1;
7b270ef2 9414 ctx.singlestep_enabled = env->singlestep_enabled;
6af0bf9c
FB
9415 ctx.tb = tb;
9416 ctx.bstate = BS_NONE;
4ad40f36 9417 /* Restore delay slot state from the tb context. */
c068688b 9418 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
fd4a04eb 9419 restore_cpu_state(env, &ctx);
932e71cd 9420#ifdef CONFIG_USER_ONLY
0eaef5aa 9421 ctx.mem_idx = MIPS_HFLAG_UM;
932e71cd 9422#else
0eaef5aa 9423 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
932e71cd 9424#endif
2e70f6ef
PB
9425 num_insns = 0;
9426 max_insns = tb->cflags & CF_COUNT_MASK;
9427 if (max_insns == 0)
9428 max_insns = CF_COUNT_MASK;
6af0bf9c 9429#ifdef DEBUG_DISAS
93fcfe39
AL
9430 qemu_log_mask(CPU_LOG_TB_CPU, "------------------------------------------------\n");
9431 /* FIXME: This may print out stale hflags from env... */
9432 log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
6af0bf9c 9433#endif
d12d51d5 9434 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
2e70f6ef 9435 gen_icount_start();
faf7aaa9 9436 while (ctx.bstate == BS_NONE) {
72cf2d4f
BS
9437 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
9438 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 9439 if (bp->pc == ctx.pc) {
278d0702 9440 save_cpu_state(&ctx, 1);
4ad40f36 9441 ctx.bstate = BS_BRANCH;
a7812ae4 9442 gen_helper_0i(raise_exception, EXCP_DEBUG);
ce62e5ba
TS
9443 /* Include the breakpoint location or the tb won't
9444 * be flushed when it must be. */
9445 ctx.pc += 4;
4ad40f36
FB
9446 goto done_generating;
9447 }
9448 }
9449 }
9450
6af0bf9c
FB
9451 if (search_pc) {
9452 j = gen_opc_ptr - gen_opc_buf;
6af0bf9c
FB
9453 if (lj < j) {
9454 lj++;
9455 while (lj < j)
9456 gen_opc_instr_start[lj++] = 0;
6af0bf9c 9457 }
4ad40f36
FB
9458 gen_opc_pc[lj] = ctx.pc;
9459 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
9460 gen_opc_instr_start[lj] = 1;
2e70f6ef 9461 gen_opc_icount[lj] = num_insns;
6af0bf9c 9462 }
2e70f6ef
PB
9463 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
9464 gen_io_start();
c9602061
NF
9465
9466 is_branch = 0;
364d4831 9467 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
c9602061
NF
9468 ctx.opcode = ldl_code(ctx.pc);
9469 insn_bytes = 4;
9470 decode_opc(env, &ctx, &is_branch);
364d4831
NF
9471 } else if (env->insn_flags & ASE_MIPS16) {
9472 ctx.opcode = lduw_code(ctx.pc);
9473 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
c9602061
NF
9474 } else {
9475 generate_exception(&ctx, EXCP_RI);
9476 break;
9477 }
9478 if (!is_branch) {
9479 handle_delay_slot(env, &ctx, insn_bytes);
9480 }
9481 ctx.pc += insn_bytes;
9482
2e70f6ef 9483 num_insns++;
4ad40f36 9484
7b270ef2
NF
9485 /* Execute a branch and its delay slot as a single instruction.
9486 This is what GDB expects and is consistent with what the
9487 hardware does (e.g. if a delay slot instruction faults, the
9488 reported PC is the PC of the branch). */
9489 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
4ad40f36
FB
9490 break;
9491
6af0bf9c
FB
9492 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
9493 break;
4ad40f36 9494
faf7aaa9
TS
9495 if (gen_opc_ptr >= gen_opc_end)
9496 break;
9497
2e70f6ef
PB
9498 if (num_insns >= max_insns)
9499 break;
1b530a6d
AJ
9500
9501 if (singlestep)
9502 break;
6af0bf9c 9503 }
2e70f6ef
PB
9504 if (tb->cflags & CF_LAST_IO)
9505 gen_io_end();
7b270ef2 9506 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
278d0702 9507 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
a7812ae4 9508 gen_helper_0i(raise_exception, EXCP_DEBUG);
16c00cb2 9509 } else {
6958549d 9510 switch (ctx.bstate) {
16c00cb2 9511 case BS_STOP:
a7812ae4 9512 gen_helper_interrupt_restart();
df1561e2
TS
9513 gen_goto_tb(&ctx, 0, ctx.pc);
9514 break;
16c00cb2 9515 case BS_NONE:
278d0702 9516 save_cpu_state(&ctx, 0);
16c00cb2
TS
9517 gen_goto_tb(&ctx, 0, ctx.pc);
9518 break;
5a5012ec 9519 case BS_EXCP:
a7812ae4 9520 gen_helper_interrupt_restart();
57fec1fe 9521 tcg_gen_exit_tb(0);
16c00cb2 9522 break;
5a5012ec
TS
9523 case BS_BRANCH:
9524 default:
9525 break;
6958549d 9526 }
6af0bf9c 9527 }
4ad40f36 9528done_generating:
2e70f6ef 9529 gen_icount_end(tb, num_insns);
6af0bf9c
FB
9530 *gen_opc_ptr = INDEX_op_end;
9531 if (search_pc) {
9532 j = gen_opc_ptr - gen_opc_buf;
9533 lj++;
9534 while (lj <= j)
9535 gen_opc_instr_start[lj++] = 0;
6af0bf9c
FB
9536 } else {
9537 tb->size = ctx.pc - pc_start;
2e70f6ef 9538 tb->icount = num_insns;
6af0bf9c
FB
9539 }
9540#ifdef DEBUG_DISAS
d12d51d5 9541 LOG_DISAS("\n");
8fec2b8c 9542 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
93fcfe39
AL
9543 qemu_log("IN: %s\n", lookup_symbol(pc_start));
9544 log_target_disas(pc_start, ctx.pc - pc_start, 0);
9545 qemu_log("\n");
6af0bf9c 9546 }
93fcfe39 9547 qemu_log_mask(CPU_LOG_TB_CPU, "---------------- %d %08x\n", ctx.bstate, ctx.hflags);
6af0bf9c 9548#endif
6af0bf9c
FB
9549}
9550
2cfc5f17 9551void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 9552{
2cfc5f17 9553 gen_intermediate_code_internal(env, tb, 0);
6af0bf9c
FB
9554}
9555
2cfc5f17 9556void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6af0bf9c 9557{
2cfc5f17 9558 gen_intermediate_code_internal(env, tb, 1);
6af0bf9c
FB
9559}
9560
8706c382
TS
9561static void fpu_dump_state(CPUState *env, FILE *f,
9562 int (*fpu_fprintf)(FILE *f, const char *fmt, ...),
9563 int flags)
6ea83fed
FB
9564{
9565 int i;
5e755519 9566 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
5a5012ec 9567
2a5612e6
SW
9568#define printfpr(fp) \
9569 do { \
9570 if (is_fpu64) \
9571 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9572 " fd:%13g fs:%13g psu: %13g\n", \
9573 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
9574 (double)(fp)->fd, \
9575 (double)(fp)->fs[FP_ENDIAN_IDX], \
9576 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
9577 else { \
9578 fpr_t tmp; \
9579 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
9580 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
9581 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
9582 " fd:%13g fs:%13g psu:%13g\n", \
9583 tmp.w[FP_ENDIAN_IDX], tmp.d, \
9584 (double)tmp.fd, \
9585 (double)tmp.fs[FP_ENDIAN_IDX], \
9586 (double)tmp.fs[!FP_ENDIAN_IDX]); \
9587 } \
6ea83fed
FB
9588 } while(0)
9589
5a5012ec
TS
9590
9591 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%08x(0x%02x)\n",
f01be154
TS
9592 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64, env->active_fpu.fp_status,
9593 get_float_exception_flags(&env->active_fpu.fp_status));
5a5012ec
TS
9594 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
9595 fpu_fprintf(f, "%3s: ", fregnames[i]);
f01be154 9596 printfpr(&env->active_fpu.fpr[i]);
6ea83fed
FB
9597 }
9598
9599#undef printfpr
9600}
9601
d26bc211 9602#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16 9603/* Debug help: The architecture requires 32bit code to maintain proper
c7e8a937 9604 sign-extended values on 64bit machines. */
c570fd16
TS
9605
9606#define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
9607
8706c382
TS
9608static void
9609cpu_mips_check_sign_extensions (CPUState *env, FILE *f,
9610 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9611 int flags)
c570fd16
TS
9612{
9613 int i;
9614
b5dc7732
TS
9615 if (!SIGN_EXT_P(env->active_tc.PC))
9616 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
9617 if (!SIGN_EXT_P(env->active_tc.HI[0]))
9618 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
9619 if (!SIGN_EXT_P(env->active_tc.LO[0]))
9620 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
c570fd16 9621 if (!SIGN_EXT_P(env->btarget))
3594c774 9622 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
c570fd16
TS
9623
9624 for (i = 0; i < 32; i++) {
b5dc7732
TS
9625 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
9626 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
c570fd16
TS
9627 }
9628
9629 if (!SIGN_EXT_P(env->CP0_EPC))
3594c774 9630 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
5499b6ff
AJ
9631 if (!SIGN_EXT_P(env->lladdr))
9632 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
c570fd16
TS
9633}
9634#endif
9635
5fafdf24 9636void cpu_dump_state (CPUState *env, FILE *f,
6af0bf9c
FB
9637 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
9638 int flags)
9639{
9640 int i;
3b46e624 9641
a7200c9f
SW
9642 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
9643 " LO=0x" TARGET_FMT_lx " ds %04x "
9644 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
3d5be870
TS
9645 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
9646 env->hflags, env->btarget, env->bcond);
6af0bf9c
FB
9647 for (i = 0; i < 32; i++) {
9648 if ((i & 3) == 0)
9649 cpu_fprintf(f, "GPR%02d:", i);
b5dc7732 9650 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
6af0bf9c
FB
9651 if ((i & 3) == 3)
9652 cpu_fprintf(f, "\n");
9653 }
568b600d 9654
3594c774 9655 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
5e755519 9656 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
3594c774 9657 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
5499b6ff 9658 env->CP0_Config0, env->CP0_Config1, env->lladdr);
5e755519 9659 if (env->hflags & MIPS_HFLAG_FPU)
7a387fff 9660 fpu_dump_state(env, f, cpu_fprintf, flags);
d26bc211 9661#if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
c570fd16
TS
9662 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
9663#endif
6af0bf9c
FB
9664}
9665
39454628
TS
9666static void mips_tcg_init(void)
9667{
f01be154 9668 int i;
39454628
TS
9669 static int inited;
9670
9671 /* Initialize various static tables. */
9672 if (inited)
6958549d 9673 return;
39454628 9674
a7812ae4 9675 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
f2c94b92 9676 TCGV_UNUSED(cpu_gpr[0]);
bb928dbe 9677 for (i = 1; i < 32; i++)
a7812ae4 9678 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9679 offsetof(CPUState, active_tc.gpr[i]),
9680 regnames[i]);
a7812ae4 9681 cpu_PC = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9682 offsetof(CPUState, active_tc.PC), "PC");
9683 for (i = 0; i < MIPS_DSP_ACC; i++) {
a7812ae4 9684 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9685 offsetof(CPUState, active_tc.HI[i]),
9686 regnames_HI[i]);
a7812ae4 9687 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9688 offsetof(CPUState, active_tc.LO[i]),
9689 regnames_LO[i]);
a7812ae4 9690 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9691 offsetof(CPUState, active_tc.ACX[i]),
9692 regnames_ACX[i]);
9693 }
a7812ae4 9694 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
4b2eb8d2
TS
9695 offsetof(CPUState, active_tc.DSPControl),
9696 "DSPControl");
1ba74fb8
AJ
9697 bcond = tcg_global_mem_new(TCG_AREG0,
9698 offsetof(CPUState, bcond), "bcond");
a7812ae4 9699 btarget = tcg_global_mem_new(TCG_AREG0,
d077b6f7 9700 offsetof(CPUState, btarget), "btarget");
41db4607
AJ
9701 hflags = tcg_global_mem_new_i32(TCG_AREG0,
9702 offsetof(CPUState, hflags), "hflags");
9703
a7812ae4
PB
9704 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
9705 offsetof(CPUState, active_fpu.fcr0),
9706 "fcr0");
9707 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
9708 offsetof(CPUState, active_fpu.fcr31),
9709 "fcr31");
39454628 9710
7dd9e556 9711 /* register helpers */
a7812ae4 9712#define GEN_HELPER 2
7dd9e556
TS
9713#include "helper.h"
9714
39454628
TS
9715 inited = 1;
9716}
9717
aaed909a
FB
9718#include "translate_init.c"
9719
9720CPUMIPSState *cpu_mips_init (const char *cpu_model)
6af0bf9c
FB
9721{
9722 CPUMIPSState *env;
c227f099 9723 const mips_def_t *def;
6af0bf9c 9724
aaed909a
FB
9725 def = cpu_mips_find_by_name(cpu_model);
9726 if (!def)
9727 return NULL;
6af0bf9c 9728 env = qemu_mallocz(sizeof(CPUMIPSState));
aaed909a 9729 env->cpu_model = def;
51cc2e78 9730 env->cpu_model_str = cpu_model;
aaed909a 9731
173d6cfe 9732 cpu_exec_init(env);
51cc2e78
BS
9733#ifndef CONFIG_USER_ONLY
9734 mmu_init(env, def);
9735#endif
9736 fpu_init(env, def);
9737 mvp_init(env, def);
39454628 9738 mips_tcg_init();
6ae81775 9739 cpu_reset(env);
0bf46a40 9740 qemu_init_vcpu(env);
6ae81775
TS
9741 return env;
9742}
9743
9744void cpu_reset (CPUMIPSState *env)
9745{
eca1bdf4
AL
9746 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
9747 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
9748 log_cpu_state(env, 0);
9749 }
9750
6ae81775 9751 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
6af0bf9c 9752 tlb_flush(env, 1);
6ae81775 9753
51cc2e78
BS
9754 /* Reset registers to their default values */
9755 env->CP0_PRid = env->cpu_model->CP0_PRid;
9756 env->CP0_Config0 = env->cpu_model->CP0_Config0;
9757#ifdef TARGET_WORDS_BIGENDIAN
9758 env->CP0_Config0 |= (1 << CP0C0_BE);
9759#endif
9760 env->CP0_Config1 = env->cpu_model->CP0_Config1;
9761 env->CP0_Config2 = env->cpu_model->CP0_Config2;
9762 env->CP0_Config3 = env->cpu_model->CP0_Config3;
9763 env->CP0_Config6 = env->cpu_model->CP0_Config6;
9764 env->CP0_Config7 = env->cpu_model->CP0_Config7;
2a6e32dd
AJ
9765 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
9766 << env->cpu_model->CP0_LLAddr_shift;
9767 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
51cc2e78
BS
9768 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
9769 env->CCRes = env->cpu_model->CCRes;
9770 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
9771 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
9772 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
9773 env->current_tc = 0;
9774 env->SEGBITS = env->cpu_model->SEGBITS;
9775 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
9776#if defined(TARGET_MIPS64)
9777 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9778 env->SEGMask |= 3ULL << 62;
9779 }
9780#endif
9781 env->PABITS = env->cpu_model->PABITS;
9782 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
9783 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
9784 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
9785 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
9786 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
9787 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
9788 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
9789 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
9790 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
9791 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
9792 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
9793 env->insn_flags = env->cpu_model->insn_flags;
9794
0eaef5aa 9795#if defined(CONFIG_USER_ONLY)
932e71cd 9796 env->hflags = MIPS_HFLAG_UM;
df357f0e
PB
9797 /* Enable access to the SYNCI_Step register. */
9798 env->CP0_HWREna |= (1 << 1);
91a75935
NF
9799 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
9800 env->hflags |= MIPS_HFLAG_FPU;
9801 }
9802#ifdef TARGET_MIPS64
9803 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
9804 env->hflags |= MIPS_HFLAG_F64;
9805 }
9806#endif
932e71cd
AJ
9807#else
9808 if (env->hflags & MIPS_HFLAG_BMASK) {
9809 /* If the exception was raised from a delay slot,
9810 come back to the jump. */
9811 env->CP0_ErrorEPC = env->active_tc.PC - 4;
aa328add 9812 } else {
932e71cd
AJ
9813 env->CP0_ErrorEPC = env->active_tc.PC;
9814 }
9815 env->active_tc.PC = (int32_t)0xBFC00000;
51cc2e78
BS
9816 env->CP0_Random = env->tlb->nb_tlb - 1;
9817 env->tlb->tlb_in_use = env->tlb->nb_tlb;
932e71cd
AJ
9818 env->CP0_Wired = 0;
9819 /* SMP not implemented */
9820 env->CP0_EBase = 0x80000000;
9821 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
9822 /* vectored interrupts not implemented, timer on int 7,
9823 no performance counters. */
9824 env->CP0_IntCtl = 0xe0000000;
9825 {
9826 int i;
9827
9828 for (i = 0; i < 7; i++) {
9829 env->CP0_WatchLo[i] = 0;
9830 env->CP0_WatchHi[i] = 0x80000000;
fd88b6ab 9831 }
932e71cd
AJ
9832 env->CP0_WatchLo[7] = 0;
9833 env->CP0_WatchHi[7] = 0;
fd88b6ab 9834 }
932e71cd
AJ
9835 /* Count register increments in debug mode, EJTAG version 1 */
9836 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
9837 env->hflags = MIPS_HFLAG_CP0;
51cc2e78
BS
9838#endif
9839#if defined(TARGET_MIPS64)
9840 if (env->cpu_model->insn_flags & ISA_MIPS3) {
9841 env->hflags |= MIPS_HFLAG_64;
9842 }
932e71cd 9843#endif
6af0bf9c 9844 env->exception_index = EXCP_NONE;
6af0bf9c 9845}
d2856f1a
AJ
9846
9847void gen_pc_load(CPUState *env, TranslationBlock *tb,
9848 unsigned long searched_pc, int pc_pos, void *puc)
9849{
b5dc7732 9850 env->active_tc.PC = gen_opc_pc[pc_pos];
d2856f1a
AJ
9851 env->hflags &= ~MIPS_HFLAG_BMASK;
9852 env->hflags |= gen_opc_hflags[pc_pos];
9853}