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