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