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